jsonata-python 0.5.3__py3-none-any.whl → 0.6.1__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 +2 -2
- jsonata/functions.py +10 -2
- jsonata/jsonata.py +2 -2
- jsonata/parser.py +43 -0
- jsonata/tokenizer.py +10 -0
- jsonata/utils.py +21 -0
- {jsonata_python-0.5.3.dist-info → jsonata_python-0.6.1.dist-info}/METADATA +10 -10
- jsonata_python-0.6.1.dist-info/RECORD +18 -0
- {jsonata_python-0.5.3.dist-info → jsonata_python-0.6.1.dist-info}/WHEEL +1 -1
- jsonata_python-0.6.1.dist-info/entry_points.txt +2 -0
- jsonata_python-0.5.3.dist-info/RECORD +0 -17
- {jsonata_python-0.5.3.dist-info → jsonata_python-0.6.1.dist-info}/licenses/LICENSE +0 -0
jsonata/cli/__main__.py
CHANGED
|
@@ -32,9 +32,9 @@ from jsonata import functions, jexception, jsonata, timebox
|
|
|
32
32
|
def get_options(argv: Optional[list[str]] = None) -> argparse.ArgumentParser:
|
|
33
33
|
"""Parses command-line arguments.
|
|
34
34
|
"""
|
|
35
|
-
parser = argparse.ArgumentParser(prog="jsonata
|
|
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.
|
|
37
|
+
"-v", "--version", action='version', version='%(prog)s 0.6.1')
|
|
38
38
|
|
|
39
39
|
parser.add_argument(
|
|
40
40
|
"-e", "--expression", metavar="<file>",
|
jsonata/functions.py
CHANGED
|
@@ -441,6 +441,13 @@ class Functions:
|
|
|
441
441
|
if char is None or not char:
|
|
442
442
|
char = " "
|
|
443
443
|
|
|
444
|
+
# match JS: truncate width to integer
|
|
445
|
+
if width is not None:
|
|
446
|
+
try:
|
|
447
|
+
width = int(width)
|
|
448
|
+
except Exception:
|
|
449
|
+
width = 0
|
|
450
|
+
|
|
444
451
|
if width < 0:
|
|
445
452
|
result = Functions.left_pad(string, -width, char)
|
|
446
453
|
else:
|
|
@@ -722,7 +729,7 @@ class Functions:
|
|
|
722
729
|
r = None
|
|
723
730
|
for i in range(0, 10):
|
|
724
731
|
try:
|
|
725
|
-
r = re.sub(pattern, replacement, s, 1)
|
|
732
|
+
r = re.sub(pattern, replacement, s, count=1)
|
|
726
733
|
break
|
|
727
734
|
except Exception as e:
|
|
728
735
|
msg = str(e)
|
|
@@ -2098,7 +2105,8 @@ class Functions:
|
|
|
2098
2105
|
dt = datetime.datetime.strptime(timestamp, "%Y")
|
|
2099
2106
|
else:
|
|
2100
2107
|
dt = datetime.datetime.fromisoformat(timestamp)
|
|
2101
|
-
|
|
2108
|
+
if dt.tzinfo is None:
|
|
2109
|
+
dt = dt.replace(tzinfo=datetime.timezone.utc)
|
|
2102
2110
|
return int(dt.timestamp() * 1000)
|
|
2103
2111
|
# try:
|
|
2104
2112
|
# size = len(timestamp)
|
jsonata/jsonata.py
CHANGED
|
@@ -800,9 +800,9 @@ class Jsonata:
|
|
|
800
800
|
|
|
801
801
|
result = None
|
|
802
802
|
if op == "=":
|
|
803
|
-
result =
|
|
803
|
+
result = utils.Utils.is_deep_equal(lhs, rhs)
|
|
804
804
|
elif op == "!=":
|
|
805
|
-
result =
|
|
805
|
+
result = not utils.Utils.is_deep_equal(lhs, rhs)
|
|
806
806
|
return result
|
|
807
807
|
|
|
808
808
|
#
|
jsonata/parser.py
CHANGED
|
@@ -529,6 +529,12 @@ class Parser:
|
|
|
529
529
|
# if/then/else ternary operator ?:
|
|
530
530
|
self.register(Parser.InfixTernaryOperator(self, tokenizer.Tokenizer.operators["?"]))
|
|
531
531
|
|
|
532
|
+
# coalescing operator ??
|
|
533
|
+
self.register(Parser.InfixCoalesce(self, tokenizer.Tokenizer.operators["??"]))
|
|
534
|
+
|
|
535
|
+
# elvis/default operator ?:
|
|
536
|
+
self.register(Parser.InfixDefault(self, tokenizer.Tokenizer.operators["?:"]))
|
|
537
|
+
|
|
532
538
|
# object transformer
|
|
533
539
|
self.register(Parser.PrefixObjectTransformer(self))
|
|
534
540
|
|
|
@@ -854,6 +860,43 @@ class Parser:
|
|
|
854
860
|
self._else = self._outer_instance.expression(0)
|
|
855
861
|
return self
|
|
856
862
|
|
|
863
|
+
class InfixCoalesce(Infix):
|
|
864
|
+
_outer_instance: 'Parser'
|
|
865
|
+
|
|
866
|
+
def __init__(self, outer_instance, get):
|
|
867
|
+
super().__init__(outer_instance, "??", get)
|
|
868
|
+
self._outer_instance = outer_instance
|
|
869
|
+
|
|
870
|
+
def led(self, left):
|
|
871
|
+
self.type = "condition"
|
|
872
|
+
# condition becomes function exists(left)
|
|
873
|
+
cond = Parser.Symbol(self._outer_instance)
|
|
874
|
+
cond.type = "function"
|
|
875
|
+
cond.value = "("
|
|
876
|
+
proc = Parser.Symbol(self._outer_instance)
|
|
877
|
+
proc.type = "variable"
|
|
878
|
+
proc.value = "exists"
|
|
879
|
+
cond.procedure = proc
|
|
880
|
+
cond.arguments = [left]
|
|
881
|
+
self.condition = cond
|
|
882
|
+
self.then = left
|
|
883
|
+
self._else = self._outer_instance.expression(0)
|
|
884
|
+
return self
|
|
885
|
+
|
|
886
|
+
class InfixDefault(Infix):
|
|
887
|
+
_outer_instance: 'Parser'
|
|
888
|
+
|
|
889
|
+
def __init__(self, outer_instance, get):
|
|
890
|
+
super().__init__(outer_instance, "?:", get)
|
|
891
|
+
self._outer_instance = outer_instance
|
|
892
|
+
|
|
893
|
+
def led(self, left):
|
|
894
|
+
self.type = "condition"
|
|
895
|
+
self.condition = left
|
|
896
|
+
self.then = left
|
|
897
|
+
self._else = self._outer_instance.expression(0)
|
|
898
|
+
return self
|
|
899
|
+
|
|
857
900
|
class PrefixObjectTransformer(Prefix):
|
|
858
901
|
_outer_instance: 'Parser'
|
|
859
902
|
|
jsonata/tokenizer.py
CHANGED
|
@@ -65,6 +65,8 @@ class Tokenizer:
|
|
|
65
65
|
'<=': 40,
|
|
66
66
|
'>=': 40,
|
|
67
67
|
'~>': 40,
|
|
68
|
+
'?:': 40,
|
|
69
|
+
'??': 40,
|
|
68
70
|
'and': 30,
|
|
69
71
|
'or': 25,
|
|
70
72
|
'in': 40,
|
|
@@ -216,6 +218,14 @@ class Tokenizer:
|
|
|
216
218
|
# ~> chain function
|
|
217
219
|
self.position += 2
|
|
218
220
|
return self.create("operator", "~>")
|
|
221
|
+
if current_char == '?' and have_more and self.path[self.position + 1] == ':':
|
|
222
|
+
# ?: default / elvis operator
|
|
223
|
+
self.position += 2
|
|
224
|
+
return self.create("operator", "?:")
|
|
225
|
+
if current_char == '?' and have_more and self.path[self.position + 1] == '?':
|
|
226
|
+
# ?? coalescing operator
|
|
227
|
+
self.position += 2
|
|
228
|
+
return self.create("operator", "??")
|
|
219
229
|
# test for single char operators
|
|
220
230
|
if Tokenizer.operators.get(str(current_char)) is not None:
|
|
221
231
|
self.position += 1
|
jsonata/utils.py
CHANGED
|
@@ -90,6 +90,27 @@ class Utils:
|
|
|
90
90
|
sequence.sequence = True
|
|
91
91
|
return sequence
|
|
92
92
|
|
|
93
|
+
@staticmethod
|
|
94
|
+
def is_deep_equal(lhs: Optional[Any], rhs: Optional[Any]) -> bool:
|
|
95
|
+
if isinstance(lhs, list) and isinstance(rhs, list):
|
|
96
|
+
if len(lhs) != len(rhs):
|
|
97
|
+
return False
|
|
98
|
+
for ii, _ in enumerate(lhs):
|
|
99
|
+
if not Utils.is_deep_equal(lhs[ii], rhs[ii]):
|
|
100
|
+
return False
|
|
101
|
+
return True
|
|
102
|
+
elif isinstance(lhs, dict) and isinstance(rhs, dict):
|
|
103
|
+
if lhs.keys() != rhs.keys():
|
|
104
|
+
return False
|
|
105
|
+
for key in lhs.keys():
|
|
106
|
+
if not Utils.is_deep_equal(lhs[key], rhs[key]):
|
|
107
|
+
return False
|
|
108
|
+
return True
|
|
109
|
+
if lhs == rhs and type(lhs) == type(rhs):
|
|
110
|
+
return True
|
|
111
|
+
|
|
112
|
+
return False
|
|
113
|
+
|
|
93
114
|
class JList(list):
|
|
94
115
|
sequence: bool
|
|
95
116
|
outer_wrapper: bool
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jsonata-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.1
|
|
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
|
|
@@ -235,7 +235,7 @@ The JSONata documentation can be found [here](https://jsonata.org).
|
|
|
235
235
|
## Installation
|
|
236
236
|
|
|
237
237
|
```
|
|
238
|
-
|
|
238
|
+
pipx install jsonata-python
|
|
239
239
|
```
|
|
240
240
|
|
|
241
241
|
## Getting Started
|
|
@@ -256,8 +256,8 @@ A very simple start:
|
|
|
256
256
|
The CLI provides the same functionality as the [Dashjoin JSONata CLI](https://github.com/dashjoin/jsonata-cli).
|
|
257
257
|
|
|
258
258
|
```
|
|
259
|
-
%
|
|
260
|
-
usage: jsonata
|
|
259
|
+
% jsonata -h
|
|
260
|
+
usage: jsonata [-h] [-v] [-e <file>] [-i <arg>] [-ic <arg>] [-f {auto,json,string}] [-o <arg>] [-oc <arg>] [-time] [-c] [-b <json-string>]
|
|
261
261
|
[-bf <file>] [-it]
|
|
262
262
|
[expr]
|
|
263
263
|
|
|
@@ -293,19 +293,19 @@ options:
|
|
|
293
293
|
### Examples
|
|
294
294
|
|
|
295
295
|
```
|
|
296
|
-
% echo '{"a":"hello", "b":" world"}' |
|
|
296
|
+
% echo '{"a":"hello", "b":" world"}' | jsonata '(a & b)'
|
|
297
297
|
hello world
|
|
298
298
|
|
|
299
|
-
% echo '{"a":"hello", "b":" world"}' |
|
|
299
|
+
% echo '{"a":"hello", "b":" world"}' | jsonata -o helloworld.json $
|
|
300
300
|
# helloworld.json written
|
|
301
301
|
|
|
302
|
-
% ls |
|
|
302
|
+
% ls | jsonata $
|
|
303
303
|
helloworld.json
|
|
304
304
|
|
|
305
|
-
% ps -o pid="",%cpu="",%mem="" |
|
|
305
|
+
% ps -o pid="",%cpu="",%mem="" | jsonata '$.$split(/\n/).$trim().[ $split(/\s+/)[$length()>0].$number() ]' -c
|
|
306
306
|
[[4105,0,0],[4646,0,0],[4666,0,0],[33696,0,0]...]
|
|
307
307
|
|
|
308
|
-
% curl -s https://raw.githubusercontent.com/jsonata-js/jsonata/master/test/test-suite/datasets/dataset1.json |
|
|
308
|
+
% curl -s https://raw.githubusercontent.com/jsonata-js/jsonata/master/test/test-suite/datasets/dataset1.json | jsonata '{"Name": FirstName & " " & Surname, "Cities": **.City, "Emails": Email[type="home"].address}'
|
|
309
309
|
{
|
|
310
310
|
"Name": "Fred Smith",
|
|
311
311
|
"Cities": [
|
|
@@ -318,7 +318,7 @@ helloworld.json
|
|
|
318
318
|
]
|
|
319
319
|
}
|
|
320
320
|
|
|
321
|
-
%
|
|
321
|
+
% jsonata -i helloworld.json -it
|
|
322
322
|
Enter an expression to have it evaluated.
|
|
323
323
|
JSONata> (a & b)
|
|
324
324
|
hello world
|
|
@@ -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=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,,
|
|
@@ -1,17 +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=giAtWZ92cOlnBcH7Zkapnib-LPSPyBFHrz-9AMdkhqQ,75500
|
|
5
|
-
jsonata/jexception.py,sha256=6Jz7WMsIiNlQ7-1Hq8RKiE2HxcHq2PDekw0qsSe3lqo,12885
|
|
6
|
-
jsonata/jsonata.py,sha256=jZIxVrNcZI3aBvE0PURZ4-cxpaK9JiJVH5Q_cllCXS0,84247
|
|
7
|
-
jsonata/parser.py,sha256=U8nNxvsDIy0wVTfNCs2DNN7RjNVm0SqfociD9cRcsWM,53877
|
|
8
|
-
jsonata/signature.py,sha256=j7eNKUuGx_9vCt5Qv8BPM7iV5vH26U0Kx8zrkDcctME,20194
|
|
9
|
-
jsonata/timebox.py,sha256=bnevNR_ONvKUiIZCJZEWsRiR0gCWTGOwn5RCY7dKqYc,2861
|
|
10
|
-
jsonata/tokenizer.py,sha256=X-JsARtkBIN6bO8_TElpw3SCageQMtfBWlexuhG2Sds,11982
|
|
11
|
-
jsonata/utils.py,sha256=U13I49Ie3hEn3PKGR4361TPengDAkbyHmwipDFZJlXo,5192
|
|
12
|
-
jsonata/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
-
jsonata/cli/__main__.py,sha256=d_tNQ3Y_yN9o_NzBip8LdhsAVLAAA62GeowFKc6zx3Y,7125
|
|
14
|
-
jsonata_python-0.5.3.dist-info/METADATA,sha256=_qkeeFX_iFWyljejtPGrx3Xjt8mgkX0tKIkTk_-uNlc,17442
|
|
15
|
-
jsonata_python-0.5.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
16
|
-
jsonata_python-0.5.3.dist-info/licenses/LICENSE,sha256=y16Ofl9KOYjhBjwULGDcLfdWBfTEZRXnduOspt-XbhQ,11325
|
|
17
|
-
jsonata_python-0.5.3.dist-info/RECORD,,
|
|
File without changes
|