omlish 0.0.0.dev117__py3-none-any.whl → 0.0.0.dev118__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,119 +1,258 @@
1
+ import abc
2
+ import dataclasses as dc
1
3
  import typing as ta
2
4
 
5
+ from ... import lang
3
6
 
4
- class Node(ta.TypedDict):
5
- type: str
6
- children: list['Node']
7
- value: ta.NotRequired[ta.Any]
8
7
 
8
+ @dc.dataclass(frozen=True)
9
+ class Node(lang.Abstract):
10
+ @property
11
+ @abc.abstractmethod
12
+ def children(self) -> ta.Sequence['Node']:
13
+ raise NotImplementedError
9
14
 
10
- def arithmetic_unary(operator, expression) -> Node:
11
- return {'type': 'arithmetic_unary', 'children': [expression], 'value': operator}
12
15
 
16
+ @dc.dataclass(frozen=True)
17
+ class LeafNode(Node, lang.Abstract):
18
+ @property
19
+ def children(self) -> ta.Sequence[Node]:
20
+ return []
13
21
 
14
- def arithmetic(operator, left, right) -> Node:
15
- return {'type': 'arithmetic', 'children': [left, right], 'value': operator}
16
22
 
23
+ @dc.dataclass(frozen=True)
24
+ class ArithmeticUnary(Node, lang.Final):
25
+ operator: str
26
+ expression: Node
17
27
 
18
- def assign(name, expr) -> Node:
19
- return {'type': 'assign', 'children': [expr], 'value': name}
28
+ @property
29
+ def children(self) -> ta.Sequence[Node]:
30
+ return [self.expression]
20
31
 
21
32
 
22
- def comparator(name, first, second) -> Node:
23
- return {'type': 'comparator', 'children': [first, second], 'value': name}
33
+ @dc.dataclass(frozen=True)
34
+ class Arithmetic(Node, lang.Final):
35
+ operator: str
36
+ left: Node
37
+ right: Node
24
38
 
39
+ @property
40
+ def children(self) -> ta.Sequence[Node]:
41
+ return [self.left, self.right]
25
42
 
26
- def current_node() -> Node:
27
- return {'type': 'current', 'children': []}
28
43
 
44
+ @dc.dataclass(frozen=True)
45
+ class Assign(Node, lang.Final):
46
+ name: str
47
+ expr: Node
29
48
 
30
- def root_node() -> Node:
31
- return {'type': 'root', 'children': []}
49
+ @property
50
+ def children(self) -> ta.Sequence[Node]:
51
+ return [self.expr]
32
52
 
33
53
 
34
- def expref(expression) -> Node:
35
- return {'type': 'expref', 'children': [expression]}
54
+ @dc.dataclass(frozen=True)
55
+ class Comparator(Node, lang.Final):
56
+ name: str
57
+ first: Node
58
+ second: Node
36
59
 
60
+ @property
61
+ def children(self) -> ta.Sequence[Node]:
62
+ return [self.first, self.second]
37
63
 
38
- def function_expression(name, args) -> Node:
39
- return {'type': 'function_expression', 'children': args, 'value': name}
40
64
 
65
+ @dc.dataclass(frozen=True)
66
+ class CurrentNode(LeafNode, lang.Final):
67
+ pass
41
68
 
42
- def field(name) -> Node:
43
- return {'type': 'field', 'children': [], 'value': name}
44
69
 
70
+ @dc.dataclass(frozen=True)
71
+ class RootNode(LeafNode, lang.Final):
72
+ pass
45
73
 
46
- def filter_projection(left, right, comparator) -> Node:
47
- return {'type': 'filter_projection', 'children': [left, right, comparator]}
48
74
 
75
+ @dc.dataclass(frozen=True)
76
+ class Expref(Node, lang.Final):
77
+ expression: Node
49
78
 
50
- def flatten(node) -> Node:
51
- return {'type': 'flatten', 'children': [node]}
79
+ @property
80
+ def children(self) -> ta.Sequence[Node]:
81
+ return [self.expression]
52
82
 
