Skip to content

Commit 1443207

Browse files
committed
Support scopes when evaluating fields.
1 parent bbe7300 commit 1443207

File tree

2 files changed

+59
-1
lines changed

2 files changed

+59
-1
lines changed

jmespath/visitor.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ def visit_field(self, node, value):
135135
try:
136136
return value.get(node['value'])
137137
except AttributeError:
138-
return None
138+
return None
139139

140140
def visit_comparator(self, node, value):
141141
# Common case: comparator is == or !=
@@ -326,3 +326,34 @@ def _visit(self, node, current):
326326
self._count += 1
327327
self._lines.append(' %s -> %s' % (current, child_name))
328328
self._visit(child, child_name)
329+
330+
331+
class Scopes:
332+
def __init__(self):
333+
self._scopes = []
334+
335+
def pushScope(self, scope):
336+
self._scopes.append(scope)
337+
338+
def popScope(self):
339+
if len(self._scopes) > 0:
340+
self._scopes.pop()
341+
342+
def getValue(self, identifier):
343+
for scope in self._scopes[::-1]:
344+
if scope.get(identifier) != None:
345+
return scope[identifier]
346+
return None
347+
348+
349+
class ScopedInterpreter(TreeInterpreter):
350+
def __init__(self, options = None):
351+
super().__init__(options)
352+
self._scopes = Scopes()
353+
354+
def visit(self, node, *args, **kwargs):
355+
node_type = node['type']
356+
if (node_type == 'field'):
357+
kwargs.update({'scopes': self._scopes})
358+
359+
return super().visit(node, *args, **kwargs)

tests/test_scopes.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
2+
import pytest
3+
4+
from tests import unittest
5+
from jmespath.visitor import Scopes
6+
7+
class TestScope(unittest.TestCase):
8+
def setUp(self):
9+
self._scopes = Scopes()
10+
11+
def test_Scope_missing(self):
12+
value = self._scopes.getValue('foo')
13+
self.assertEqual(None, value)
14+
15+
def test_Scope_root(self):
16+
self._scopes.pushScope({'foo': 'bar'})
17+
value = self._scopes.getValue('foo')
18+
self.assertEqual('bar', value)
19+
20+
def test_Scope_nested(self):
21+
self._scopes.pushScope({'foo': 'bar'})
22+
self._scopes.pushScope({'foo': 'baz'})
23+
value = self._scopes.getValue('foo')
24+
self.assertEqual('baz', value)
25+
26+
if __name__ == '__main__':
27+
unittest.main()

0 commit comments

Comments
 (0)