Skip to content

Commit 93164e0

Browse files
committed
Simpifly passing of bindings
1 parent f9bd4e0 commit 93164e0

2 files changed

Lines changed: 28 additions & 3 deletions

File tree

src/jsonata/jsonata.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
import sys
3232
import threading
3333
from dataclasses import dataclass
34-
from typing import Any, Callable, Mapping, MutableSequence, Optional, Sequence, Type, MutableMapping
34+
from typing import Any, Callable, Mapping, MutableSequence, Optional, Sequence, Type, MutableMapping, Union
3535

3636
from jsonata import functions, jexception, parser, signature as sig, timebox, utils
3737

@@ -1976,7 +1976,7 @@ def is_output_convert_nulls(self) -> bool:
19761976
def set_output_convert_nulls(self, output_convert_nulls: bool) -> None:
19771977
self.output_convert_nulls = output_convert_nulls
19781978

1979-
def evaluate(self, input: Optional[Any], bindings: Optional[Frame] = None) -> Optional[Any]:
1979+
def evaluate(self, input: Optional[Any], bindings: Optional[Union[Frame, Mapping[str, Any]]] = None) -> Optional[Any]:
19801980
# throw if the expression compiled with syntax errors
19811981
if self.errors is not None:
19821982
raise jexception.JException("S0500", 0)
@@ -1986,7 +1986,9 @@ def evaluate(self, input: Optional[Any], bindings: Optional[Frame] = None) -> Op
19861986
# var exec_env
19871987
# the variable bindings have been passed in - create a frame to hold these
19881988
exec_env = self.create_frame(self.environment)
1989-
for k, v in bindings.bindings.items():
1989+
# accept either a Frame or a plain mapping (e.g. dict) of variable bindings
1990+
items = bindings.bindings if isinstance(bindings, Jsonata.Frame) else bindings
1991+
for k, v in items.items():
19901992
exec_env.bind(k, v)
19911993
else:
19921994
exec_env = self.environment

tests/jsonata_test.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,29 @@ def test_path(self):
104104
print(str(data))
105105
self.eval_expr("foo.bar", data, None, 42, None)
106106

107+
def test_dict_bindings(self):
108+
data = {
109+
"products": [
110+
{"name": "Apple", "price": 1.20},
111+
{"name": "Banana", "price": 0.50},
112+
{"name": "Cherry", "price": 2.50},
113+
]
114+
}
115+
expr = jsonata.Jsonata(
116+
"products[price <= $maxPrice]"
117+
".(name & ' costs ' & $currencySymbol & $string(price))"
118+
)
119+
expected = ["Apple costs $1.2", "Banana costs $0.5"]
120+
121+
# A plain dict can be passed directly as the bindings.
122+
assert expr.evaluate(data, bindings={"maxPrice": 1.50, "currencySymbol": "$"}) == expected
123+
124+
# A Frame is still accepted for backward compatibility.
125+
binding_frame = jsonata.Jsonata.Frame(None)
126+
binding_frame.bind("maxPrice", 1.50)
127+
binding_frame.bind("currencySymbol", "$")
128+
assert expr.evaluate(data, bindings=binding_frame) == expected
129+
107130
def run_case(self, name):
108131
if not self.run_test_suite(name):
109132
raise Exception()

0 commit comments

Comments
 (0)