Skip to content

Commit

Permalink
[jmespath#186] options: add default not found value option
Browse files Browse the repository at this point in the history
  • Loading branch information
Filip Uhlik committed Mar 20, 2024
1 parent 2ad18b0 commit 89550c9
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 5 deletions.
11 changes: 6 additions & 5 deletions jmespath/visitor.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import operator
from numbers import Number

from jmespath import functions
from jmespath.compat import string_type
from numbers import Number


def _equals(x, y):
Expand Down Expand Up @@ -58,7 +58,7 @@ def _is_actual_number(x):

class Options(object):
"""Options to control how a JMESPath function is evaluated."""
def __init__(self, dict_cls=None, custom_functions=None):
def __init__(self, dict_cls=None, custom_functions=None, not_found_value=None):
#: The class to use when creating a dict. The interpreter
# may create dictionaries during the evaluation of a JMESPath
# expression. For example, a multi-select hash will
Expand All @@ -69,6 +69,7 @@ def __init__(self, dict_cls=None, custom_functions=None):
# have predictable key ordering.
self.dict_cls = dict_cls
self.custom_functions = custom_functions
self.not_found_value = not_found_value


class _Expression(object):
Expand Down Expand Up @@ -133,9 +134,9 @@ def visit_subexpression(self, node, value):

def visit_field(self, node, value):
try:
return value.get(node['value'])
return value.get(node['value'], self._options.not_found_value)
except AttributeError:
return None
return self._options.not_found_value

def visit_comparator(self, node, value):
# Common case: comparator is == or !=
Expand Down Expand Up @@ -298,7 +299,7 @@ def _is_false(self, value):
# because the truth/false values are different between
# python and jmespath.
return (value == '' or value == [] or value == {} or value is None or
value is False)
value is False or value == self._options.not_found_value)

def _is_true(self, value):
return not self._is_false(value)
Expand Down
12 changes: 12 additions & 0 deletions tests/test_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,15 @@ def test_can_handle_decimals_as_numeric_type(self):
result = decimal.Decimal('3')
self.assertEqual(jmespath.search('[?a >= `1`].a', [{'a': result}]),
[result])


class TestNotFoundValueOption(unittest.TestCase):
opt = jmespath.Options(not_found_value='foo')

def test_can_supply_custom_not_found_value(self):
value = jmespath.search('b', {'a': 1}, self.opt)
self.assertEqual(value, 'foo')

def test_custom_value_is_treated_as_false(self):
value = jmespath.search('b || a', {'a': 1}, self.opt)
self.assertEqual(value, 1)

0 comments on commit 89550c9

Please sign in to comment.