Skip to content

Commit

Permalink
Refactor .match() to ditch use of eval() & remain case-insensitive.
Browse files Browse the repository at this point in the history
  • Loading branch information
jathanism committed Jan 28, 2016
1 parent 3b2f317 commit 92ef037
Showing 1 changed file with 26 additions and 10 deletions.
36 changes: 26 additions & 10 deletions trigger/netdevices/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -916,16 +916,32 @@ def match(self, **kwargs):
:returns: List of NetDevice objects
"""
# Here we build a list comprehension and then eval it at the end.
query_prefix = "[dev for dev in self.all() if "
query_suffix = "]"
template = "%r.lower() in getattr(dev, %r, '').lower()"
list_body = ' and '.join(
template % (v, k.lower()) for k, v in kwargs.iteritems()
)
list_comp = query_prefix + list_body + query_suffix

return eval(list_comp)
all_field_names = getattr(self, '_all_field_names', {})

# Cache the field names the first time .match() is called.
if not all_field_names:
# Merge in field_names from every NetDevice
for dev in self.all():
dev_fields = ((f.lower(), f) for f in dev.__dict__)
all_field_names.update(dev_fields)
self._all_field_names = all_field_names

# An iterator so we can filtering functionally
devices = iter(self.all())

def map_attr(attr):
"""Helper function for the lower-to-regular attribute mapping."""
return self._all_field_names[attr.lower()]

# Use generators to keep filtering the iterator of devices.
for attr, val in kwargs.iteritems():
attr = map_attr(attr)
val = val.lower()
devices = (
d for d in devices if val in getattr(d, attr, '').lower()
)

return list(devices)

def get_devices_by_type(self, devtype):
"""
Expand Down

0 comments on commit 92ef037

Please sign in to comment.