53
83
 
54
- def identity() -> Node:
55
- return {'type': 'identity', 'children': []}
84
+ @dc.dataclass(frozen=True)
85
+ class FunctionExpression(Node, lang.Final):
86
+ name: str
87
+ args: ta.Sequence[Node]
56
88
 
89
+ @property
90
+ def children(self) -> ta.Sequence[Node]:
91
+ return tuple(self.args)
57
92
 
58
- def index(index) -> Node:
59
- return {'type': 'index', 'value': index, 'children': []}
60
93
 
94
+ @dc.dataclass(frozen=True)
95
+ class Field(LeafNode, lang.Final):
96
+ name: str
61
97
 
62
- def index_expression(children) -> Node:
63
- return {'type': 'index_expression', 'children': children}
64
98
 
99
+ @dc.dataclass(frozen=True)
100
+ class FilterProjection(Node, lang.Final):
101
+ left: Node
102
+ right: Node
103
+ comparator: Node
65
104
 
66
- def key_val_pair(key_name, node) -> Node:
67
- return {'type': 'key_val_pair', 'children': [node], 'value': key_name}
105
+ @property
106
+ def children(self) -> ta.Sequence[Node]:
107
+ return [self.left, self.right, self.comparator]
68
108
 
69
109
 
70
- def let_expression(bindings, expr) -> Node:
71
- return {'type': 'let_expression', 'children': [*bindings, expr]}
110
+ @dc.dataclass(frozen=True)
111
+ class Flatten(Node, lang.Final):
112
+ node: Node
72
113
 
114
+ @property
115
+ def children(self) -> ta.Sequence[Node]:
116
+ return [self.node]
73
117
 
74
- def literal(literal_value) -> Node:
75
- return {'type': 'literal', 'value': literal_value, 'children': []}
76
118
 
119
+ @dc.dataclass(frozen=True)
120
+ class Identity(LeafNode, lang.Final):
121
+ pass
77
122
 
78
- def multi_select_dict(nodes) -> Node:
79
- return {'type': 'multi_select_dict', 'children': nodes}
80
123
 
124
+ @dc.dataclass(frozen=True)
125
+ class Index(LeafNode, lang.Final):
126
+ index: int
81
127
 
82
- def multi_select_list(nodes) -> Node:
83
- return {'type': 'multi_select_list', 'children': nodes}
84
128
 
129
+ @dc.dataclass(frozen=True)
130
+ class IndexExpression(Node, lang.Final):
131
+ nodes: ta.Sequence[Node]
85
132
 
86
- def or_expression(left, right) -> Node:
87
- return {'type': 'or_expression', 'children': [left, right]}
133
+ @property
134
+ def children(self) -> ta.Sequence[Node]:
135
+ return tuple(self.nodes)
88
136
 
89
137
 
90
- def and_expression(left, right) -> Node:
91
- return {'type': 'and_expression', 'children': [left, right]}
138
+ @dc.dataclass(frozen=True)
139
+ class KeyValPair(Node, lang.Final):
140
+ key_name: str
141
+ node: Node
92
142
 
143
+ @property
144
+ def children(self) -> ta.Sequence[Node]:
145
+ return [self.node]
93
146
 
94
- def not_expression(expr) -> Node:
95
- return {'type': 'not_expression', 'children': [expr]}
96
147
 
148
+ @dc.dataclass(frozen=True)
149
+ class LetExpression(Node, lang.Final):
150
+ bindings: ta.Sequence[Node]
151
+ expr: Node
97
152
 
98
- def pipe(left: Node, right: Node) -> Node:
99
- return {'type': 'pipe', 'children': [left, right]}
153
+ @property
154
+ def children(self) -> ta.Sequence[Node]:
155
+ return [*self.bindings, self.expr]
100
156
 
101
157
 
