omlish 0.0.0.dev117__py3-none-any.whl → 0.0.0.dev119__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.
- omlish/__about__.py +2 -2
- omlish/collections/hasheq.py +0 -10
- omlish/fnpairs.py +1 -10
- omlish/formats/json/__init__.py +5 -0
- omlish/formats/json/literals.py +179 -0
- omlish/formats/json/render.py +2 -3
- omlish/formats/json/stream/render.py +1 -1
- omlish/formats/json/types.py +6 -0
- omlish/lang/classes/abstract.py +37 -14
- omlish/lang/imports.py +1 -1
- omlish/lang/maybes.py +10 -12
- omlish/lite/journald.py +163 -0
- omlish/lite/logs.py +6 -2
- omlish/logs/_abc.py +53 -0
- omlish/logs/handlers.py +1 -1
- omlish/specs/jmespath/ast.py +199 -60
- omlish/specs/jmespath/cli.py +43 -29
- omlish/specs/jmespath/functions.py +397 -274
- omlish/specs/jmespath/lexer.py +2 -2
- omlish/specs/jmespath/parser.py +169 -133
- omlish/specs/jmespath/scope.py +15 -11
- omlish/specs/jmespath/visitor.py +211 -137
- omlish/testing/pytest/plugins/pydevd.py +6 -6
- {omlish-0.0.0.dev117.dist-info → omlish-0.0.0.dev119.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev117.dist-info → omlish-0.0.0.dev119.dist-info}/RECORD +29 -26
- {omlish-0.0.0.dev117.dist-info → omlish-0.0.0.dev119.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev117.dist-info → omlish-0.0.0.dev119.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev117.dist-info → omlish-0.0.0.dev119.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev117.dist-info → omlish-0.0.0.dev119.dist-info}/top_level.txt +0 -0
omlish/logs/_abc.py
CHANGED
@@ -16,27 +16,80 @@ ExceptionInfo: ta.TypeAlias = tuple[type[BaseException], BaseException, types.Tr
|
|
16
16
|
|
17
17
|
|
18
18
|
class LogRecord:
|
19
|
+
"""https://docs.python.org/3/library/logging.html#logrecord-attributes"""
|
20
|
+
|
21
|
+
# Name of the logger used to log the call.
|
19
22
|
name: str
|
23
|
+
|
24
|
+
# Human-readable time when the LogRecord was created. By default this is of the form '2003-07-08 16:49:45,896' (the
|
25
|
+
# numbers after the comma are millisecond portion of the time).
|
26
|
+
asctime: str
|
27
|
+
|
28
|
+
# The logged message, computed as msg % args. This is set when Formatter.format() is invoked.
|
29
|
+
message: str
|
30
|
+
|
31
|
+
# The format string passed in the original logging call. Merged with args to produce message, or an arbitrary object
|
32
|
+
# (see Using arbitrary objects as messages).
|
20
33
|
msg: str
|
34
|
+
|
35
|
+
# The tuple of arguments merged into msg to produce message, or a dict whose values are used for the merge (when
|
36
|
+
# there is only one argument, and it is a dictionary).
|
21
37
|
args: tuple
|
38
|
+
|
39
|
+
# Text logging level for the message ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL').
|
22
40
|
levelname: str
|
41
|
+
|
42
|
+
# # Numeric logging level for the message (DEBUG, INFO, WARNING, ERROR, CRITICAL).
|
23
43
|
levelno: Level
|
44
|
+
|
45
|
+
# Full pathname of the source file where the logging call was issued (if available).
|
24
46
|
pathname: str
|
47
|
+
|
48
|
+
# Filename portion of pathname.
|
25
49
|
filename: str
|
50
|
+
|
51
|
+
# Module (name portion of filename).
|
26
52
|
module: str
|
53
|
+
|
54
|
+
# Exception tuple (à la sys.exc_info) or, if no exception has occurred, None.
|
27
55
|
exc_info: ExceptionInfo | None
|
56
|
+
|
28
57
|
exc_text: str | None
|
58
|
+
|
59
|
+
# Stack frame information (where available) from the bottom of the stack in the current thread, up to and including
|
60
|
+
# the stack frame of the logging call which resulted in the creation of this record.
|
29
61
|
stack_info: str | None
|
62
|
+
|
63
|
+
# Source line number where the logging call was issued (if available).
|
30
64
|
lineno: int
|
65
|
+
|
66
|
+
# Name of function containing the logging call.
|
31
67
|
funcName: str
|
68
|
+
|
69
|
+
# Time when the LogRecord was created (as returned by time.time_ns() / 1e9).
|
32
70
|
created: float
|
71
|
+
|
72
|
+
# Millisecond portion of the time when the LogRecord was created.
|
33
73
|
msecs: float
|
74
|
+
|
75
|
+
# Time in milliseconds when the LogRecord was created, relative to the time the logging module was loaded.
|
34
76
|
relativeCreated: float
|
77
|
+
|
78
|
+
# Thread ID (if available).
|
35
79
|
thread: int
|
80
|
+
|
81
|
+
# Thread name (if available).
|
36
82
|
threadName: str
|
83
|
+
|
84
|
+
# Process name (if available).
|
37
85
|
processName: str
|
86
|
+
|
87
|
+
# Process ID (if available).
|
38
88
|
process: int
|
39
89
|
|
90
|
+
# asyncio.Task name (if available).
|
91
|
+
taskName: str
|
92
|
+
|
40
93
|
|
41
94
|
##
|
42
95
|
|
omlish/logs/handlers.py
CHANGED
omlish/specs/jmespath/ast.py
CHANGED
@@ -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
|
-
|
19
|
-
|
28
|
+
@property
|
29
|
+
def children(self) -> ta.Sequence[Node]:
|
30
|
+
return [self.expression]
|
20
31
|
|
21
32
|
|
22
|
-
|
23
|
-
|
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
|
-
|
31
|
-
|
49
|
+
@property
|
50
|
+
def children(self) -> ta.Sequence[Node]:
|
51
|
+
return [self.expr]
|
32
52
|
|
33
53
|
|
34
|
-
|
35
|
-
|
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
|
-
|
51
|
-
|
79
|
+
@property
|
80
|
+
def children(self) -> ta.Sequence[Node]:
|
81
|
+
return [self.expression]
|
52
82
|
|
53
83
|
|
54
|
-
|
55
|
-
|
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
|
-
|
67
|
-
|
105
|
+
@property
|
106
|
+
def children(self) -> ta.Sequence[Node]:
|
107
|
+
return [self.left, self.right, self.comparator]
|
68
108
|
|
69
109
|
|
70
|
-
|
71
|
-
|
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
|
-
|
87
|
-
|
133
|
+
@property
|
134
|
+
def children(self) -> ta.Sequence[Node]:
|
135
|
+
return tuple(self.nodes)
|
88
136
|
|
89
137
|
|
90
|
-
|
91
|
-
|
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
|
-
|
99
|
-
|
153
|
+
@property
|
154
|
+
def children(self) -> ta.Sequence[Node]:
|
155
|
+
return [*self.bindings, self.expr]
|
100
156
|
|
101
157
|
|
102
|
-
|
103
|
-
|
158
|
+
@dc.dataclass(frozen=True)
|
159
|
+
class Literal(LeafNode, lang.Final):
|
160
|
+
literal_value: ta.Any
|
104
161
|
|
105
162
|
|
106
|
-
|
107
|
-
|
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
|
-
|
115
|
-
|
176
|
+
@property
|
177
|
+
def children(self) -> ta.Sequence[Node]:
|
178
|
+
return tuple(self.nodes)
|
116
179
|
|
117
180
|
|
118
|
-
|
119
|
-
|
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
|
omlish/specs/jmespath/cli.py
CHANGED
@@ -1,35 +1,49 @@
|
|
1
1
|
#!/usr/bin/env python3
|
2
2
|
import argparse
|
3
|
-
import
|
4
|
-
import pprint
|
3
|
+
import dataclasses as dc
|
5
4
|
import sys
|
5
|
+
import typing as ta
|
6
6
|
|
7
|
-
from
|
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
|
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
|
-
|
17
|
-
|
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
|
-
|
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
|
-
|
44
|
-
|
57
|
+
print(json_dumps(search(expression, data), ensure_ascii=False))
|
58
|
+
return 0
|
45
59
|
|
46
|
-
except
|
47
|
-
|
60
|
+
except ArityError as e:
|
61
|
+
print(f'invalid-arity: {e}', file=sys.stderr)
|
48
62
|
return 1
|
49
63
|
|
50
|
-
except
|
51
|
-
|
64
|
+
except JmespathTypeError as e:
|
65
|
+
print(f'invalid-type: {e}', file=sys.stderr)
|
52
66
|
return 1
|
53
67
|
|
54
|
-
except
|
55
|
-
|
68
|
+
except JmespathValueError as e:
|
69
|
+
print(f'invalid-value: {e}', file=sys.stderr)
|
56
70
|
return 1
|
57
71
|
|
58
|
-
except
|
59
|
-
|
72
|
+
except UnknownFunctionError as e:
|
73
|
+
print(f'unknown-function: {e}', file=sys.stderr)
|
60
74
|
return 1
|
61
75
|
|
62
|
-
except
|
63
|
-
|
76
|
+
except ParseError as e:
|
77
|
+
print(f'syntax-error: {e}', file=sys.stderr)
|
64
78
|
return 1
|
65
79
|
|
66
80
|
|