omlish 0.0.0.dev306__py3-none-any.whl → 0.0.0.dev307__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/formats/edn/__init__.py +2 -1
- omlish/formats/edn/lexing.py +325 -0
- omlish/formats/edn/parsing.py +292 -251
- omlish/formats/edn/values.py +10 -10
- omlish/formats/json/__init__.py +2 -2
- omlish/formats/json/stream/{build.py → building.py} +8 -8
- omlish/formats/json/stream/{parse.py → parsing.py} +5 -5
- omlish/formats/json/stream/{render.py → rendering.py} +7 -7
- omlish/formats/json/stream/utils.py +3 -3
- omlish/funcs/genmachine.py +22 -18
- {omlish-0.0.0.dev306.dist-info → omlish-0.0.0.dev307.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev306.dist-info → omlish-0.0.0.dev307.dist-info}/RECORD +19 -19
- {omlish-0.0.0.dev306.dist-info → omlish-0.0.0.dev307.dist-info}/WHEEL +1 -1
- omlish/formats/edn/LICENSE +0 -16
- /omlish/formats/json/{render.py → rendering.py} +0 -0
- /omlish/formats/json/stream/{lex.py → lexing.py} +0 -0
- {omlish-0.0.0.dev306.dist-info → omlish-0.0.0.dev307.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev306.dist-info → omlish-0.0.0.dev307.dist-info}/licenses/LICENSE +0 -0
- {omlish-0.0.0.dev306.dist-info → omlish-0.0.0.dev307.dist-info}/top_level.txt +0 -0
omlish/__about__.py
CHANGED
omlish/formats/edn/__init__.py
CHANGED
@@ -0,0 +1,325 @@
|
|
1
|
+
r"""
|
2
|
+
https://github.com/edn-format/edn
|
3
|
+
https://github.com/antlr/grammars-v4/blob/master/edn/edn.g4
|
4
|
+
https://github.com/jorinvo/edn-data/blob/1e5824f63803eb58f35e98839352000053d47115/src/parse.ts
|
5
|
+
https://clojure.org/reference/reader#_extensible_data_notation_edn
|
6
|
+
"""
|
7
|
+
import dataclasses as dc
|
8
|
+
import io
|
9
|
+
import typing as ta
|
10
|
+
|
11
|
+
from ... import check
|
12
|
+
from ...funcs.genmachine import GenMachine
|
13
|
+
|
14
|
+
|
15
|
+
##
|
16
|
+
|
17
|
+
|
18
|
+
TokenKind: ta.TypeAlias = ta.Literal[
|
19
|
+
'STRING',
|
20
|
+
'CHAR',
|
21
|
+
'WORD',
|
22
|
+
'COMMENT',
|
23
|
+
|
24
|
+
'LPAREN',
|
25
|
+
'RPAREN',
|
26
|
+
'LBRACKET',
|
27
|
+
'RBRACKET',
|
28
|
+
'HASH_LBRACE',
|
29
|
+
'LBRACE',
|
30
|
+
'RBRACE',
|
31
|
+
|
32
|
+
'HASH_UNDERSCORE',
|
33
|
+
'META',
|
34
|
+
'QUOTE',
|
35
|
+
]
|
36
|
+
|
37
|
+
|
38
|
+
class Position(ta.NamedTuple):
|
39
|
+
ofs: int
|
40
|
+
line: int
|
41
|
+
col: int
|
42
|
+
|
43
|
+
|
44
|
+
class Token(ta.NamedTuple):
|
45
|
+
kind: TokenKind
|
46
|
+
src: str
|
47
|
+
|
48
|
+
pos: Position
|
49
|
+
|
50
|
+
def __iter__(self):
|
51
|
+
raise TypeError
|
52
|
+
|
53
|
+
|
54
|
+
##
|
55
|
+
|
56
|
+
|
57
|
+
SINGLE_TOKENS: ta.Mapping[str, TokenKind] = {
|
58
|
+
'(': 'LPAREN',
|
59
|
+
')': 'RPAREN',
|
60
|
+
'[': 'LBRACKET',
|
61
|
+
']': 'RBRACKET',
|
62
|
+
'{': 'LBRACE',
|
63
|
+
'}': 'RBRACE',
|
64
|
+
|
65
|
+
'^': 'META',
|
66
|
+
"'": 'QUOTE',
|
67
|
+
}
|
68
|
+
|
69
|
+
|
70
|
+
HASH_TOKENS: ta.Mapping[str, TokenKind] = {
|
71
|
+
'{': 'HASH_LBRACE',
|
72
|
+
'_': 'HASH_UNDERSCORE',
|
73
|
+
}
|
74
|
+
|
75
|
+
|
76
|
+
WORD_FIRST_SPECIAL_CHARS = ':.*+!-_?$%&=<>.'
|
77
|
+
WORD_BODY_SPECIAL_CHARS = '/'
|
78
|
+
|
79
|
+
|
80
|
+
##
|
81
|
+
|
82
|
+
|
83
|
+
@dc.dataclass()
|
84
|
+
class StreamLexError(Exception):
|
85
|
+
message: str
|
86
|
+
|
87
|
+
pos: Position
|
88
|
+
|
89
|
+
|
90
|
+
class StreamLexer(GenMachine[str, Token]):
|
91
|
+
def __init__(self) -> None:
|
92
|
+
self._ofs = 0
|
93
|
+
self._line = 1
|
94
|
+
self._col = 0
|
95
|
+
|
96
|
+
self._buf = io.StringIO()
|
97
|
+
|
98
|
+
super().__init__(self._do_main())
|
99
|
+
|
100
|
+
@property
|
101
|
+
def pos(self) -> Position:
|
102
|
+
return Position(
|
103
|
+
self._ofs,
|
104
|
+
self._line,
|
105
|
+
self._col,
|
106
|
+
)
|
107
|
+
|
108
|
+
def _char_in(self, c: str) -> str:
|
109
|
+
if not isinstance(c, str):
|
110
|
+
raise TypeError(c)
|
111
|
+
if c and len(c) != 1:
|
112
|
+
raise ValueError(c)
|
113
|
+
|
114
|
+
self._ofs += 1
|
115
|
+
|
116
|
+
if c == '\n':
|
117
|
+
self._line += 1
|
118
|
+
self._col = 0
|
119
|
+
else:
|
120
|
+
self._col += 1
|
121
|
+
|
122
|
+
return c
|
123
|
+
|
124
|
+
def _make_tok(
|
125
|
+
self,
|
126
|
+
kind: TokenKind,
|
127
|
+
src: str,
|
128
|
+
pos: Position,
|
129
|
+
) -> ta.Sequence[Token]:
|
130
|
+
tok = Token(
|
131
|
+
kind,
|
132
|
+
src,
|
133
|
+
pos,
|
134
|
+
)
|
135
|
+
return (tok,)
|
136
|
+
|
137
|
+
def _flip_buf(self) -> str:
|
138
|
+
src = self._buf.getvalue()
|
139
|
+
self._buf.seek(0)
|
140
|
+
self._buf.truncate()
|
141
|
+
return src
|
142
|
+
|
143
|
+
def _raise(self, msg: str, src: Exception | None = None) -> ta.NoReturn:
|
144
|
+
raise StreamLexError(msg, self.pos) from src
|
145
|
+
|
146
|
+
def _do_main(self, p: str | None = None):
|
147
|
+
while True:
|
148
|
+
if p is not None:
|
149
|
+
c = p
|
150
|
+
p = None
|
151
|
+
else:
|
152
|
+
c = self._char_in((yield None)) # noqa
|
153
|
+
|
154
|
+
if not c:
|
155
|
+
return None
|
156
|
+
|
157
|
+
if c.isspace() or c == ',':
|
158
|
+
continue
|
159
|
+
|
160
|
+
if c in SINGLE_TOKENS:
|
161
|
+
yield self._make_tok(SINGLE_TOKENS[c], c, self.pos)
|
162
|
+
continue
|
163
|
+
|
164
|
+
if c == ';':
|
165
|
+
return self._do_comment()
|
166
|
+
|
167
|
+
if c == '"':
|
168
|
+
return self._do_string()
|
169
|
+
|
170
|
+
if c == '\\':
|
171
|
+
return self._do_char()
|
172
|
+
|
173
|
+
if c == '#':
|
174
|
+
return self._do_hash()
|
175
|
+
|
176
|
+
if (
|
177
|
+
c.isalnum() or
|
178
|
+
c in WORD_FIRST_SPECIAL_CHARS
|
179
|
+
):
|
180
|
+
return self._do_word(c)
|
181
|
+
|
182
|
+
self._raise(f'Unexpected input: {c}')
|
183
|
+
|
184
|
+
def _do_comment(self):
|
185
|
+
check.state(self._buf.tell() == 0)
|
186
|
+
self._buf.write(';')
|
187
|
+
|
188
|
+
pos = self.pos
|
189
|
+
|
190
|
+
while True:
|
191
|
+
try:
|
192
|
+
c = self._char_in((yield None)) # noqa
|
193
|
+
except GeneratorExit:
|
194
|
+
self._raise('Unexpected end of input')
|
195
|
+
|
196
|
+
if not c or c == '\n':
|
197
|
+
break
|
198
|
+
|
199
|
+
self._buf.write(c)
|
200
|
+
|
201
|
+
src = self._flip_buf()
|
202
|
+
yield self._make_tok('COMMENT', src, pos)
|
203
|
+
return self._do_main()
|
204
|
+
|
205
|
+
def _do_string(self):
|
206
|
+
check.state(self._buf.tell() == 0)
|
207
|
+
self._buf.write('"')
|
208
|
+
|
209
|
+
pos = self.pos
|
210
|
+
|
211
|
+
esc = False
|
212
|
+
while True:
|
213
|
+
try:
|
214
|
+
c = self._char_in((yield None)) # noqa
|
215
|
+
except GeneratorExit:
|
216
|
+
self._raise('Unexpected end of input')
|
217
|
+
|
218
|
+
if not c:
|
219
|
+
self._raise(f'Unterminated string literal: {self._buf.getvalue()}')
|
220
|
+
|
221
|
+
self._buf.write(c)
|
222
|
+
if esc:
|
223
|
+
esc = False
|
224
|
+
elif c == '\\':
|
225
|
+
esc = True
|
226
|
+
elif c == '"':
|
227
|
+
break
|
228
|
+
|
229
|
+
src = self._flip_buf()
|
230
|
+
yield self._make_tok('STRING', src, pos)
|
231
|
+
return self._do_main()
|
232
|
+
|
233
|
+
def _do_char(self):
|
234
|
+
check.state(self._buf.tell() == 0)
|
235
|
+
self._buf.write('\\')
|
236
|
+
|
237
|
+
pos = self.pos
|
238
|
+
|
239
|
+
while True:
|
240
|
+
try:
|
241
|
+
c = self._char_in((yield None)) # noqa
|
242
|
+
except GeneratorExit:
|
243
|
+
self._raise('Unexpected end of input')
|
244
|
+
|
245
|
+
if not c or not (
|
246
|
+
c.isalnum() or
|
247
|
+
c == '\\'
|
248
|
+
):
|
249
|
+
break
|
250
|
+
|
251
|
+
self._buf.write(c)
|
252
|
+
|
253
|
+
src = self._flip_buf()
|
254
|
+
yield self._make_tok('CHAR', src, pos)
|
255
|
+
return self._do_main(c)
|
256
|
+
|
257
|
+
def _do_hash(self):
|
258
|
+
check.state(self._buf.tell() == 0)
|
259
|
+
|
260
|
+
pos = self.pos
|
261
|
+
|
262
|
+
try:
|
263
|
+
c = self._char_in((yield None)) # noqa
|
264
|
+
except GeneratorExit:
|
265
|
+
self._raise('Unexpected end of input')
|
266
|
+
|
267
|
+
if (ht := HASH_TOKENS.get(c)) is not None:
|
268
|
+
yield self._make_tok(ht, '#' + c, pos)
|
269
|
+
return self._do_main()
|
270
|
+
|
271
|
+
elif (
|
272
|
+
c.isalnum() or
|
273
|
+
c == '#' or
|
274
|
+
c in WORD_FIRST_SPECIAL_CHARS
|
275
|
+
):
|
276
|
+
return self._do_word('#' + c, pos=pos)
|
277
|
+
|
278
|
+
else:
|
279
|
+
self._raise(f'Unexpected input: {c}')
|
280
|
+
|
281
|
+
def _do_word(self, pfx: str, *, pos: Position | None = None):
|
282
|
+
check.state(self._buf.tell() == 0)
|
283
|
+
self._buf.write(pfx)
|
284
|
+
|
285
|
+
if pos is None:
|
286
|
+
pos = self.pos
|
287
|
+
|
288
|
+
while True:
|
289
|
+
try:
|
290
|
+
c = self._char_in((yield None)) # noqa
|
291
|
+
except GeneratorExit:
|
292
|
+
self._raise('Unexpected end of input')
|
293
|
+
|
294
|
+
if not c or not (
|
295
|
+
c.isalnum() or
|
296
|
+
c in WORD_FIRST_SPECIAL_CHARS or
|
297
|
+
c in WORD_BODY_SPECIAL_CHARS
|
298
|
+
):
|
299
|
+
break
|
300
|
+
|
301
|
+
self._buf.write(c)
|
302
|
+
|
303
|
+
src = self._flip_buf()
|
304
|
+
yield self._make_tok('WORD', src, pos)
|
305
|
+
return self._do_main(c)
|
306
|
+
|
307
|
+
|
308
|
+
##
|
309
|
+
|
310
|
+
|
311
|
+
def test_lex():
|
312
|
+
for s in [
|
313
|
+
'"abc"',
|
314
|
+
'{"a" "b"}',
|
315
|
+
'1',
|
316
|
+
'-1',
|
317
|
+
'{a :b c 420}',
|
318
|
+
'#{a}',
|
319
|
+
]:
|
320
|
+
print(s)
|
321
|
+
with StreamLexer() as lex:
|
322
|
+
for c in [*s, '']:
|
323
|
+
for t in lex(c):
|
324
|
+
print(t)
|
325
|
+
print()
|
omlish/formats/edn/parsing.py
CHANGED
@@ -1,28 +1,88 @@
|
|
1
|
+
# ruff: noqa: PYI055 UP007
|
1
2
|
"""
|
2
3
|
TODO:
|
4
|
+
- \u0123 in strings
|
5
|
+
- https://clojure.org/reference/reader
|
3
6
|
- reader meta - ^:foo
|
7
|
+
- read table
|
4
8
|
"""
|
5
|
-
|
9
|
+
import dataclasses as dc
|
6
10
|
import datetime
|
7
11
|
import enum
|
12
|
+
import io
|
8
13
|
import re
|
9
14
|
import typing as ta
|
10
15
|
|
11
16
|
from ... import check
|
17
|
+
from ...funcs.genmachine import GenMachine
|
18
|
+
from .lexing import Position
|
19
|
+
from .lexing import StreamLexer
|
20
|
+
from .lexing import Token
|
12
21
|
from .values import Char
|
22
|
+
from .values import Collection
|
13
23
|
from .values import Keyword
|
14
24
|
from .values import List
|
15
25
|
from .values import Map
|
16
26
|
from .values import Set
|
17
27
|
from .values import Symbol
|
18
|
-
from .values import
|
28
|
+
from .values import Tagged
|
19
29
|
from .values import Vector
|
20
30
|
|
21
31
|
|
22
32
|
##
|
23
33
|
|
24
34
|
|
25
|
-
|
35
|
+
WORD_CONST_VALUES: ta.Mapping[str, ta.Any] = {
|
36
|
+
'true': True,
|
37
|
+
'false': False,
|
38
|
+
'nil': None,
|
39
|
+
|
40
|
+
'##Inf': float('inf'),
|
41
|
+
'##-Inf': float('-inf'),
|
42
|
+
'##NaN': float('nan'),
|
43
|
+
}
|
44
|
+
|
45
|
+
|
46
|
+
STRING_ESCAPE_MAP: ta.Mapping[str, str] = {
|
47
|
+
'"': '"',
|
48
|
+
'\\': '\\',
|
49
|
+
'b': '\b',
|
50
|
+
'f': '\f',
|
51
|
+
'n': '\n',
|
52
|
+
'r': '\r',
|
53
|
+
't': '\t',
|
54
|
+
}
|
55
|
+
|
56
|
+
|
57
|
+
CHAR_ESCAPE_MAP: ta.Mapping[str, str] = {
|
58
|
+
'backspace': '\b',
|
59
|
+
'formfeed': '\f',
|
60
|
+
'newline': '\n',
|
61
|
+
'return': '\r',
|
62
|
+
'space': ' ',
|
63
|
+
'tab': '\t',
|
64
|
+
}
|
65
|
+
|
66
|
+
|
67
|
+
##
|
68
|
+
|
69
|
+
|
70
|
+
@dc.dataclass()
|
71
|
+
class StreamParseError(Exception):
|
72
|
+
message: str
|
73
|
+
|
74
|
+
pos: Position | None = None
|
75
|
+
|
76
|
+
|
77
|
+
@dc.dataclass(frozen=True)
|
78
|
+
class MetaMaker:
|
79
|
+
fn: ta.Callable[..., ta.Any]
|
80
|
+
|
81
|
+
def __call__(self, *args: ta.Any, meta: ta.Any | None = None) -> ta.Any:
|
82
|
+
return self.fn(*args, meta=meta)
|
83
|
+
|
84
|
+
|
85
|
+
class StreamParser(GenMachine[Token, ta.Any]):
|
26
86
|
DEFAULT_TAG_HANDLERS: ta.ClassVar[ta.Mapping[str, ta.Callable[..., ta.Any]]] = {
|
27
87
|
'inst': lambda val: datetime.datetime.fromisoformat(val) if isinstance(val, str) else None,
|
28
88
|
}
|
@@ -30,19 +90,17 @@ class ListParser:
|
|
30
90
|
def __init__(
|
31
91
|
self,
|
32
92
|
*,
|
33
|
-
keyword_maker: ta.Callable[..., ta.Any] = Keyword,
|
34
|
-
char_maker: ta.Callable[..., ta.Any] = Char,
|
35
|
-
symbol_maker: ta.Callable[..., ta.Any] = Symbol,
|
93
|
+
keyword_maker: ta.Callable[..., ta.Any] = MetaMaker(Keyword),
|
94
|
+
char_maker: ta.Callable[..., ta.Any] = MetaMaker(Char),
|
95
|
+
symbol_maker: ta.Callable[..., ta.Any] = MetaMaker(Symbol),
|
36
96
|
|
37
|
-
list_maker: ta.Callable[..., ta.Any] = List.new,
|
38
|
-
vector_maker: ta.Callable[..., ta.Any] = Vector.new,
|
39
|
-
set_maker: ta.Callable[..., ta.Any] = Set.new,
|
40
|
-
map_maker: ta.Callable[..., ta.Any] = Map.new,
|
97
|
+
list_maker: ta.Callable[..., ta.Any] = MetaMaker(List.new),
|
98
|
+
vector_maker: ta.Callable[..., ta.Any] = MetaMaker(Vector.new),
|
99
|
+
set_maker: ta.Callable[..., ta.Any] = MetaMaker(Set.new),
|
100
|
+
map_maker: ta.Callable[..., ta.Any] = MetaMaker(Map.new),
|
41
101
|
|
42
102
|
tag_handlers: ta.Mapping[str, ta.Callable[..., ta.Any]] | None = None,
|
43
103
|
) -> None:
|
44
|
-
super().__init__()
|
45
|
-
|
46
104
|
self._keyword_maker = keyword_maker
|
47
105
|
self._char_maker = char_maker
|
48
106
|
self._symbol_maker = symbol_maker
|
@@ -57,299 +115,260 @@ class ListParser:
|
|
57
115
|
**(tag_handlers or {}),
|
58
116
|
}
|
59
117
|
|
60
|
-
self._stack: list[
|
61
|
-
|
62
|
-
|
63
|
-
|
118
|
+
self._stack: list[
|
119
|
+
tuple[
|
120
|
+
ta.Union[
|
121
|
+
type[Collection],
|
122
|
+
StreamParser._StackSpecial,
|
123
|
+
],
|
124
|
+
list[ta.Any],
|
125
|
+
],
|
126
|
+
] = []
|
64
127
|
|
65
|
-
|
128
|
+
super().__init__(self._do_main())
|
66
129
|
|
67
|
-
class
|
68
|
-
|
69
|
-
|
130
|
+
class _StackSpecial(enum.Enum): # noqa
|
131
|
+
DISCARD = enum.auto()
|
132
|
+
TAG = enum.auto()
|
70
133
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
134
|
+
def _emit_value(self, value: ta.Any) -> tuple[ta.Any, ...]:
|
135
|
+
while self._stack and self._stack[-1][0] is StreamParser._StackSpecial.TAG:
|
136
|
+
cc, cl = self._stack.pop()
|
137
|
+
ts = check.non_empty_str(check.single(cl))
|
138
|
+
value = Tagged(ts, value)
|
76
139
|
|
77
|
-
|
78
|
-
|
79
|
-
LIST = 1
|
80
|
-
MAP = 2
|
81
|
-
SET = 3
|
82
|
-
TAG = 4
|
140
|
+
if not self._stack:
|
141
|
+
return (value,)
|
83
142
|
|
84
|
-
|
143
|
+
cc, cl = self._stack[-1]
|
85
144
|
|
86
|
-
|
87
|
-
|
88
|
-
|
145
|
+
if cc is StreamParser._StackSpecial.DISCARD:
|
146
|
+
check.empty(cl)
|
147
|
+
self._stack.pop()
|
148
|
+
return ()
|
89
149
|
|
90
|
-
|
150
|
+
elif cc is StreamParser._StackSpecial.TAG:
|
151
|
+
ts = check.non_empty_str(check.single(cl))
|
152
|
+
self._stack.pop()
|
153
|
+
tv = Tagged(ts, value)
|
154
|
+
return (tv,)
|
91
155
|
|
92
|
-
|
93
|
-
|
156
|
+
elif cc is Map:
|
157
|
+
if cl and len(cl[-1]) < 2:
|
158
|
+
cl[-1] = (*cl[-1], value)
|
159
|
+
else:
|
160
|
+
cl.append((value,))
|
161
|
+
return ()
|
162
|
+
|
163
|
+
elif isinstance(cc, type) and issubclass(cc, Collection):
|
164
|
+
cl.append(value)
|
165
|
+
return ()
|
166
|
+
|
167
|
+
else:
|
168
|
+
raise RuntimeError(cc)
|
169
|
+
|
170
|
+
def _do_main(self):
|
171
|
+
while True:
|
172
|
+
tok: Token
|
173
|
+
try:
|
174
|
+
tok = yield None # noqa
|
175
|
+
except GeneratorExit:
|
176
|
+
if self._stack:
|
177
|
+
raise StreamParseError('Expected value') from None
|
178
|
+
else:
|
179
|
+
raise
|
94
180
|
|
95
|
-
|
96
|
-
prev_state.append(self._result)
|
181
|
+
value: ta.Any
|
97
182
|
|
98
|
-
|
99
|
-
prev_state.append(self._result)
|
183
|
+
# scalars
|
100
184
|
|
101
|
-
|
102
|
-
|
103
|
-
prev_state[0].append([prev_state[1].pop(), self._result])
|
104
|
-
else:
|
105
|
-
prev_state[1].append(self._result)
|
185
|
+
if tok.kind == 'STRING':
|
186
|
+
value = self._parse_string(tok)
|
106
187
|
|
107
|
-
|
108
|
-
|
188
|
+
elif tok.kind == 'CHAR':
|
189
|
+
value = self._parse_char(tok)
|
109
190
|
|
110
|
-
|
111
|
-
|
191
|
+
elif tok.kind == 'WORD':
|
192
|
+
if tok.src.startswith('#'):
|
193
|
+
# FIXME: more dispatching
|
194
|
+
self._stack.append((StreamParser._StackSpecial.TAG, [tok.src[1:]]))
|
195
|
+
continue
|
112
196
|
|
113
|
-
else:
|
114
|
-
tag_handler = self._tag_handlers.get(prev_state)
|
115
|
-
if tag_handler:
|
116
|
-
self._result = tag_handler(self._result)
|
117
197
|
else:
|
118
|
-
|
119
|
-
|
120
|
-
self._update_stack()
|
121
|
-
return
|
122
|
-
|
123
|
-
# TODO: else error
|
124
|
-
# Reset result after updating stack
|
125
|
-
self._result = self._UNDEFINED
|
126
|
-
|
127
|
-
#
|
128
|
-
|
129
|
-
_INT_PAT = re.compile(r'^[-+]?(0|[1-9][0-9]*)$')
|
130
|
-
_BIGINT_PAT = re.compile(r'^[-+]?(0|[1-9][0-9]*)N$')
|
131
|
-
_FLOAT_PAT = re.compile(r'^[-+]?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?(0|[1-9][0-9]*))?M?$')
|
132
|
-
|
133
|
-
def _match(self) -> None:
|
134
|
-
if self._state == 'nil':
|
135
|
-
self._result = None
|
136
|
-
|
137
|
-
elif self._state == 'true':
|
138
|
-
self._result = True
|
139
|
-
|
140
|
-
elif self._state == 'false':
|
141
|
-
self._result = False
|
142
|
-
|
143
|
-
elif self._state.startswith(':'):
|
144
|
-
# Keyword
|
145
|
-
self._result = self._keyword_maker(self._state[1:])
|
146
|
-
|
147
|
-
elif self._state.startswith('#'):
|
148
|
-
# Tag
|
149
|
-
self._stack.append((ListParser._StackItem.TAG, self._state[1:]))
|
150
|
-
self._result = self._UNDEFINED
|
151
|
-
|
152
|
-
elif self._INT_PAT.match(self._state):
|
153
|
-
# Int
|
154
|
-
self._result = int(self._state)
|
155
|
-
|
156
|
-
elif self._FLOAT_PAT.match(self._state):
|
157
|
-
# Float
|
158
|
-
self._result = float(self._state)
|
159
|
-
|
160
|
-
elif self._BIGINT_PAT.match(self._state):
|
161
|
-
# BigInt
|
162
|
-
self._result = int(self._state[:-1]) # In Python we don't need special handling for bigint
|
163
|
-
|
164
|
-
elif self._state.startswith('\\'):
|
165
|
-
# Char
|
166
|
-
check.state(len(self._state) > 1)
|
167
|
-
if self._state == '\\space':
|
168
|
-
c = ' '
|
169
|
-
elif self._state == '\\newline':
|
170
|
-
c = '\n'
|
171
|
-
elif self._state == '\\return':
|
172
|
-
c = '\r'
|
173
|
-
elif self._state == '\\tab':
|
174
|
-
c = '\t'
|
175
|
-
elif self._state == '\\\\':
|
176
|
-
c = '\\'
|
177
|
-
elif self._state.startswith('\\u'):
|
178
|
-
check.state(len(self._state) == 6)
|
179
|
-
c = chr(int(self._state[2:], 16))
|
180
|
-
else:
|
181
|
-
check.state(len(self._state) == 2)
|
182
|
-
c = self._state[1:]
|
198
|
+
value = self._parse_word(tok)
|
183
199
|
|
184
|
-
|
200
|
+
elif tok.kind == 'COMMENT':
|
201
|
+
continue
|
202
|
+
|
203
|
+
# open
|
204
|
+
|
205
|
+
elif tok.kind == 'LPAREN':
|
206
|
+
self._stack.append((List, []))
|
207
|
+
continue
|
185
208
|
|
186
|
-
|
187
|
-
|
188
|
-
|
209
|
+
elif tok.kind == 'LBRACKET':
|
210
|
+
self._stack.append((Vector, []))
|
211
|
+
continue
|
189
212
|
|
190
|
-
|
213
|
+
elif tok.kind == 'HASH_LBRACE':
|
214
|
+
self._stack.append((Set, []))
|
215
|
+
continue
|
191
216
|
|
192
|
-
|
217
|
+
elif tok.kind == 'LBRACE':
|
218
|
+
self._stack.append((Map, []))
|
219
|
+
continue
|
193
220
|
|
194
|
-
|
221
|
+
elif tok.kind == 'HASH_UNDERSCORE':
|
222
|
+
self._stack.append((StreamParser._StackSpecial.DISCARD, []))
|
223
|
+
continue
|
195
224
|
|
196
|
-
|
197
|
-
't': '\t',
|
198
|
-
'r': '\r',
|
199
|
-
'n': '\n',
|
200
|
-
'\\': '\\',
|
201
|
-
'"': '"',
|
202
|
-
}
|
225
|
+
# close
|
203
226
|
|
204
|
-
|
205
|
-
|
227
|
+
elif tok.kind == 'RPAREN':
|
228
|
+
cc, cl = self._stack.pop()
|
229
|
+
check.state(cc is List)
|
230
|
+
value = self._list_maker(cl)
|
206
231
|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
self._result = self._UNDEFINED
|
232
|
+
elif tok.kind == 'RBRACKET':
|
233
|
+
cc, cl = self._stack.pop()
|
234
|
+
check.state(cc is Vector)
|
235
|
+
value = self._vector_maker(cl)
|
212
236
|
|
213
|
-
|
237
|
+
elif tok.kind == 'RBRACE':
|
238
|
+
cc, cl = self._stack.pop()
|
214
239
|
|
215
|
-
|
216
|
-
|
217
|
-
self._match()
|
218
|
-
self._update_stack()
|
219
|
-
self._mode = ListParser._ParseMode.STRING
|
220
|
-
self._state = ''
|
221
|
-
continue
|
240
|
+
if cc is Set:
|
241
|
+
value = self._set_maker(cl)
|
222
242
|
|
223
|
-
|
224
|
-
|
225
|
-
|
243
|
+
elif cc is Map:
|
244
|
+
if cl and len(cl[-1]) != 2:
|
245
|
+
raise RuntimeError('Mismatched map entries')
|
246
|
+
value = self._map_maker(cl)
|
226
247
|
|
227
|
-
|
228
|
-
|
229
|
-
self._update_stack()
|
230
|
-
continue
|
248
|
+
else:
|
249
|
+
raise RuntimeError(cc)
|
231
250
|
|
232
|
-
|
233
|
-
self._match()
|
234
|
-
self._update_stack()
|
251
|
+
# nyi
|
235
252
|
|
236
|
-
|
237
|
-
|
253
|
+
elif tok.kind == 'META':
|
254
|
+
raise NotImplementedError
|
238
255
|
|
239
|
-
|
240
|
-
|
241
|
-
self._result = self._map_maker(prev_state[0])
|
256
|
+
elif tok.kind == 'QUOTE':
|
257
|
+
raise NotImplementedError
|
242
258
|
|
243
|
-
|
244
|
-
# FIXME:
|
245
|
-
# check.state(stack_item == ListParser._StackItem.SET)
|
246
|
-
self._result = self._set_maker(prev_state)
|
259
|
+
# failure
|
247
260
|
|
248
|
-
|
249
|
-
|
261
|
+
else:
|
262
|
+
raise ValueError(tok.kind)
|
263
|
+
|
264
|
+
# emit
|
265
|
+
|
266
|
+
if (ev := self._emit_value(value)):
|
267
|
+
yield ev
|
268
|
+
|
269
|
+
def _parse_string(self, tok: Token) -> str:
|
270
|
+
check.state(tok.kind == 'STRING')
|
271
|
+
src = tok.src
|
272
|
+
check.state(src[0] == '"')
|
273
|
+
check.state(src[-1] == '"')
|
274
|
+
check.state(len(src) > 1)
|
275
|
+
|
276
|
+
p = 1
|
277
|
+
end = len(src) - 1
|
278
|
+
if src.find('\\', p, end) < 0:
|
279
|
+
return src[1:-1]
|
280
|
+
|
281
|
+
sb = io.StringIO()
|
282
|
+
while True:
|
283
|
+
if (n := src.find('\\', p, end)) < 0:
|
284
|
+
sb.write(src[p:end])
|
285
|
+
break
|
286
|
+
|
287
|
+
sb.write(src[p:n])
|
288
|
+
p = n + 1
|
289
|
+
check.state(p < end)
|
290
|
+
x = src[p]
|
291
|
+
p += 1
|
292
|
+
|
293
|
+
if x == 'u':
|
294
|
+
check.state(p < end - 4)
|
295
|
+
r = chr(int(src[p:p + 4], 16))
|
296
|
+
p += 4
|
250
297
|
|
251
|
-
|
252
|
-
|
253
|
-
self._update_stack()
|
254
|
-
stack_item, prev_state = self._stack.pop()
|
255
|
-
self._result = self._vector_maker(tuple(prev_state))
|
256
|
-
self._update_stack()
|
257
|
-
continue
|
298
|
+
else:
|
299
|
+
r = STRING_ESCAPE_MAP[x]
|
258
300
|
|
259
|
-
|
260
|
-
self._match()
|
261
|
-
self._update_stack()
|
262
|
-
stack_item, prev_state = self._stack.pop()
|
263
|
-
self._result = self._list_maker(prev_state)
|
264
|
-
self._update_stack()
|
265
|
-
continue
|
301
|
+
sb.write(r)
|
266
302
|
|
267
|
-
|
268
|
-
self._match()
|
269
|
-
self._update_stack()
|
270
|
-
self._stack.append((ListParser._StackItem.VECTOR, []))
|
271
|
-
continue
|
303
|
+
return sb.getvalue()
|
272
304
|
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
305
|
+
def _parse_char(self, tok: Token) -> ta.Any:
|
306
|
+
check.state(tok.kind == 'CHAR')
|
307
|
+
src = tok.src
|
308
|
+
check.state(len(src) > 1)
|
309
|
+
check.state(src.startswith('\\'))
|
278
310
|
|
279
|
-
|
280
|
-
|
281
|
-
self._stack.append((ListParser._StackItem.TAG, char))
|
282
|
-
self._result = self._UNDEFINED
|
283
|
-
self._state = ''
|
284
|
-
continue
|
311
|
+
if len(src) == 2:
|
312
|
+
c = src[1]
|
285
313
|
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
self._update_stack()
|
290
|
-
self._stack.append((ListParser._StackItem.SET, []))
|
291
|
-
self._state = ''
|
292
|
-
continue
|
314
|
+
elif src[1] == 'u':
|
315
|
+
check.state(len(src) == 6)
|
316
|
+
c = chr(int(src[2:], 16))
|
293
317
|
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
self._stack.append((ListParser._StackItem.MAP, [[], []]))
|
298
|
-
self._state = ''
|
299
|
-
continue
|
318
|
+
elif src[1] == 'o':
|
319
|
+
# \oXXX -> octal
|
320
|
+
raise NotImplementedError
|
300
321
|
|
301
|
-
|
302
|
-
|
322
|
+
else:
|
323
|
+
c = CHAR_ESCAPE_MAP[src[1:]]
|
303
324
|
|
304
|
-
|
305
|
-
if char == '\\':
|
306
|
-
self._stack.append((self._mode, self._state))
|
307
|
-
self._mode = ListParser._ParseMode.ESCAPE
|
308
|
-
self._state = ''
|
309
|
-
continue
|
325
|
+
return self._char_maker(c)
|
310
326
|
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
self._update_stack()
|
315
|
-
self._state = ''
|
316
|
-
continue
|
327
|
+
_INT_PAT = re.compile(r'[-+]?(0|[1-9][0-9]*)')
|
328
|
+
_BIGINT_PAT = re.compile(r'[-+]?(0|[1-9][0-9]*)N')
|
329
|
+
_FLOAT_PAT = re.compile(r'[-+]?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?(0|[1-9][0-9]*))?M?')
|
317
330
|
|
318
|
-
|
331
|
+
def _parse_word(self, tok: Token) -> ta.Any:
|
332
|
+
check.state(tok.kind == 'WORD')
|
333
|
+
src = tok.src
|
334
|
+
check.non_empty_str(src)
|
335
|
+
check.state(not src.startswith('#'))
|
319
336
|
|
320
|
-
|
321
|
-
|
322
|
-
escaped_char = self._STRING_ESCAPE_MAP.get(char, char)
|
323
|
-
stack_item, prev_state = self._stack.pop()
|
324
|
-
self._mode = check.isinstance(stack_item, ListParser._ParseMode)
|
325
|
-
self._state = prev_state + escaped_char
|
337
|
+
if src in WORD_CONST_VALUES:
|
338
|
+
return WORD_CONST_VALUES[src]
|
326
339
|
|
327
|
-
|
328
|
-
|
329
|
-
self._mode = ListParser._ParseMode.IDLE
|
340
|
+
elif src.startswith(':'):
|
341
|
+
return self._keyword_maker(src[1:])
|
330
342
|
|
331
|
-
|
332
|
-
|
343
|
+
elif self._INT_PAT.fullmatch(src):
|
344
|
+
# FIXME: numbers lol
|
345
|
+
# 2r101010, 052, 8r52, 0x2a, 36r16, and 42 are all the same Long.
|
346
|
+
# Floating point numbers are read as Doubles; with M suffix they are read as BigDecimals.
|
347
|
+
# Ratios are supported, e.g. 22/7.
|
348
|
+
return int(src)
|
333
349
|
|
334
|
-
|
335
|
-
|
336
|
-
self._update_stack()
|
350
|
+
elif self._BIGINT_PAT.fullmatch(src):
|
351
|
+
return int(src[:-1])
|
337
352
|
|
338
|
-
|
353
|
+
elif self._FLOAT_PAT.fullmatch(src):
|
354
|
+
return float(src)
|
339
355
|
|
340
|
-
|
341
|
-
|
342
|
-
return values
|
356
|
+
else:
|
357
|
+
return self._symbol_maker(src)
|
343
358
|
|
344
359
|
|
345
|
-
|
360
|
+
##
|
346
361
|
|
347
362
|
|
348
363
|
def parse_list(src: str, **kwargs: ta.Any) -> list[ta.Any]:
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
364
|
+
r: list[ta.Any] = []
|
365
|
+
with StreamLexer() as l:
|
366
|
+
with StreamParser(**kwargs) as p:
|
367
|
+
for c in [*src, '']:
|
368
|
+
for t in l(c):
|
369
|
+
for o in p(t):
|
370
|
+
r.append(o) # noqa
|
371
|
+
return r
|
353
372
|
|
354
373
|
|
355
374
|
def parse(src: str, **kwargs: ta.Any) -> ta.Any | None:
|
@@ -357,3 +376,25 @@ def parse(src: str, **kwargs: ta.Any) -> ta.Any | None:
|
|
357
376
|
if not values:
|
358
377
|
return None
|
359
378
|
return check.single(values)
|
379
|
+
|
380
|
+
|
381
|
+
##
|
382
|
+
|
383
|
+
|
384
|
+
def test_parse():
|
385
|
+
for s in [
|
386
|
+
'"abc"',
|
387
|
+
'"a\\bc"',
|
388
|
+
'{"a" "b"}',
|
389
|
+
'1',
|
390
|
+
'-1',
|
391
|
+
'{a :b c 420}',
|
392
|
+
'#{a}',
|
393
|
+
'(1 #_ 2 3)',
|
394
|
+
'"foo\u1234bar"',
|
395
|
+
'\\x',
|
396
|
+
'\\u1234',
|
397
|
+
]:
|
398
|
+
print(s)
|
399
|
+
print(parse(s))
|
400
|
+
print()
|
omlish/formats/edn/values.py
CHANGED
@@ -15,7 +15,7 @@ _DEBUG = __debug__
|
|
15
15
|
|
16
16
|
@dc.dataclass(frozen=True)
|
17
17
|
class Value(lang.Abstract, lang.Sealed):
|
18
|
-
|
18
|
+
meta: ta.Any | None = dc.field(default=None, kw_only=True)
|
19
19
|
|
20
20
|
|
21
21
|
#
|
@@ -87,8 +87,8 @@ class List(Collection, lang.Final):
|
|
87
87
|
check.isinstance(self.items, tuple)
|
88
88
|
|
89
89
|
@classmethod
|
90
|
-
def new(cls, items: ta.Iterable[ta.Any]) -> 'List':
|
91
|
-
return cls(tuple(items))
|
90
|
+
def new(cls, items: ta.Iterable[ta.Any], *, meta: ta.Any | None = None) -> 'List':
|
91
|
+
return cls(tuple(items), meta=meta)
|
92
92
|
|
93
93
|
|
94
94
|
@dataclass_cache_hash()
|
@@ -104,8 +104,8 @@ class Vector(Collection, lang.Final):
|
|
104
104
|
check.isinstance(self.items, tuple)
|
105
105
|
|
106
106
|
@classmethod
|
107
|
-
def new(cls, items: ta.Iterable[ta.Any]) -> 'Vector':
|
108
|
-
return cls(tuple(items))
|
107
|
+
def new(cls, items: ta.Iterable[ta.Any], *, meta: ta.Any | None = None) -> 'Vector':
|
108
|
+
return cls(tuple(items), meta=meta)
|
109
109
|
|
110
110
|
|
111
111
|
@dataclass_cache_hash()
|
@@ -121,8 +121,8 @@ class Set(Collection, lang.Final):
|
|
121
121
|
check.isinstance(self.items, tuple)
|
122
122
|
|
123
123
|
@classmethod
|
124
|
-
def new(cls, items: ta.Iterable[ta.Any]) -> 'Set':
|
125
|
-
return cls(tuple(items))
|
124
|
+
def new(cls, items: ta.Iterable[ta.Any], *, meta: ta.Any | None = None) -> 'Set':
|
125
|
+
return cls(tuple(items), meta=meta)
|
126
126
|
|
127
127
|
|
128
128
|
@dataclass_cache_hash()
|
@@ -141,8 +141,8 @@ class Map(Collection, lang.Final):
|
|
141
141
|
check.equal(len(t), 2)
|
142
142
|
|
143
143
|
@classmethod
|
144
|
-
def new(cls, items: ta.Iterable[ta.Iterable[ta.Any]]) -> 'Map':
|
145
|
-
return cls(tuple((k, v) for k, v in items))
|
144
|
+
def new(cls, items: ta.Iterable[ta.Iterable[ta.Any]], *, meta: ta.Any | None = None) -> 'Map':
|
145
|
+
return cls(tuple((k, v) for k, v in items), meta=meta)
|
146
146
|
|
147
147
|
|
148
148
|
#
|
@@ -150,7 +150,7 @@ class Map(Collection, lang.Final):
|
|
150
150
|
|
151
151
|
@dataclass_cache_hash()
|
152
152
|
@dc.dataclass(frozen=True)
|
153
|
-
class
|
153
|
+
class Tagged(Value, lang.Final):
|
154
154
|
t: str
|
155
155
|
v: ta.Any
|
156
156
|
|
omlish/formats/json/__init__.py
CHANGED
@@ -35,11 +35,11 @@ from .json import ( # noqa
|
|
35
35
|
)
|
36
36
|
|
37
37
|
if _ta.TYPE_CHECKING:
|
38
|
-
from .
|
38
|
+
from .rendering import ( # noqa
|
39
39
|
JsonRenderer,
|
40
40
|
)
|
41
41
|
else:
|
42
|
-
_lang.proxy_init(globals(), '.
|
42
|
+
_lang.proxy_init(globals(), '.rendering', [
|
43
43
|
'JsonRenderer',
|
44
44
|
])
|
45
45
|
|
@@ -1,13 +1,13 @@
|
|
1
1
|
import typing as ta
|
2
2
|
|
3
|
-
from .
|
4
|
-
from .
|
5
|
-
from .
|
6
|
-
from .
|
7
|
-
from .
|
8
|
-
from .
|
9
|
-
from .
|
10
|
-
from .
|
3
|
+
from .lexing import SCALAR_VALUE_TYPES
|
4
|
+
from .parsing import BeginArray
|
5
|
+
from .parsing import BeginObject
|
6
|
+
from .parsing import EndArray
|
7
|
+
from .parsing import EndObject
|
8
|
+
from .parsing import JsonStreamObject
|
9
|
+
from .parsing import JsonStreamParserEvent
|
10
|
+
from .parsing import Key
|
11
11
|
|
12
12
|
|
13
13
|
##
|
@@ -4,11 +4,11 @@ import typing as ta
|
|
4
4
|
from .... import lang
|
5
5
|
from ....funcs.genmachine import GenMachine
|
6
6
|
from .errors import JsonStreamError
|
7
|
-
from .
|
8
|
-
from .
|
9
|
-
from .
|
10
|
-
from .
|
11
|
-
from .
|
7
|
+
from .lexing import SCALAR_VALUE_TYPES
|
8
|
+
from .lexing import VALUE_TOKEN_KINDS
|
9
|
+
from .lexing import Position
|
10
|
+
from .lexing import ScalarValue
|
11
|
+
from .lexing import Token
|
12
12
|
|
13
13
|
|
14
14
|
##
|
@@ -1,14 +1,14 @@
|
|
1
1
|
import io
|
2
2
|
import typing as ta
|
3
3
|
|
4
|
-
from ..
|
4
|
+
from ..rendering import AbstractJsonRenderer
|
5
5
|
from ..types import SCALAR_TYPES
|
6
|
-
from .
|
7
|
-
from .
|
8
|
-
from .
|
9
|
-
from .
|
10
|
-
from .
|
11
|
-
from .
|
6
|
+
from .parsing import BeginArray
|
7
|
+
from .parsing import BeginObject
|
8
|
+
from .parsing import EndArray
|
9
|
+
from .parsing import EndObject
|
10
|
+
from .parsing import JsonStreamParserEvent
|
11
|
+
from .parsing import Key
|
12
12
|
|
13
13
|
|
14
14
|
##
|
@@ -2,9 +2,9 @@ import dataclasses as dc
|
|
2
2
|
import typing as ta
|
3
3
|
|
4
4
|
from .... import lang
|
5
|
-
from .
|
6
|
-
from .
|
7
|
-
from .
|
5
|
+
from .building import JsonObjectBuilder
|
6
|
+
from .lexing import JsonStreamLexer
|
7
|
+
from .parsing import JsonStreamParser
|
8
8
|
|
9
9
|
|
10
10
|
##
|
omlish/funcs/genmachine.py
CHANGED
@@ -34,7 +34,10 @@ class GenMachine(ta.Generic[I, O]):
|
|
34
34
|
if initial is None:
|
35
35
|
raise TypeError('No initial state')
|
36
36
|
|
37
|
-
self.
|
37
|
+
self._gen = initial
|
38
|
+
|
39
|
+
if (n := next(self._gen)) is not None: # noqa
|
40
|
+
raise GenMachine.NotStartedError
|
38
41
|
|
39
42
|
def _initial_state(self) -> MachineGen | None:
|
40
43
|
return None
|
@@ -74,33 +77,34 @@ class GenMachine(ta.Generic[I, O]):
|
|
74
77
|
class Error(Exception):
|
75
78
|
pass
|
76
79
|
|
77
|
-
class
|
80
|
+
class NotStartedError(Error):
|
78
81
|
pass
|
79
82
|
|
80
|
-
class
|
83
|
+
class ClosedError(Error):
|
81
84
|
pass
|
82
85
|
|
83
|
-
|
84
|
-
|
85
|
-
def _advance(self, gen: MachineGen) -> None:
|
86
|
-
self._gen = gen
|
86
|
+
class StateError(Error):
|
87
|
+
pass
|
87
88
|
|
88
|
-
|
89
|
-
raise GenMachine.ClosedError
|
89
|
+
#
|
90
90
|
|
91
91
|
def __call__(self, i: I) -> ta.Iterable[O]:
|
92
92
|
if self._gen is None:
|
93
93
|
raise GenMachine.ClosedError
|
94
94
|
|
95
95
|
gi: I | None = i
|
96
|
-
|
97
|
-
|
98
|
-
gi
|
99
|
-
|
96
|
+
while True:
|
97
|
+
try:
|
98
|
+
while (o := self._gen.send(gi)) is not None: # type: ignore[union-attr]
|
99
|
+
gi = None
|
100
|
+
yield from o
|
100
101
|
|
101
|
-
|
102
|
-
if s.value is None:
|
103
|
-
self._gen = None
|
104
|
-
return None
|
102
|
+
break
|
105
103
|
|
106
|
-
|
104
|
+
except StopIteration as s:
|
105
|
+
if (sv := s.value) is None:
|
106
|
+
self._gen = None
|
107
|
+
return None
|
108
|
+
|
109
|
+
self._gen = sv
|
110
|
+
gi = None
|
@@ -1,5 +1,5 @@
|
|
1
1
|
omlish/.manifests.json,sha256=orgsRvtpHu8tdhaCvlP9v3P495OJopYYiHKjK68WtWg,8587
|
2
|
-
omlish/__about__.py,sha256=
|
2
|
+
omlish/__about__.py,sha256=YdK-L7JBeMEmm3Dl7hWjoFj3BouojWQPvOl_zSLUgMA,3478
|
3
3
|
omlish/__init__.py,sha256=SsyiITTuK0v74XpKV8dqNaCmjOlan1JZKrHQv5rWKPA,253
|
4
4
|
omlish/c3.py,sha256=rer-TPOFDU6fYq_AWio_AmA-ckZ8JDY5shIzQ_yXfzA,8414
|
5
5
|
omlish/cached.py,sha256=MLap_p0rdGoDIMVhXVHm1tsbcWobJF0OanoodV03Ju8,542
|
@@ -319,21 +319,21 @@ omlish/formats/props.py,sha256=auCv-Jx79KGlWfyG1-Qo0ou-Ex0W_mF3r_lDFdsVkWI,18920
|
|
319
319
|
omlish/formats/repr.py,sha256=kYrNs4o-ji8nOdp6u_L3aMgBMWN1ZAZJSAWgQQfStSQ,414
|
320
320
|
omlish/formats/xml.py,sha256=VJfqHR60dhAtjeG8WXFMozFqesTBSGvv264d67eDFXc,3514
|
321
321
|
omlish/formats/yaml.py,sha256=jGPQlTE0vSV-p0O7TJRNlf6o1uq4gx8PrHZe1ApJ_o8,7386
|
322
|
-
omlish/formats/edn/
|
323
|
-
omlish/formats/edn/__init__.py,sha256=JXHN8RlPAl-l2OnOQOQgYO8-f2zrYy-bGS2uaHiD9x0,183
|
322
|
+
omlish/formats/edn/__init__.py,sha256=H3q5B-dibXvQV8pmuWizTo6Xk75M7M0M7VPCLt86rpo,195
|
324
323
|
omlish/formats/edn/codec.py,sha256=k6-Ra3P3Rlv6JA69-jPLI4nCe5XVes_QJbcsj5DYzMM,454
|
325
|
-
omlish/formats/edn/
|
326
|
-
omlish/formats/edn/
|
324
|
+
omlish/formats/edn/lexing.py,sha256=plwbFwHLOmrr5_QhmzvMTmTK55Ot0DxRgKY6ASSl_-Y,6966
|
325
|
+
omlish/formats/edn/parsing.py,sha256=rtoOnDo8TuTo_GAhrNoVHu7Ys7CboALdgOF2PevAJYk,10152
|
326
|
+
omlish/formats/edn/values.py,sha256=jf0g88KJIMALxcuH51SoaMWg1HqTUqc1ugldmyyXWoc,3707
|
327
327
|
omlish/formats/ini/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
328
328
|
omlish/formats/ini/codec.py,sha256=omuFg0kiDksv8rRlWd_v32ebzEcKlgmiPgGID3bRi2M,631
|
329
329
|
omlish/formats/ini/sections.py,sha256=7wYyZdVTQbMPFpjQEACKJfAEPzUBrogINsrvFgxJoZ0,1015
|
330
|
-
omlish/formats/json/__init__.py,sha256=
|
330
|
+
omlish/formats/json/__init__.py,sha256=HXFv4VDTBhx0k5U4JYWZqxziBwzJoPX51QK3xIboT8U,786
|
331
331
|
omlish/formats/json/codecs.py,sha256=E5KErfqsgGZq763ixXLT3qysbk5MIsypT92xG5aSaIs,796
|
332
332
|
omlish/formats/json/consts.py,sha256=A0cTAGGLyjo-gcYIQrL4JIaardI0yPMhQoNmh42BaRg,387
|
333
333
|
omlish/formats/json/encoding.py,sha256=O4iIWle7W_-RwpOvJNlqOfkbnDyiQHexV5Za4hlrFzw,497
|
334
334
|
omlish/formats/json/json.py,sha256=Mdqv2vdMi7gp96eV0BIYH5UdWpjWfsh-tSMZeywG-08,331
|
335
335
|
omlish/formats/json/literals.py,sha256=6ptwZyfTXodEtAjDnUhsx6XU3KRZWWYWKYtZ8T7rzsQ,5625
|
336
|
-
omlish/formats/json/
|
336
|
+
omlish/formats/json/rendering.py,sha256=r6J5YKSzcxPg_RiG5idGqJ-AIZozJQ_Awj6W_oSGRjk,4555
|
337
337
|
omlish/formats/json/types.py,sha256=ueO9-uOU2eVWowJf0LH1fHFLjZ6fTIZyq9qybcLQaiQ,147
|
338
338
|
omlish/formats/json/backends/__init__.py,sha256=gnaNDCxy_KmmPUPDnjxO5_WjuWxLGbI9FYWx8ZJuQUU,97
|
339
339
|
omlish/formats/json/backends/base.py,sha256=WqtyoM82pyM0NyqpPwndrebr1bUVU1QlpmVQNrcAO8c,1114
|
@@ -343,12 +343,12 @@ omlish/formats/json/backends/orjson.py,sha256=wR8pMGFtkhZGHcNVk7vNYUnv8lUapdK89p
|
|
343
343
|
omlish/formats/json/backends/std.py,sha256=PM00Kh9ZR2XzollHMEvdo35Eml1N-zFfRW-LOCV5ftM,3085
|
344
344
|
omlish/formats/json/backends/ujson.py,sha256=BNJCU4kluGHdqTUKLJEuHhE2m2TmqR7HEN289S0Eokg,2278
|
345
345
|
omlish/formats/json/stream/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
346
|
-
omlish/formats/json/stream/
|
346
|
+
omlish/formats/json/stream/building.py,sha256=SGbExmaerqOEiNSom2AERlpyXTj4dpM0QbMW-2WWM2o,2550
|
347
347
|
omlish/formats/json/stream/errors.py,sha256=c8M8UAYmIZ-vWZLeKD2jMj4EDCJbr9QR8Jq_DyHjujQ,43
|
348
|
-
omlish/formats/json/stream/
|
349
|
-
omlish/formats/json/stream/
|
350
|
-
omlish/formats/json/stream/
|
351
|
-
omlish/formats/json/stream/utils.py,sha256=
|
348
|
+
omlish/formats/json/stream/lexing.py,sha256=ItsWvtl5SZH-HwQtPy8Cpf4nszqDzvUTdIOEmSRiZ-E,6807
|
349
|
+
omlish/formats/json/stream/parsing.py,sha256=yvH5Llql3Ri_1xDhi1s9CKL6XLJVSQ8vYJ_dz3KAX-4,6223
|
350
|
+
omlish/formats/json/stream/rendering.py,sha256=uuJc__MR0G5kypYMAAudBNjBfiIzA_GGli-DWT90428,3730
|
351
|
+
omlish/formats/json/stream/utils.py,sha256=UhBRuWbb25wrdQWl8Ttq7xGRLoa329TvNdecGCZxgzg,1197
|
352
352
|
omlish/formats/json5/Json5.g4,sha256=ZUmgJPvj8lSMUD_v3wijp10ZQExYB5mu5Q089dYEJSU,2389
|
353
353
|
omlish/formats/json5/__init__.py,sha256=BsjPz5zJDji3GjQ8x8hWvcl1GYPV_ZIHnE3c2Sr8aTU,102
|
354
354
|
omlish/formats/json5/codec.py,sha256=ldnxCRo0JP1fkGLt0mMxJlLvNxqIF_1KUCcSp1HtI-M,452
|
@@ -365,7 +365,7 @@ omlish/formats/toml/codec.py,sha256=5HFGWEPd9IFxPlRMRheX8FEDlRIzLe1moHEOj2_PFKU,
|
|
365
365
|
omlish/formats/toml/parser.py,sha256=c6Hrf6OfVQVtgsYUXL5P5PQQqF-v7r8nkUmprxhV-lI,30536
|
366
366
|
omlish/formats/toml/writer.py,sha256=HIp6XvriXaPTLqyLe-fkIiEf1Pyhsp0TcOg5rFBpO3g,3226
|
367
367
|
omlish/funcs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
368
|
-
omlish/funcs/genmachine.py,sha256=
|
368
|
+
omlish/funcs/genmachine.py,sha256=8K5fNvFwxctZcVyulOqPLhZ_6Nwh8RAN6yawiE4wFio,2606
|
369
369
|
omlish/funcs/match.py,sha256=gMLZn1enNiFvQaWrQubY300M1BrmdKWzeePihBS7Ywc,6153
|
370
370
|
omlish/funcs/pairs.py,sha256=VCkZjDmJGtR76BsejsHNfb4TcpHCtkkmak-zWDFchAo,3904
|
371
371
|
omlish/funcs/pipes.py,sha256=E7Sz8Aj8ke_vCs5AMNwg1I36kRdHVGTnzxVQaDyn43U,2490
|
@@ -852,9 +852,9 @@ omlish/typedvalues/holder.py,sha256=ZTnHiw-K38ciOBLEdwgrltr7Xp8jjEs_0Lp69DH-G-o,
|
|
852
852
|
omlish/typedvalues/marshal.py,sha256=hWHRLcrGav7lvXJDtb9bNI0ickl4SKPQ6F4BbTpqw3A,4219
|
853
853
|
omlish/typedvalues/reflect.py,sha256=Ih1YgU-srUjsvBn_P7C66f73_VCvcwqE3ffeBnZBgt4,674
|
854
854
|
omlish/typedvalues/values.py,sha256=ym46I-q2QJ_6l4UlERqv3yj87R-kp8nCKMRph0xQ3UA,1307
|
855
|
-
omlish-0.0.0.
|
856
|
-
omlish-0.0.0.
|
857
|
-
omlish-0.0.0.
|
858
|
-
omlish-0.0.0.
|
859
|
-
omlish-0.0.0.
|
860
|
-
omlish-0.0.0.
|
855
|
+
omlish-0.0.0.dev307.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
856
|
+
omlish-0.0.0.dev307.dist-info/METADATA,sha256=UgKZG7ukJ09NYqteFnD8DCdWblMH5cosVoyewHJxBTY,4416
|
857
|
+
omlish-0.0.0.dev307.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
|
858
|
+
omlish-0.0.0.dev307.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
|
859
|
+
omlish-0.0.0.dev307.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
|
860
|
+
omlish-0.0.0.dev307.dist-info/RECORD,,
|
omlish/formats/edn/LICENSE
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
The MIT License (MIT)
|
2
|
-
|
3
|
-
Copyright (c) 2020 Jorin Vogel
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
6
|
-
documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
7
|
-
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
8
|
-
persons to whom the Software is furnished to do so, subject to the following conditions:
|
9
|
-
|
10
|
-
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
11
|
-
Software.
|
12
|
-
|
13
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
14
|
-
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
15
|
-
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
16
|
-
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|