jsonata-python 0.6.1__py3-none-any.whl → 0.6.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jsonata/cli/__main__.py +1 -1
- jsonata/datetimeutils.py +5 -5
- jsonata/functions.py +22 -29
- jsonata/jexception.py +3 -0
- jsonata/jsonata.py +23 -6
- jsonata/parser.py +2 -1
- jsonata/signature.py +1 -0
- jsonata/tokenizer.py +7 -3
- jsonata/utils.py +4 -7
- {jsonata_python-0.6.1.dist-info → jsonata_python-0.6.2.dist-info}/METADATA +2 -2
- jsonata_python-0.6.2.dist-info/RECORD +18 -0
- {jsonata_python-0.6.1.dist-info → jsonata_python-0.6.2.dist-info}/WHEEL +1 -1
- jsonata_python-0.6.1.dist-info/RECORD +0 -18
- {jsonata_python-0.6.1.dist-info → jsonata_python-0.6.2.dist-info}/entry_points.txt +0 -0
- {jsonata_python-0.6.1.dist-info → jsonata_python-0.6.2.dist-info}/licenses/LICENSE +0 -0
jsonata/cli/__main__.py
CHANGED
|
@@ -34,7 +34,7 @@ def get_options(argv: Optional[list[str]] = None) -> argparse.ArgumentParser:
|
|
|
34
34
|
"""
|
|
35
35
|
parser = argparse.ArgumentParser(prog="jsonata", description="Pure Python JSONata CLI")
|
|
36
36
|
parser.add_argument(
|
|
37
|
-
"-v", "--version", action='version', version='%(prog)s 0.6.
|
|
37
|
+
"-v", "--version", action='version', version='%(prog)s 0.6.2')
|
|
38
38
|
|
|
39
39
|
parser.add_argument(
|
|
40
40
|
"-e", "--expression", metavar="<file>",
|
jsonata/datetimeutils.py
CHANGED
|
@@ -524,7 +524,7 @@ class DateTimeUtils:
|
|
|
524
524
|
while pos < len(picture):
|
|
525
525
|
if picture[pos] == '[':
|
|
526
526
|
# check it's not a doubled [[
|
|
527
|
-
if picture[pos + 1] == '[':
|
|
527
|
+
if pos + 1 < len(picture) and picture[pos + 1] == '[':
|
|
528
528
|
# literal [
|
|
529
529
|
format.add_literal(picture, start, pos)
|
|
530
530
|
format.parts.append(DateTimeUtils.SpecPart("literal", value="["))
|
|
@@ -637,14 +637,14 @@ class DateTimeUtils:
|
|
|
637
637
|
|
|
638
638
|
offset_millis = (60 * offset_hours + offset_minutes) * 60 * 1000
|
|
639
639
|
date_time = datetime.datetime.fromtimestamp((millis + offset_millis) / 1000.0, datetime.timezone.utc)
|
|
640
|
-
|
|
640
|
+
parts = []
|
|
641
641
|
for part in format_spec.parts:
|
|
642
642
|
if part.type == "literal":
|
|
643
|
-
|
|
643
|
+
parts.append(part.value)
|
|
644
644
|
else:
|
|
645
|
-
|
|
645
|
+
parts.append(DateTimeUtils._format_component(date_time, part, offset_hours, offset_minutes))
|
|
646
646
|
|
|
647
|
-
return
|
|
647
|
+
return ''.join(parts)
|
|
648
648
|
|
|
649
649
|
@staticmethod
|
|
650
650
|
def _format_component(date: datetime.datetime, marker_spec: SpecPart, offset_hours: int,
|
jsonata/functions.py
CHANGED
|
@@ -474,11 +474,7 @@ class Functions:
|
|
|
474
474
|
pads = size - str_len
|
|
475
475
|
if pads <= 0:
|
|
476
476
|
return string
|
|
477
|
-
padding =
|
|
478
|
-
i = 0
|
|
479
|
-
while i < pads + 1:
|
|
480
|
-
padding += pad_str
|
|
481
|
-
i += 1
|
|
477
|
+
padding = pad_str * (pads // len(pad_str) + 1)
|
|
482
478
|
return Functions.substr(padding, 0, pads) + string
|
|
483
479
|
|
|
484
480
|
# Source: Jsonata4Java PadFunction
|
|
@@ -501,11 +497,7 @@ class Functions:
|
|
|
501
497
|
pads = size - str_len
|
|
502
498
|
if pads <= 0:
|
|
503
499
|
return string
|
|
504
|
-
padding =
|
|
505
|
-
i = 0
|
|
506
|
-
while i < pads + 1:
|
|
507
|
-
padding += pad_str
|
|
508
|
-
i += 1
|
|
500
|
+
padding = pad_str * (pads // len(pad_str) + 1)
|
|
509
501
|
return string + Functions.substr(padding, 0, pads)
|
|
510
502
|
|
|
511
503
|
@dataclass
|
|
@@ -767,23 +759,23 @@ class Functions:
|
|
|
767
759
|
raise jexception.JException("Fourth argument of replace function must evaluate to a positive number", 0)
|
|
768
760
|
|
|
769
761
|
def string_replacer(match):
|
|
770
|
-
|
|
762
|
+
parts = []
|
|
771
763
|
position = 0
|
|
772
764
|
repl = str(replacement)
|
|
773
765
|
while position < len(repl):
|
|
774
766
|
index = repl.find('$', position)
|
|
775
767
|
if index == -1:
|
|
776
|
-
|
|
768
|
+
parts.append(repl[position:])
|
|
777
769
|
break
|
|
778
|
-
|
|
770
|
+
parts.append(repl[position:index])
|
|
779
771
|
position = index + 1
|
|
780
772
|
if position < len(repl):
|
|
781
773
|
dollar_val = repl[position]
|
|
782
774
|
if dollar_val == '$':
|
|
783
|
-
|
|
775
|
+
parts.append('$')
|
|
784
776
|
position += 1
|
|
785
777
|
elif dollar_val == '0':
|
|
786
|
-
|
|
778
|
+
parts.append(match.group(0))
|
|
787
779
|
position += 1
|
|
788
780
|
else:
|
|
789
781
|
max_digits = len(str(len(match.groups())))
|
|
@@ -791,15 +783,15 @@ class Functions:
|
|
|
791
783
|
if group_num.isdigit():
|
|
792
784
|
group_index = int(group_num)
|
|
793
785
|
if 0 < group_index <= len(match.groups()):
|
|
794
|
-
|
|
786
|
+
parts.append(match.group(group_index) or '')
|
|
795
787
|
position += len(group_num)
|
|
796
788
|
else:
|
|
797
|
-
|
|
789
|
+
parts.append('$')
|
|
798
790
|
else:
|
|
799
|
-
|
|
791
|
+
parts.append('$')
|
|
800
792
|
else:
|
|
801
|
-
|
|
802
|
-
return
|
|
793
|
+
parts.append('$')
|
|
794
|
+
return ''.join(parts)
|
|
803
795
|
|
|
804
796
|
if callable(replacement):
|
|
805
797
|
replacer = lambda m: replacement(m.groupdict())
|
|
@@ -810,23 +802,23 @@ class Functions:
|
|
|
810
802
|
|
|
811
803
|
if isinstance(pattern, str):
|
|
812
804
|
# Use string methods for literal string patterns
|
|
813
|
-
|
|
805
|
+
parts = []
|
|
814
806
|
position = 0
|
|
815
807
|
count = 0
|
|
816
808
|
while True:
|
|
817
809
|
if limit is not None and count >= limit:
|
|
818
|
-
|
|
810
|
+
parts.append(string[position:])
|
|
819
811
|
break
|
|
820
812
|
index = string.find(pattern, position)
|
|
821
813
|
if index == -1:
|
|
822
|
-
|
|
814
|
+
parts.append(string[position:])
|
|
823
815
|
break
|
|
824
|
-
|
|
816
|
+
parts.append(string[position:index])
|
|
825
817
|
match = re.match(re.escape(pattern), string[index:])
|
|
826
|
-
|
|
818
|
+
parts.append(replacer(match))
|
|
827
819
|
position = index + len(pattern)
|
|
828
820
|
count += 1
|
|
829
|
-
return
|
|
821
|
+
return ''.join(parts)
|
|
830
822
|
else:
|
|
831
823
|
# Use regex for pattern objects
|
|
832
824
|
if limit is None:
|
|
@@ -1844,7 +1836,8 @@ class Functions:
|
|
|
1844
1836
|
#
|
|
1845
1837
|
@staticmethod
|
|
1846
1838
|
def error(message: Optional[str]) -> NoReturn:
|
|
1847
|
-
raise jexception.JException("D3137", -1,
|
|
1839
|
+
raise jexception.JException("D3137", -1,
|
|
1840
|
+
message if message is not None else "$error() function evaluated")
|
|
1848
1841
|
|
|
1849
1842
|
#
|
|
1850
1843
|
#
|
|
@@ -1859,8 +1852,8 @@ class Functions:
|
|
|
1859
1852
|
raise jexception.JException("T0410", -1)
|
|
1860
1853
|
|
|
1861
1854
|
if not condition:
|
|
1862
|
-
raise jexception.JException("D3141", -1,
|
|
1863
|
-
|
|
1855
|
+
raise jexception.JException("D3141", -1,
|
|
1856
|
+
message if message is not None else "$assert() statement failed")
|
|
1864
1857
|
|
|
1865
1858
|
#
|
|
1866
1859
|
#
|
jsonata/jexception.py
CHANGED
jsonata/jsonata.py
CHANGED
|
@@ -469,7 +469,7 @@ class Jsonata:
|
|
|
469
469
|
result.tuple_stream = True
|
|
470
470
|
step_env = environment
|
|
471
471
|
if tuple_bindings is None:
|
|
472
|
-
tuple_bindings = [{"@": item} for item in input
|
|
472
|
+
tuple_bindings = [{"@": item} for item in input]
|
|
473
473
|
|
|
474
474
|
for tuple_binding in tuple_bindings:
|
|
475
475
|
step_env = self.create_frame_from_tuple(environment, tuple_binding)
|
|
@@ -519,7 +519,7 @@ class Jsonata:
|
|
|
519
519
|
if index < 0:
|
|
520
520
|
# count in from end of array
|
|
521
521
|
index = len(input) + index
|
|
522
|
-
item = input[index] if index < len(input) else None
|
|
522
|
+
item = input[index] if 0 <= index < len(input) else None
|
|
523
523
|
if item is not None:
|
|
524
524
|
if isinstance(item, list):
|
|
525
525
|
results = item
|
|
@@ -684,9 +684,6 @@ class Jsonata:
|
|
|
684
684
|
if isinstance(value, list):
|
|
685
685
|
value = self.flatten(value, None)
|
|
686
686
|
results = functions.Functions.append(results, value)
|
|
687
|
-
elif isinstance(value, dict):
|
|
688
|
-
# Call recursively do decompose the map
|
|
689
|
-
results.extend(self.evaluate_wildcard(expr, value))
|
|
690
687
|
else:
|
|
691
688
|
results.append(value)
|
|
692
689
|
|
|
@@ -1475,7 +1472,14 @@ class Jsonata:
|
|
|
1475
1472
|
elif isinstance(proc, Jsonata.JLambda):
|
|
1476
1473
|
result = proc.call(input, validated_args)
|
|
1477
1474
|
elif isinstance(proc, re.Pattern):
|
|
1478
|
-
|
|
1475
|
+
_res = []
|
|
1476
|
+
for s in validated_args:
|
|
1477
|
+
if isinstance(s, str):
|
|
1478
|
+
_res.append(Jsonata._regex_closure(proc.finditer(s)))
|
|
1479
|
+
if len(_res) == 1:
|
|
1480
|
+
result = _res[0]
|
|
1481
|
+
else:
|
|
1482
|
+
result = _res
|
|
1479
1483
|
else:
|
|
1480
1484
|
print("Proc not found " + str(proc))
|
|
1481
1485
|
raise jexception.JException("T1006", 0)
|
|
@@ -1489,6 +1493,19 @@ class Jsonata:
|
|
|
1489
1493
|
raise err
|
|
1490
1494
|
return result
|
|
1491
1495
|
|
|
1496
|
+
@staticmethod
|
|
1497
|
+
def _regex_closure(iterator):
|
|
1498
|
+
m = next(iterator, None)
|
|
1499
|
+
if m is None:
|
|
1500
|
+
return None
|
|
1501
|
+
return {
|
|
1502
|
+
"match": m.group(),
|
|
1503
|
+
"start": m.start(),
|
|
1504
|
+
"end": m.end(),
|
|
1505
|
+
"groups": [m.group()],
|
|
1506
|
+
"next": Jsonata.JLambda(lambda: Jsonata._regex_closure(iterator))
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1492
1509
|
#
|
|
1493
1510
|
# Evaluate lambda against input data
|
|
1494
1511
|
# @param {Object} expr - JSONata expression
|
jsonata/parser.py
CHANGED
|
@@ -1047,7 +1047,8 @@ class Parser:
|
|
|
1047
1047
|
rest = self.process_ast(expr.rhs)
|
|
1048
1048
|
if (rest.type == "function" and rest.procedure.type == "path" and len(
|
|
1049
1049
|
rest.procedure.steps) == 1 and rest.procedure.steps[0].type == "name" and
|
|
1050
|
-
result.steps[-1].type == "function"
|
|
1050
|
+
result.steps[-1].type == "function" and
|
|
1051
|
+
isinstance(rest.procedure.steps[0].value, Parser.Symbol)):
|
|
1051
1052
|
# next function in chain of functions - will override a thenable
|
|
1052
1053
|
result.steps[-1].next_function = rest.procedure.steps[0].value
|
|
1053
1054
|
if rest.type == "path":
|
jsonata/signature.py
CHANGED
jsonata/tokenizer.py
CHANGED
|
@@ -32,6 +32,8 @@ from typing import Any, Optional
|
|
|
32
32
|
|
|
33
33
|
from jsonata import jexception, utils
|
|
34
34
|
|
|
35
|
+
_NUMBER_PATTERN = re.compile(r"^-?(0|([1-9][0-9]*))(\.[0-9]+)?([Ee][-+]?[0-9]+)?")
|
|
36
|
+
|
|
35
37
|
|
|
36
38
|
class Tokenizer:
|
|
37
39
|
operators = {
|
|
@@ -135,7 +137,10 @@ class Tokenizer:
|
|
|
135
137
|
if pattern == "":
|
|
136
138
|
raise jexception.JException("S0301", self.position)
|
|
137
139
|
self.position += 1
|
|
138
|
-
|
|
140
|
+
if self.position < self.length:
|
|
141
|
+
current_char = self.path[self.position]
|
|
142
|
+
else:
|
|
143
|
+
current_char = None
|
|
139
144
|
# flags
|
|
140
145
|
start = self.position
|
|
141
146
|
while current_char == 'i' or current_char == 'm':
|
|
@@ -264,8 +269,7 @@ class Tokenizer:
|
|
|
264
269
|
self.position += 1
|
|
265
270
|
raise jexception.JException("S0101", self.position)
|
|
266
271
|
# test for numbers
|
|
267
|
-
|
|
268
|
-
match_ = numregex.search(self.path[self.position:])
|
|
272
|
+
match_ = _NUMBER_PATTERN.search(self.path[self.position:])
|
|
269
273
|
if match_ is not None:
|
|
270
274
|
num = float(match_.group(0))
|
|
271
275
|
if not math.isnan(num) and math.isfinite(num):
|
jsonata/utils.py
CHANGED
|
@@ -74,11 +74,7 @@ class Utils:
|
|
|
74
74
|
@staticmethod
|
|
75
75
|
def create_sequence(el: Optional[Any] = NONE) -> list:
|
|
76
76
|
if el is not Utils.NONE:
|
|
77
|
-
|
|
78
|
-
sequence = Utils.JList(el)
|
|
79
|
-
else:
|
|
80
|
-
# This case does NOT exist in Javascript! Why?
|
|
81
|
-
sequence = Utils.JList([el])
|
|
77
|
+
sequence = Utils.JList([el])
|
|
82
78
|
else:
|
|
83
79
|
sequence = Utils.JList()
|
|
84
80
|
sequence.sequence = True
|
|
@@ -106,9 +102,10 @@ class Utils:
|
|
|
106
102
|
if not Utils.is_deep_equal(lhs[key], rhs[key]):
|
|
107
103
|
return False
|
|
108
104
|
return True
|
|
109
|
-
if lhs == rhs
|
|
105
|
+
if lhs == rhs:
|
|
106
|
+
if isinstance(lhs, bool) != isinstance(rhs, bool):
|
|
107
|
+
return False
|
|
110
108
|
return True
|
|
111
|
-
|
|
112
109
|
return False
|
|
113
110
|
|
|
114
111
|
class JList(list):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jsonata-python
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.2
|
|
4
4
|
Summary: Pure Python implementation of JSONata
|
|
5
5
|
Project-URL: Homepage, https://github.com/rayokota/jsonata-python
|
|
6
6
|
Project-URL: Bug Reports, https://github.com/rayokota/jsonata-python/issues
|
|
@@ -212,7 +212,7 @@ Keywords: json,jsonata
|
|
|
212
212
|
Classifier: Development Status :: 4 - Beta
|
|
213
213
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
214
214
|
Classifier: Programming Language :: Python
|
|
215
|
-
Requires-Python: >=3.
|
|
215
|
+
Requires-Python: >=3.10
|
|
216
216
|
Description-Content-Type: text/markdown
|
|
217
217
|
|
|
218
218
|
# jsonata-python
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
jsonata/__init__.py,sha256=4r8USHj4SoBy_TD8dLxt9HJIgpLfXApFrZBipi4rgr0,388
|
|
2
|
+
jsonata/constants.py,sha256=WtdH_l_s5KD-SiOJ4GR2az7WpVgKB2HguXUnyfy4tvs,3017
|
|
3
|
+
jsonata/datetimeutils.py,sha256=lCTGih5Qn4HZlqG2qcCniREaOt_2Dvxai5rpFq-hKj4,48609
|
|
4
|
+
jsonata/functions.py,sha256=VoVVyK-9SS6CrseChFJkERqUxm7mPzcoIeALegwVztI,75709
|
|
5
|
+
jsonata/jexception.py,sha256=AjyPmFyE7FecV--FLYHfcZFu-SkG1XKAEdvUQ1Ojuqo,12956
|
|
6
|
+
jsonata/jsonata.py,sha256=mKoqLdVED7nQyCjNqxgPr5_IBV5nzLKdonXDVy0SXyk,84652
|
|
7
|
+
jsonata/parser.py,sha256=VfWmD79PA_zp7uXUjbVY1E9CEwA60EG1EV2vEKue__M,55444
|
|
8
|
+
jsonata/signature.py,sha256=6iQIgFSCH9Wv7Zhuu5U8PT-LVTtxY_qL8QMsGn5wGH4,20221
|
|
9
|
+
jsonata/timebox.py,sha256=bnevNR_ONvKUiIZCJZEWsRiR0gCWTGOwn5RCY7dKqYc,2861
|
|
10
|
+
jsonata/tokenizer.py,sha256=M5vEaYrMEr6UQwakDLz7dAAIXeJ7ZBPlqw9gYWTbcZM,12550
|
|
11
|
+
jsonata/utils.py,sha256=kn2qjrp7et2NPT3T6XtF9g6Y5lIHWEHgA42hHXQz8rs,5834
|
|
12
|
+
jsonata/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
+
jsonata/cli/__main__.py,sha256=XfgdzMQEvKd3xkgTpvUndn5ifgVi0j4fYrn2Oejzu1E,7121
|
|
14
|
+
jsonata_python-0.6.2.dist-info/METADATA,sha256=9U-6dc9p-wUZaptm0-59-RUQsAT3kRgHUDGnIwKNSyo,17338
|
|
15
|
+
jsonata_python-0.6.2.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
16
|
+
jsonata_python-0.6.2.dist-info/entry_points.txt,sha256=a-W2yyT3IPhcC1q12BhKPcWnjNi3NXTZ3ZxoI9_UK88,54
|
|
17
|
+
jsonata_python-0.6.2.dist-info/licenses/LICENSE,sha256=y16Ofl9KOYjhBjwULGDcLfdWBfTEZRXnduOspt-XbhQ,11325
|
|
18
|
+
jsonata_python-0.6.2.dist-info/RECORD,,
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
jsonata/__init__.py,sha256=4r8USHj4SoBy_TD8dLxt9HJIgpLfXApFrZBipi4rgr0,388
|
|
2
|
-
jsonata/constants.py,sha256=WtdH_l_s5KD-SiOJ4GR2az7WpVgKB2HguXUnyfy4tvs,3017
|
|
3
|
-
jsonata/datetimeutils.py,sha256=IzU6y-vwyhwobHyw9rsImBye-RfWDV7K8Vk0Xs-yiG0,48567
|
|
4
|
-
jsonata/functions.py,sha256=it09GOcMOJ2XDlvh_yhf-bgABaHMTrUFhzXa0kUsrNk,75729
|
|
5
|
-
jsonata/jexception.py,sha256=6Jz7WMsIiNlQ7-1Hq8RKiE2HxcHq2PDekw0qsSe3lqo,12885
|
|
6
|
-
jsonata/jsonata.py,sha256=YmLrus5eBOdcGIzV6nEzsFOkBRJvosE-3bjpdQZVISg,84248
|
|
7
|
-
jsonata/parser.py,sha256=dzZ6PeM5l3scTHq4DzCXt4FSRO49yzYEk7XqspCcHNU,55359
|
|
8
|
-
jsonata/signature.py,sha256=j7eNKUuGx_9vCt5Qv8BPM7iV5vH26U0Kx8zrkDcctME,20194
|
|
9
|
-
jsonata/timebox.py,sha256=bnevNR_ONvKUiIZCJZEWsRiR0gCWTGOwn5RCY7dKqYc,2861
|
|
10
|
-
jsonata/tokenizer.py,sha256=6noGxO1L_n2V-Uva5oV044Xx0p08Gm7-XXSfLEG4rR0,12429
|
|
11
|
-
jsonata/utils.py,sha256=WDs-z5JRJ5pUEpmAwUY3xgDFxEIsvTqZXp8UX6cNSpQ,5952
|
|
12
|
-
jsonata/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
-
jsonata/cli/__main__.py,sha256=x1cz-w1NYBb_UNJuDnwqmGaz1SdfHwpMjKXIz5GQG-A,7121
|
|
14
|
-
jsonata_python-0.6.1.dist-info/METADATA,sha256=lNCEnZXUk7pzV8kP9unZq0AVkNoB2ZngEPbdfiaoUO8,17337
|
|
15
|
-
jsonata_python-0.6.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
16
|
-
jsonata_python-0.6.1.dist-info/entry_points.txt,sha256=a-W2yyT3IPhcC1q12BhKPcWnjNi3NXTZ3ZxoI9_UK88,54
|
|
17
|
-
jsonata_python-0.6.1.dist-info/licenses/LICENSE,sha256=y16Ofl9KOYjhBjwULGDcLfdWBfTEZRXnduOspt-XbhQ,11325
|
|
18
|
-
jsonata_python-0.6.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|