Skip to content

fix(attrmatch): use None to match missing attributes #643

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/taskgraph/util/attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ def attrmatch(attributes, **kwargs):
* Given a set or list, the attribute value must be contained within it.
* A callable is called with the attribute value and returns a boolean.

If an attribute is specified as a keyword argument but not present in the
task's attributes, the result is False.
Attributes that are not defined in a task are considered to have a value of
None. Therefore to match tasks that *don't* have an attribute, you can use:

{ "attr_name": None }

Args:
attributes (dict): The task's attributes object.
Expand All @@ -27,16 +29,14 @@ def attrmatch(attributes, **kwargs):
bool: Whether the task's attributes match the conditions or not.
"""
for kwkey, kwval in kwargs.items():
if kwkey not in attributes:
return False
attval = attributes[kwkey]
attval = attributes.get(kwkey)
if isinstance(kwval, (set, list)):
if attval not in kwval:
return False
elif callable(kwval):
if not kwval(attval):
return False
elif kwval != attributes[kwkey]:
elif kwval != attval:
return False
return True

Expand Down
9 changes: 7 additions & 2 deletions test/test_util_attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,13 @@ def test_trivial_match(self):
self.assertTrue(attrmatch({}))

def test_missing_attribute(self):
"""If a filtering attribute is not present, no match"""
self.assertFalse(attrmatch({}, someattr=10))
"""If a filtering attribute is not present, no match unless it is
None"""
self.assertFalse(attrmatch({"a": 1}, a=1, b=2))
self.assertTrue(attrmatch({"a": 1}, a=1, b=None))
self.assertTrue(attrmatch({"a": 1, "b": None}, a=1, b=None))
self.assertTrue(attrmatch({"a": 1}, a=1, b=[None, 2]))
self.assertTrue(attrmatch({"a": 1, "b": 2}, a=1, b=[None, 2]))

def test_literal_attribute(self):
"""Literal attributes must match exactly"""
Expand Down
Loading