Skip to content

Commit

Permalink
fix: filter Implementation is set operator (#25182) (#25195)
Browse files Browse the repository at this point in the history
* Implementation is set operator. fix issue #25180

* Refactored filtrer operator `is`,
Add tests

* fix: Correct implementation for `is set`

---------

Co-authored-by: Ankush Menat <ankush@frappe.io>
(cherry picked from commit eff50e1)

# Conflicts:
#	frappe/tests/test_utils.py

Co-authored-by: Maxim Sysoev <maks4a@gmail.com>
  • Loading branch information
mergify[bot] and rareMaxim committed Mar 2, 2024
1 parent 3dafbf9 commit 20a7879
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 3 deletions.
18 changes: 15 additions & 3 deletions frappe/tests/test_utils.py
Expand Up @@ -175,8 +175,15 @@ def test_date_time(self):
)
)

def test_like_not_like(self):
doc = {"doctype": "User", "username": "test_abc", "prefix": "startswith", "suffix": "endswith"}
def test_filter_evaluation(self):
doc = {
"doctype": "User",
"username": "test_abc",
"prefix": "startswith",
"suffix": "endswith",
"empty": None,
"number": 0,
}

test_cases = [
([["username", "like", "test"]], True),
Expand All @@ -187,10 +194,15 @@ def test_like_not_like(self):
([["prefix", "not like", "end%"]], True),
([["suffix", "like", "%with"]], True),
([["suffix", "not like", "%end"]], True),
([["suffix", "is", "set"]], True),
([["suffix", "is", "not set"]], False),
([["empty", "is", "set"]], False),
([["empty", "is", "not set"]], True),
([["number", "is", "set"]], True),
]

for filter, expected_result in test_cases:
self.assertEqual(evaluate_filters(doc, filter), expected_result)
self.assertEqual(evaluate_filters(doc, filter), expected_result, msg=f"{filter}")


class TestMoney(FrappeTestCase):
Expand Down
20 changes: 20 additions & 0 deletions frappe/utils/data.py
Expand Up @@ -1693,6 +1693,25 @@ def sql_like(value: str, pattern: str) -> bool:
return pattern in value


def filter_operator_is(value: str, pattern: str) -> bool:
"""Operator `is` can have two values: 'set' or 'not set'."""
pattern = pattern.lower()

def is_set():
if value is None:
return False
elif isinstance(value, str) and not value:
return False
return True

if pattern == "set":
return is_set()
elif pattern == "not set":
return not is_set()
else:
frappe.throw(frappe._(f"Invalid argument for operator 'IS': {pattern}"))


operator_map = {
# startswith
"^": lambda a, b: (a or "").startswith(b),
Expand All @@ -1710,6 +1729,7 @@ def sql_like(value: str, pattern: str) -> bool:
"None": lambda a, b: a is None,
"like": sql_like,
"not like": lambda a, b: not sql_like(a, b),
"is": filter_operator_is,
}


Expand Down

0 comments on commit 20a7879

Please sign in to comment.