102
- def projection(left: Node, right: Node) -> Node:
103
- return {'type': 'projection', 'children': [left, right]}
158
+ @dc.dataclass(frozen=True)
159
+ class Literal(LeafNode, lang.Final):
160
+ literal_value: ta.Any
104
161
 
105
162
 
106
- def subexpression(children) -> Node:
107
- return {'type': 'subexpression', 'children': children}
163
+ @dc.dataclass(frozen=True)
164
+ class MultiSelectDict(Node, lang.Final):
165
+ nodes: ta.Sequence[KeyValPair]
108
166
 
167
+ @property
168
+ def children(self) -> ta.Sequence[Node]:
169
+ return tuple(self.nodes)
109
170
 
110
- def slice(start, end, step) -> Node: # noqa
111
- return {'type': 'slice', 'children': [start, end, step]}
112
171
 
172
+ @dc.dataclass(frozen=True)
173
+ class MultiSelectList(Node, lang.Final):
174
+ nodes: ta.Sequence[Node]
113
175
 
114
- def value_projection(left: Node, right: Node) -> Node:
115
- return {'type': 'value_projection', 'children': [left, right]}
176
+ @property
177
+ def children(self) -> ta.Sequence[Node]:
178
+ return tuple(self.nodes)
116
179
 
117
180
 
118
- def variable_ref(name: str) -> Node:
119
- return {'type': 'variable_ref', 'children': [], 'value': name}
181
+ @dc.dataclass(frozen=True)
182
+ class OrExpression(Node, lang.Final):
183
+ left: Node
184
+ right: Node
185
+
186
+ @property
187
+ def children(self) -> ta.Sequence[Node]:
188
+ return [self.left, self.right]
189
+
190
+
191
+ @dc.dataclass(frozen=True)
192
+ class AndExpression(Node, lang.Final):
193
+ left: Node
194
+ right: Node
195
+
196
+ @property
197
+ def children(self) -> ta.Sequence[Node]:
198
+ return [self.left, self.right]
199
+
200
+
201
+ @dc.dataclass(frozen=True)
202
+ class NotExpression(Node, lang.Final):
203
+ expr: Node
204
+
205
+ @property
206
+ def children(self) -> ta.Sequence[Node]:
207
+ return [self.expr]
208
+
209
+
210
+ @dc.dataclass(frozen=True)
211
+ class Pipe(Node, lang.Final):
212
+ left: Node
213
+ right: Node
214
+
215
+ @property
216
+ def children(self) -> ta.Sequence[Node]:
217
+ return [self.left, self.right]
218
+
219
+
220
+ @dc.dataclass(frozen=True)
221
+ class Projection(Node, lang.Final):
222
+ left: Node
223
+ right: Node
224
+
225
+ @property
226
+ def children(self) -> ta.Sequence[Node]:
227
+ return [self.left, self.right]
228
+
229
+
230
+ @dc.dataclass(frozen=True)
231
+ class Subexpression(Node, lang.Final):
232
+ children_nodes: ta.Sequence[Node]
233
+
234
+ @property
235
+ def children(self) -> ta.Sequence[Node]:
236
+ return tuple(self.children_nodes)
237
+
238
+
239
+ @dc.dataclass(frozen=True)
240
+ class Slice(LeafNode, lang.Final):
241
+ start: int | None
242
+ end: int | None
243
+ step: int | None
244
+
245
+
246
+ @dc.dataclass(frozen=True)
247
+ class ValueProjection(Node, lang.Final):
248
+ left: Node
249
+ right: Node
250
+
251
+ @property
252
+ def children(self) -> ta.Sequence[Node]:
253
+ return [self.left, self.right]
254
+
255
+
256
+ @dc.dataclass(frozen=True)
257
+ class VariableRef(LeafNode, lang.Final):
258
+ name: str
@@ -1,35 +1,49 @@
1
1
  #!/usr/bin/env python3
2
2
  import argparse
3
- import json
4
- import pprint
3
+ import dataclasses as dc
5
4
  import sys
