Skip to content

Commit

Permalink
Fix issue #222 with matches_filters method (#223)
Browse files Browse the repository at this point in the history
  • Loading branch information
Antelox authored Sep 1, 2023
1 parent 0cbb3d0 commit d63ef1a
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 26 deletions.
59 changes: 33 additions & 26 deletions karton/core/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,32 +212,39 @@ def matches_filters(self, filters: List[Dict[str, Any]]) -> bool:
:meta private:
"""

def value_compare(filter_value: Any, header_value: Any) -> bool:
# Coerce to string for comparison
filter_value_str = str(filter_value)
header_value_str = str(header_value)

negated = False
if filter_value_str.startswith("!"):
negated = True
filter_value_str = filter_value_str[1:]

if header_value is None:
return negated

# fnmatch is great for handling simple wildcard patterns (?, *, [abc])
# If negated: match result should not be True (XOR)
return fnmatch.fnmatchcase(header_value_str, filter_value_str) != negated

return any(
# If any of consumer filters matches the header
all(
# Match: all consumer filter fields match the task header
value_compare(filter_value, self.headers.get(filter_key))
for filter_key, filter_value in task_filter.items()
)
for task_filter in filters
)
matches = False
for task_filter in filters:
matched = []
for filter_key, filter_value in task_filter.items():
# Coerce to string for comparison
header_value = self.headers.get(filter_key)
filter_value_str = str(filter_value)
header_value_str = str(header_value)

negated = False
if filter_value_str.startswith("!"):
negated = True
filter_value_str = filter_value_str[1:]

if header_value is None:
matched.append(negated)
continue

# fnmatch is great for handling simple wildcard patterns (?, *, [abc])
match = fnmatch.fnmatchcase(header_value_str, filter_value_str)
# if matches, but it's negated then we can return straight away
# since no matter the other filters
if match and negated:
return False

# else, apply a XOR logic to take care of negation matching
matched.append(match != negated)

# set the flag if all consumer filter fields match the task header.
# It will be set to True only if at least one filter matches the header
matches |= all(m for m in matched)

return matches

def set_task_parent(self, parent: "Task"):
"""
Expand Down
4 changes: 4 additions & 0 deletions tests/test_task_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ def test_catch_all_filter(self):

def test_negated_filter(self):
filters = [
{
"type": "sample",
"platform": "!macos"
},
{
"type": "sample",
"platform": "!win*"
Expand Down

0 comments on commit d63ef1a

Please sign in to comment.