diff --git a/jmespath/visitor.py b/jmespath/visitor.py index 15fb1774..7477029b 100644 --- a/jmespath/visitor.py +++ b/jmespath/visitor.py @@ -1,3 +1,4 @@ +import copy import operator from jmespath import functions @@ -225,7 +226,7 @@ def visit_key_val_pair(self, node, value): return self.visit(node['children'][0], value) def visit_literal(self, node, value): - return node['value'] + return copy.deepcopy(node['value']) def visit_multi_select_dict(self, node, value): if value is None: diff --git a/tests/test_search.py b/tests/test_search.py index 4832079b..4a479e94 100644 --- a/tests/test_search.py +++ b/tests/test_search.py @@ -62,3 +62,33 @@ def test_can_handle_decimals_as_numeric_type(self): result = decimal.Decimal('3') self.assertEqual(jmespath.search('[?a >= `1`].a', [{'a': result}]), [result]) + + def test_literal_empty_list_changes_do_not_propagate(self): + first = jmespath.search('`[]`', {}) + first.extend([1, 2, 3]) + second = jmespath.search('`[]`', {}) + self.assertEqual(second, []) + + def test_literal_list_changes_do_not_propagate(self): + first = jmespath.search('`[1, 2, 3]`', {}) + first.append(99) + second = jmespath.search('`[1, 2, 3]`', {}) + self.assertEqual(second, [1, 2, 3]) + + def test_literal_nested_dict_changes_do_not_propagate(self): + first = jmespath.search('`{"key": [1, 2, 3]}`', {}) + first['key'].append(99) + second = jmespath.search('`{"key": [1, 2, 3]}`', {}) + self.assertEqual(second, {'key': [1, 2, 3]}) + + def test_literal_dict_added_key_does_not_propagate(self): + first = jmespath.search('`{"a": 1}`', {}) + first['new_key'] = 99 + second = jmespath.search('`{"a": 1}`', {}) + self.assertEqual(second, {'a': 1}) + + def test_literal_dict_overwritten_key_does_not_propagate(self): + first = jmespath.search('`{"a": 1}`', {}) + first['a'] = 99 + second = jmespath.search('`{"a": 1}`', {}) + self.assertEqual(second, {'a': 1})