Skip to content

Commit 7eed376

Browse files
committed
Move interpreter to exprefs
This moves the cyclic dependency between functions and interpreters to expref nodes and functions. This makes it easier to create custom function runtime classes as they now have no instance state.
1 parent a6baa17 commit 7eed376

File tree

2 files changed

+13
-34
lines changed

2 files changed

+13
-34
lines changed

jmespath/functions.py

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import math
22
import json
3-
import weakref
43

54
from jmespath import exceptions
65
from jmespath.compat import string_type as STRING_TYPE
@@ -60,24 +59,6 @@ class RuntimeFunctions(object):
6059
FUNCTION_TABLE = {
6160
}
6261

63-
def __init__(self):
64-
self._interpreter = None
65-
66-
@property
67-
def interpreter(self):
68-
if self._interpreter is None:
69-
return None
70-
else:
71-
return self._interpreter()
72-
73-
@interpreter.setter
74-
def interpreter(self, value):
75-
# A weakref is used because we have
76-
# a cyclic reference and we want to allow
77-
# for the memory to be properly freed when
78-
# the objects are no longer needed.
79-
self._interpreter = weakref.ref(value)
80-
8162
def call_function(self, function_name, resolved_args):
8263
try:
8364
spec = self.FUNCTION_TABLE[function_name]
@@ -255,7 +236,7 @@ def _func_join(self, separator, array):
255236
def _func_map(self, expref, arg):
256237
result = []
257238
for element in arg:
258-
result.append(self.interpreter.visit(expref.expression, element))
239+
result.append(expref.visit(expref.expression, element))
259240
return result
260241

261242
@builtin_function({"types": ['array-number', 'array-string']})
@@ -323,34 +304,32 @@ def _func_sort_by(self, array, expref):
323304
# that validates that type, which requires that remaining array
324305
# elements resolve to the same type as the first element.
325306
required_type = self._convert_to_jmespath_type(
326-
type(self.interpreter.visit(expref.expression, array[0])).__name__)
307+
type(expref.visit(expref.expression, array[0])).__name__)
327308
if required_type not in ['number', 'string']:
328309
raise exceptions.JMESPathTypeError(
329310
'sort_by', array[0], required_type, ['string', 'number'])
330-
keyfunc = self._create_key_func(expref.expression,
311+
keyfunc = self._create_key_func(expref,
331312
[required_type],
332313
'sort_by')
333314
return list(sorted(array, key=keyfunc))
334315

335316
@builtin_function({'types': ['array']}, {'types': ['expref']})
336317
def _func_min_by(self, array, expref):
337-
keyfunc = self._create_key_func(expref.expression,
318+
keyfunc = self._create_key_func(expref,
338319
['number', 'string'],
339320
'min_by')
340321
return min(array, key=keyfunc)
341322

342323
@builtin_function({'types': ['array']}, {'types': ['expref']})
343324
def _func_max_by(self, array, expref):
344-
keyfunc = self._create_key_func(expref.expression,
325+
keyfunc = self._create_key_func(expref,
345326
['number', 'string'],
346327
'min_by')
347328
return max(array, key=keyfunc)
348329

349-
def _create_key_func(self, expr_node, allowed_types, function_name):
350-
interpreter = self.interpreter
351-
330+
def _create_key_func(self, expref, allowed_types, function_name):
352331
def keyfunc(x):
353-
result = interpreter.visit(expr_node, x)
332+
result = expref.visit(expref.expression, x)
354333
actual_typename = type(result).__name__
355334
jmespath_type = self._convert_to_jmespath_type(actual_typename)
356335
# allowed_types is in term of jmespath types, not python types.

jmespath/visitor.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,12 @@ def __init__(self, dict_cls):
4848

4949

5050
class _Expression(object):
51-
def __init__(self, expression):
51+
def __init__(self, expression, interpreter):
5252
self.expression = expression
53+
self.interpreter = interpreter
54+
55+
def visit(self, node, *args, **kwargs):
56+
return self.interpreter.visit(node, *args, **kwargs)
5357

5458

5559
class Visitor(object):
@@ -88,10 +92,6 @@ def __init__(self, options=None):
8892
if options is not None and options.dict_cls is not None:
8993
self._dict_cls = self._options.dict_cls
9094
self._functions = functions.RuntimeFunctions()
91-
# Note that .interpreter is a property that uses
92-
# a weakref so that the cyclic reference can be
93-
# properly freed.
94-
self._functions.interpreter = self
9595

9696
def default_visit(self, node, *args, **kwargs):
9797
raise NotImplementedError(node['type'])
@@ -119,7 +119,7 @@ def visit_current(self, node, value):
119119
return value
120120

121121
def visit_expref(self, node, value):
122-
return _Expression(node['children'][0])
122+
return _Expression(node['children'][0], self)
123123

124124
def visit_function_expression(self, node, value):
125125
resolved_args = []

0 commit comments

Comments
 (0)