diff --git a/karton/core/query.py b/karton/core/query.py index 4146df8..0c1eb7e 100644 --- a/karton/core/query.py +++ b/karton/core/query.py @@ -1,4 +1,6 @@ +import fnmatch import re + from collections.abc import Mapping, Sequence from typing import Dict, Type @@ -303,13 +305,13 @@ def __repr__(self): return f"" -def toregex(x): - """Naive/PoC wildcard-to-regex conversion""" - if not isinstance(x, str): - raise QueryError(f"Unexpected value in the regex conversion: {x}") - if "?" in x or "*" in x or "[" in x: - return {"$regex": "^" + x.replace("?", ".?").replace("*", ".*") + "$"} - return x +def toregex(wildcard): + if not isinstance(wildcard, str): + raise QueryError(f"Unexpected value in the regex conversion: {wildcard}") + # If is not neessary, but we avoid unnecessary regular expressions. + if any(c in wildcard for c in "?*[]!"): + return {"$regex": fnmatch.translate(wildcard)} + return wildcard def convert(filters): diff --git a/tests/test_task_filters.py b/tests/test_task_filters.py index c01253f..369f58c 100644 --- a/tests/test_task_filters.py +++ b/tests/test_task_filters.py @@ -508,3 +508,17 @@ def test_newstyle_flip(self): } ) self.assertFalse(task_sample.matches_filters(filters)) + + def test_oldstyle_wildcards(self): + # Old-style wildcards, except negative filters, don't mix + filters = [{"foo": "ba[!rz]"}] + + task_sample = Task(headers={ + "foo": "bar", + }) + self.assertFalse(task_sample.matches_filters(filters)) + + task_sample = Task(headers={ + "foo": "bat", + }) + self.assertTrue(task_sample.matches_filters(filters))