From 9c3540a5b9c74f4916cb0b141625b32af96a690b Mon Sep 17 00:00:00 2001 From: fhgffy <102001626+fhgffy@users.noreply.github.com> Date: Sun, 11 Oct 2026 04:02:04 +0800 Subject: [PATCH] Use JMESPath scalar equality for array containment --- jmespath/functions.py | 4 ++++ tests/test_functions.py | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/jmespath/functions.py b/jmespath/functions.py index 627b569d..0102833a 100644 --- a/jmespath/functions.py +++ b/jmespath/functions.py @@ -212,6 +212,10 @@ def _func_to_number(self, arg): @signature({'types': ['array', 'string']}, {'types': []}) def _func_contains(self, subject, search): + if isinstance(subject, list): + # 2026-10-11: Import after initialization to share comparator equality. + from jmespath.visitor import _equals + return any(_equals(element, search) for element in subject) return search in subject @signature({'types': ['string', 'array', 'object']}) diff --git a/tests/test_functions.py b/tests/test_functions.py index a352d69e..3bd002a7 100644 --- a/tests/test_functions.py +++ b/tests/test_functions.py @@ -55,3 +55,22 @@ def test_variadic_is_pluralized(self): self.assertEqual( str(exception), 'Expected at least 1 argument for function not_null(), received 0') + + def test_contains_array_distinguishes_booleans_from_numbers(self): + # 2026-10-11: Array membership must use JMESPath scalar equality. + for value, search in [(True, 1), (False, 0), (1, True), (0, False), + (True, 1.0), (False, 0.0)]: + with self.subTest(value=value, search=search): + data = {'values': [value], 'search': search} + self.assertFalse(jmespath.search('contains(values, search)', data)) + + def test_contains_array_preserves_valid_matches(self): + # 2026-10-11: Preserve numeric equivalence and matching JSON types. + for value, search in [(1, 1.0), (0, 0.0), (True, True), + (False, False), (None, None), ('one', 'one')]: + with self.subTest(value=value, search=search): + data = {'values': [value], 'search': search} + self.assertTrue(jmespath.search('contains(values, search)', data)) + self.assertFalse(jmespath.search('contains(@, `true`)', [])) + self.assertTrue(jmespath.search('contains(@, `true`)', [1, True])) + self.assertTrue(jmespath.search("contains(@, 'bar')", 'foobar'))