jsonata-python 0.5.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/__init__.py ADDED
@@ -0,0 +1,10 @@
1
+ from jsonata.constants import Constants
2
+ from jsonata.datetimeutils import DateTimeUtils
3
+ from jsonata.functions import Functions
4
+ from jsonata.jexception import JException
5
+ from jsonata.jsonata import Jsonata
6
+ from jsonata.parser import Parser
7
+ from jsonata.signature import Signature
8
+ from jsonata.timebox import Timebox
9
+ from jsonata.tokenizer import Tokenizer
10
+ from jsonata.utils import Utils
File without changes
@@ -0,0 +1,242 @@
1
+ #
2
+ # Copyright Robert Yokota
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License")
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+ # Derived from the following code:
17
+ #
18
+ # Project name: jsonata-cli
19
+ # Copyright Dashjoin GmbH. https://dashjoin.com
20
+ # Licensed under the Apache License, Version 2.0 (the "License")
21
+ #
22
+
23
+ import argparse
24
+ import cmd
25
+ import json
26
+ import sys
27
+ from typing import Any, Optional
28
+
29
+ from jsonata import functions, jexception, jsonata, timebox
30
+
31
+
32
+ def get_options(argv: Optional[list[str]] = None) -> argparse.ArgumentParser:
33
+ """Parses command-line arguments.
34
+ """
35
+ parser = argparse.ArgumentParser(prog="jsonata.cli", description="Pure Python JSONata CLI")
36
+ parser.add_argument(
37
+ "-v", "--version", action='version', version='%(prog)s 0.5.2')
38
+
39
+ parser.add_argument(
40
+ "-e", "--expression", metavar="<file>",
41
+ help="JSON expression to evaluate."
42
+ )
43
+ parser.add_argument(
44
+ "-i", "--input", metavar="<arg>",
45
+ help="JSON input file (- for stdin)"
46
+ )
47
+ parser.add_argument(
48
+ "-ic", "--icharset", default="utf-8", metavar="<arg>",
49
+ help="Input character set (default=utf-8)"
50
+ )
51
+ parser.add_argument(
52
+ "-f", "--format", choices=['auto', 'json', 'string'], default="auto",
53
+ help="Input format (default=auto)"
54
+ )
55
+ parser.add_argument(
56
+ "-o", "--output", metavar="<arg>",
57
+ help="JSON output file (- for stdin)"
58
+ )
59
+ parser.add_argument(
60
+ "-oc", "--ocharset", default="utf-8", metavar="<arg>",
61
+ help="Output character set (default=utf-8)"
62
+ )
63
+ parser.add_argument(
64
+ "-time", default=False, action="store_true",
65
+ help="Print performance timers to stderr"
66
+ )
67
+ parser.add_argument(
68
+ "-c", "--compact", default=False, action="store_true",
69
+ help="Compact JSON output (don't prettify)"
70
+ )
71
+ parser.add_argument(
72
+ "-b", "--bindings", metavar="<json-string>",
73
+ help="JSONata variable bindings"
74
+ )
75
+ parser.add_argument(
76
+ "-bf", "--bindings-file", dest="bindings_file", metavar="<file>",
77
+ help="JSONata variable bindings file"
78
+ )
79
+ parser.add_argument(
80
+ "-it", "--interactive", default=False, action="store_true",
81
+ help="Interactive REPL"
82
+ )
83
+
84
+ # The expression
85
+ parser.add_argument(
86
+ "expr", nargs='?')
87
+
88
+ return parser
89
+
90
+
91
+ class JsonataREPL(cmd.Cmd):
92
+ prompt = "JSONata> "
93
+ intro = "Enter an expression to have it evaluated."
94
+
95
+ def __init__(self, doc, bindings):
96
+ super().__init__()
97
+ self.doc = doc
98
+ self.bindings = bindings
99
+
100
+ def jsonata_eval(self, text: str) -> Optional[Any]:
101
+ try:
102
+ j = jsonata.Jsonata.jsonata(text)
103
+ frame = j.create_frame()
104
+ for k, v in self.bindings.items():
105
+ frame.bind(k, v)
106
+ return j.evaluate(self.doc, frame)
107
+ except jexception.JException as ex:
108
+ print("JSONata error: " + str(ex) + "\n")
109
+ raise
110
+
111
+ def preloop(self) -> None:
112
+ pass
113
+
114
+ def do_set(self, args: str) -> bool:
115
+ """Set variable expression
116
+
117
+ Evaluates the expression, saves the result as the given variable in the current activation.
118
+ """
119
+ name, space, args = args.partition(' ')
120
+ value = json.loads(args)
121
+ print(value)
122
+ self.bindings[name] = value
123
+ return False
124
+
125
+ def do_show(self, args: str) -> bool:
126
+ """Shows all variables in the current activation."""
127
+ print(self.bindings)
128
+ return False
129
+
130
+ def do_quit(self, args: str) -> bool:
131
+ """Quits from the REPL."""
132
+ return True
133
+
134
+ do_exit = do_quit
135
+
136
+ def default(self, args: str) -> bool:
137
+ """Evaluate an expression."""
138
+ try:
139
+ value = self.jsonata_eval(args)
140
+ print(value)
141
+ except Exception as ex:
142
+ pass
143
+ return False
144
+
145
+
146
+ def read_input(inp: str, format: str) -> str:
147
+ if format == "auto":
148
+ try:
149
+ return json.loads(inp)
150
+ except json.JSONDecodeError:
151
+ return inp
152
+ elif format == "json":
153
+ return json.loads(inp)
154
+ elif format == "string":
155
+ return inp
156
+
157
+
158
+ def main(argv: Optional[list[str]] = None) -> int:
159
+ parser = get_options(argv)
160
+ options = parser.parse_args(argv)
161
+
162
+ if options.expression is None and options.expr is None:
163
+ parser.print_help()
164
+ return 1
165
+
166
+ icharset = options.icharset
167
+ ocharset = options.icharset
168
+
169
+ expr_file = options.expression
170
+ if expr_file is None:
171
+ expr = options.expr
172
+ else:
173
+ with open(expr_file, 'r', encoding=icharset) as fd:
174
+ expr = fd.read()
175
+
176
+ prettify = not options.compact
177
+
178
+ bindings_file = options.bindings_file
179
+ if bindings_file is None:
180
+ bindings_str = options.bindings
181
+ else:
182
+ with open(bindings_file, 'r', encoding=icharset) as fd:
183
+ bindings_str = fd.read()
184
+ if bindings_str is None:
185
+ bindings = {}
186
+ else:
187
+ bindings = json.loads(bindings_str)
188
+
189
+ if options.input == '-' or options.input is None:
190
+ input = sys.stdin.read()
191
+ else:
192
+ with open(options.input, 'r', encoding=icharset) as fd:
193
+ input = fd.read()
194
+
195
+ t0 = timebox.Timebox.current_milli_time()
196
+
197
+ format = options.format
198
+ doc = read_input(input, format)
199
+
200
+ t1 = timebox.Timebox.current_milli_time()
201
+
202
+ if options.interactive:
203
+ repl = JsonataREPL(doc, bindings)
204
+ repl.cmdloop()
205
+ return 0
206
+
207
+ try:
208
+ j = jsonata.Jsonata.jsonata(expr)
209
+ frame = j.create_frame()
210
+ for k, v in bindings.items():
211
+ frame.bind(k, v)
212
+
213
+ t2 = timebox.Timebox.current_milli_time()
214
+
215
+ result = j.evaluate(doc, frame)
216
+
217
+ t3 = timebox.Timebox.current_milli_time()
218
+
219
+ s = functions.Functions.string(result, prettify)
220
+
221
+ output = options.output
222
+ if output is None:
223
+ print(s)
224
+ else:
225
+ with open(output, 'w', encoding=ocharset) as fd:
226
+ fd.write(s)
227
+
228
+ t4 = timebox.Timebox.current_milli_time()
229
+
230
+ if options.time:
231
+ sys.stderr.write("Performance(millis): total=" + str(t4-t0) + " t(in)=" + str(t1-t0) +
232
+ " t(parse)=" + str(t2-t1) + " t(eval)="+str(t3-t2) + " t(out)=" + str(t4-t3) + "\n")
233
+ except jexception.JException as ex:
234
+ sys.stderr.write("JSONata error: " + str(ex) + "\n")
235
+ return 1
236
+
237
+ return 0
238
+
239
+
240
+ if __name__ == "__main__":
241
+ ret = main(sys.argv[1:])
242
+ sys.exit(ret)
jsonata/constants.py ADDED
@@ -0,0 +1,68 @@
1
+ #
2
+ # Copyright Robert Yokota
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License")
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+ # Derived from the following code:
17
+ #
18
+ # Project name: jsonata-java
19
+ # Copyright Dashjoin GmbH. https://dashjoin.com
20
+ # Licensed under the Apache License, Version 2.0 (the "License")
21
+ #
22
+
23
+ #
24
+ # Constants required by DateTimeUtils
25
+ #
26
+ class Constants:
27
+ ERR_MSG_SEQUENCE_UNSUPPORTED = "Formatting or parsing an integer as a sequence starting with %s is not supported by this implementation"
28
+ ERR_MSG_DIFF_DECIMAL_GROUP = "In a decimal digit pattern, all digits must be from the same decimal group"
29
+ ERR_MSG_NO_CLOSING_BRACKET = "No matching closing bracket ']' in date/time picture string"
30
+ ERR_MSG_UNKNOWN_COMPONENT_SPECIFIER = "Unknown component specifier %s in date/time picture string"
31
+ ERR_MSG_INVALID_NAME_MODIFIER = "The 'name' modifier can only be applied to months and days in the date/time picture string, not %s"
32
+ ERR_MSG_TIMEZONE_FORMAT = "The timezone integer format specifier cannot have more than four digits"
33
+ ERR_MSG_MISSING_FORMAT = "The date/time picture string is missing specifiers required to parse the timestamp"
34
+ ERR_MSG_INVALID_OPTIONS_SINGLE_CHAR = "Argument 3 of function %s is invalid. The value of the %s property must be a single character"
35
+ ERR_MSG_INVALID_OPTIONS_STRING = "Argument 3 of function %s is invalid. The value of the %s property must be a string"
36
+
37
+ #
38
+ # Collection of decimal format strings that defined by xsl:decimal-format.
39
+ #
40
+ # <pre>
41
+ # &lt;!ELEMENT xsl:decimal-format EMPTY&gt
42
+ # &lt;!ATTLIST xsl:decimal-format
43
+ # name %qname; #IMPLIED
44
+ # decimal-separator %char; "."
45
+ # grouping-separator %char; ","
46
+ # infinity CDATA "Infinity"
47
+ # minus-sign %char; "-"
48
+ # NaN CDATA "NaN"
49
+ # percent %char; "%"
50
+ # per-mille %char; "&#x2030;"
51
+ # zero-digit %char; "0"
52
+ # digit %char; "#"
53
+ # pattern-separator %char; ";"&GT
54
+ # </pre>
55
+ #
56
+ # http://www.w3.org/TR/xslt#format-number} to explain format-number in XSLT
57
+ # Specification xsl.usage advanced
58
+ #
59
+ SYMBOL_DECIMAL_SEPARATOR = "decimal-separator"
60
+ SYMBOL_GROUPING_SEPARATOR = "grouping-separator"
61
+ SYMBOL_INFINITY = "infinity"
62
+ SYMBOL_MINUS_SIGN = "minus-sign"
63
+ SYMBOL_NAN = "NaN"
64
+ SYMBOL_PERCENT = "percent"
65
+ SYMBOL_PER_MILLE = "per-mille"
66
+ SYMBOL_ZERO_DIGIT = "zero-digit"
67
+ SYMBOL_DIGIT = "digit"
68
+ SYMBOL_PATTERN_SEPARATOR = "pattern-separator"