5
+ import typing as ta
6
6
 
7
- from . import exceptions
7
+ from ...formats import json
8
+ from .ast import Node
9
+ from .exceptions import ArityError
10
+ from .exceptions import JmespathTypeError
11
+ from .exceptions import JmespathValueError
12
+ from .exceptions import ParseError
13
+ from .exceptions import UnknownFunctionError
8
14
  from .parser import compile
9
15
  from .parser import search
16
+ from .visitor import node_type
10
17
 
11
18
 
12
- def _main():
19
+ def _ast_to_json(o: ta.Any) -> ta.Any:
20
+ if isinstance(o, json.SCALAR_TYPES):
21
+ return o
22
+ elif isinstance(o, Node):
23
+ return {node_type(o): {f.name: _ast_to_json(getattr(o, f.name)) for f in dc.fields(o)}}
24
+ elif isinstance(o, (list, tuple)):
25
+ return [_ast_to_json(e) for e in o]
26
+ else:
27
+ raise TypeError(o)
28
+
29
+
30
+ def _main() -> int:
13
31
  parser = argparse.ArgumentParser()
14
32
  parser.add_argument('expression')
15
- parser.add_argument(
16
- '-f',
17
- '--filename',
18
- help='The filename containing the input data. If a filename is not given then data is read from stdin.',
19
- )
20
- parser.add_argument(
21
- '--ast',
22
- action='store_true',
23
- help='Pretty print the AST, do not search the data.',
24
- )
33
+ parser.add_argument('-f', '--filename')
34
+ parser.add_argument('-c', '--compact', action='store_true')
35
+ parser.add_argument('--ast', action='store_true')
25
36
  args = parser.parse_args()
26
37
 
38
+ if args.compact:
39
+ json_dumps = json.dumps_compact
40
+ else:
41
+ json_dumps = json.dumps_pretty
42
+
27
43
  expression = args.expression
28
44
  if args.ast:
29
- # Only print the AST
30
45
  expression = compile(args.expression)
31
- sys.stdout.write(pprint.pformat(expression.parsed))
32
- sys.stdout.write('\n')
46
+ print(json_dumps(_ast_to_json(expression.parsed)))
33
47
  return 0
34
48
 
35
49
  if args.filename:
@@ -40,27 +54,27 @@ def _main():
40
54
  data = json.loads(data)
41
55
 
42
56
  try:
43
- sys.stdout.write(json.dumps(search(expression, data), indent=4, ensure_ascii=False))
44
- sys.stdout.write('\n')
57
+ print(json_dumps(search(expression, data), ensure_ascii=False))
58
+ return 0
45
59
 
46
- except exceptions.ArityError as e:
47
- sys.stderr.write(f'invalid-arity: {e}\n')
60
+ except ArityError as e:
61
+ print(f'invalid-arity: {e}', file=sys.stderr)
48
62
  return 1
49
63
 
50
- except exceptions.JmespathTypeError as e:
51
- sys.stderr.write(f'invalid-type: {e}\n')
64
+ except JmespathTypeError as e:
65
+ print(f'invalid-type: {e}', file=sys.stderr)
52
66
  return 1
53
67
 
54
- except exceptions.JmespathValueError as e:
55
- sys.stderr.write(f'invalid-value: {e}\n')
68
+ except JmespathValueError as e:
69
+ print(f'invalid-value: {e}', file=sys.stderr)
56
70
  return 1
57
71
 
58
- except exceptions.UnknownFunctionError as e:
59
- sys.stderr.write(f'unknown-function: {e}\n')
72
+ except UnknownFunctionError as e:
73
+ print(f'unknown-function: {e}', file=sys.stderr)
60
74
  return 1
61
75
 
62
- except exceptions.ParseError as e:
63
- sys.stderr.write(f'syntax-error: {e}\n')
76
+ except ParseError as e:
77
+ print(f'syntax-error: {e}', file=sys.stderr)
64
78
  return 1
65
79
 
66
80