omlish 0.0.0.dev307__py3-none-any.whl → 0.0.0.dev308__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 CHANGED
@@ -1,5 +1,5 @@
1
- __version__ = '0.0.0.dev307'
2
- __revision__ = '7fd729bd16b72af663b113712ea301f150b2449d'
1
+ __version__ = '0.0.0.dev308'
2
+ __revision__ = '78cf17d1a6de1ee32440b0b62de28fdd17f9bedc'
3
3
 
4
4
 
5
5
  #
@@ -50,11 +50,11 @@ class AnyioSubprocesses(AbstractAsyncSubprocesses):
50
50
  stderr = io.BytesIO()
51
51
  tg.start_soon(read_output, proc.stderr, stderr)
52
52
 
53
- if proc.stdin and run.input is not None:
54
- await proc.stdin.send(run.input)
55
- await proc.stdin.aclose()
53
+ if proc.stdin and run.input is not None:
54
+ await proc.stdin.send(run.input)
55
+ await proc.stdin.aclose()
56
56
 
57
- await proc.wait()
57
+ await proc.wait()
58
58
 
59
59
  if run.check and proc.returncode != 0:
60
60
  raise subprocess.CalledProcessError(
@@ -32,6 +32,8 @@ TokenKind: ta.TypeAlias = ta.Literal[
32
32
  'HASH_UNDERSCORE',
33
33
  'META',
34
34
  'QUOTE',
35
+
36
+ 'SPACE',
35
37
  ]
36
38
 
37
39
 
@@ -88,7 +90,13 @@ class StreamLexError(Exception):
88
90
 
89
91
 
90
92
  class StreamLexer(GenMachine[str, Token]):
91
- def __init__(self) -> None:
93
+ def __init__(
94
+ self,
95
+ *,
96
+ include_space: bool = False,
97
+ ) -> None:
98
+ self._include_space = include_space
99
+
92
100
  self._ofs = 0
93
101
  self._line = 1
94
102
  self._col = 0
@@ -155,6 +163,8 @@ class StreamLexer(GenMachine[str, Token]):
155
163
  return None
156
164
 
157
165
  if c.isspace() or c == ',':
166
+ if self._include_space:
167
+ yield self._make_tok('SPACE', c, self.pos)
158
168
  continue
159
169
 
160
170
  if c in SINGLE_TOKENS:
@@ -303,23 +313,3 @@ class StreamLexer(GenMachine[str, Token]):
303
313
  src = self._flip_buf()
304
314
  yield self._make_tok('WORD', src, pos)
305
315
  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()
@@ -178,10 +178,15 @@ class StreamParser(GenMachine[Token, ta.Any]):
178
178
  else:
179
179
  raise
180
180
 
181
- value: ta.Any
181
+ # ignored
182
+
183
+ if tok.kind in ('SPACE', 'COMMENT'):
184
+ continue
182
185
 
183
186
  # scalars
184
187
 
188
+ value: ta.Any
189
+
185
190
  if tok.kind == 'STRING':
186
191
  value = self._parse_string(tok)
187
192
 
@@ -197,9 +202,6 @@ class StreamParser(GenMachine[Token, ta.Any]):
197
202
  else:
198
203
  value = self._parse_word(tok)
199
204
 
200
- elif tok.kind == 'COMMENT':
201
- continue
202
-
203
205
  # open
204
206
 
205
207
  elif tok.kind == 'LPAREN':
@@ -324,8 +326,7 @@ class StreamParser(GenMachine[Token, ta.Any]):
324
326
 
325
327
  return self._char_maker(c)
326
328
 
327
- _INT_PAT = re.compile(r'[-+]?(0|[1-9][0-9]*)')
328
- _BIGINT_PAT = re.compile(r'[-+]?(0|[1-9][0-9]*)N')
329
+ _INT_PAT = re.compile(r'[-+]?(0|[1-9][0-9]*)N?')
329
330
  _FLOAT_PAT = re.compile(r'[-+]?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?(0|[1-9][0-9]*))?M?')
330
331
 
331
332
  def _parse_word(self, tok: Token) -> ta.Any:
@@ -345,10 +346,11 @@ class StreamParser(GenMachine[Token, ta.Any]):
345
346
  # 2r101010, 052, 8r52, 0x2a, 36r16, and 42 are all the same Long.
346
347
  # Floating point numbers are read as Doubles; with M suffix they are read as BigDecimals.
347
348
  # Ratios are supported, e.g. 22/7.
348
- return int(src)
349
+ if src.endswith('N'):
350
+ return int(src[:-1])
349
351
 
350
- elif self._BIGINT_PAT.fullmatch(src):
351
- return int(src[:-1])
352
+ else:
353
+ return int(src)
352
354
 
353
355
  elif self._FLOAT_PAT.fullmatch(src):
354
356
  return float(src)
@@ -376,25 +378,3 @@ def parse(src: str, **kwargs: ta.Any) -> ta.Any | None:
376
378
  if not values:
377
379
  return None
378
380
  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()
@@ -40,7 +40,14 @@ ControlTokenKind: ta.TypeAlias = ta.Literal[
40
40
  'COLON',
41
41
  ]
42
42
 
43
- TokenKind: ta.TypeAlias = ValueTokenKind | ControlTokenKind
43
+ SpaceTokenKind: ta.TypeAlias = ta.Literal['SPACE']
44
+
45
+ TokenKind: ta.TypeAlias = ta.Union[ # noqa
46
+ ValueTokenKind,
47
+ ControlTokenKind,
48
+ SpaceTokenKind,
49
+ ]
50
+
44
51
 
45
52
  #
46
53
 
@@ -109,8 +116,10 @@ class JsonStreamLexer(GenMachine[str, Token]):
109
116
  self,
110
117
  *,
111
118
  include_raw: bool = False,
119
+ include_space: bool = False,
112
120
  ) -> None:
113
121
  self._include_raw = include_raw
122
+ self._include_space = include_space
114
123
 
115
124
  self._ofs = 0
116
125
  self._line = 1
@@ -174,6 +183,8 @@ class JsonStreamLexer(GenMachine[str, Token]):
174
183
  return None
175
184
 
176
185
  if c.isspace():
186
+ if self._include_space:
187
+ yield self._make_tok('SPACE', c, c, self.pos)
177
188
  continue
178
189
 
179
190
  if c in CONTROL_TOKENS:
@@ -282,7 +293,11 @@ class JsonStreamLexer(GenMachine[str, Token]):
282
293
  if c in CONTROL_TOKENS:
283
294
  yield self._make_tok(CONTROL_TOKENS[c], c, c, pos)
284
295
 
285
- elif not c.isspace():
296
+ elif c.isspace():
297
+ if self._include_space:
298
+ yield self._make_tok('SPACE', c, c, self.pos)
299
+
300
+ else:
286
301
  self._raise(f'Unexpected character after number: {c}')
287
302
 
288
303
  return self._do_main()
@@ -102,6 +102,15 @@ class JsonStreamParser(GenMachine[Token, JsonStreamParserEvent]):
102
102
 
103
103
  #
104
104
 
105
+ def _next_tok(self):
106
+ while True:
107
+ tok = yield None
108
+
109
+ if tok.kind != 'SPACE':
110
+ return tok
111
+
112
+ #
113
+
105
114
  def _emit_event(self, v):
106
115
  if not self._stack:
107
116
  return ((v,), self._do_value())
@@ -129,7 +138,7 @@ class JsonStreamParser(GenMachine[Token, JsonStreamParserEvent]):
129
138
 
130
139
  def _do_value(self, *, must_be_present: bool = False):
131
140
  try:
132
- tok = yield None
141
+ tok = yield from self._next_tok()
133
142
  except GeneratorExit:
134
143
  if self._stack:
135
144
  raise JsonStreamParseError('Expected value') from None
@@ -180,7 +189,7 @@ class JsonStreamParser(GenMachine[Token, JsonStreamParserEvent]):
180
189
 
181
190
  def _do_object_body(self, *, must_be_present: bool = False):
182
191
  try:
183
- tok = yield None
192
+ tok = yield from self._next_tok()
184
193
  except GeneratorExit:
185
194
  raise JsonStreamParseError('Expected object body') from None
186
195
 
@@ -188,7 +197,7 @@ class JsonStreamParser(GenMachine[Token, JsonStreamParserEvent]):
188
197
  k = tok.value
189
198
 
190
199
  try:
191
- tok = yield None
200
+ tok = yield from self._next_tok()
192
201
  except GeneratorExit:
193
202
  raise JsonStreamParseError('Expected key') from None
194
203
  if tok.kind != 'COLON':
@@ -211,7 +220,7 @@ class JsonStreamParser(GenMachine[Token, JsonStreamParserEvent]):
211
220
 
212
221
  def _do_after_pair(self):
213
222
  try:
214
- tok = yield None
223
+ tok = yield from self._next_tok()
215
224
  except GeneratorExit:
216
225
  raise JsonStreamParseError('Expected continuation') from None
217
226
 
@@ -244,7 +253,7 @@ class JsonStreamParser(GenMachine[Token, JsonStreamParserEvent]):
244
253
 
245
254
  def _do_after_element(self):
246
255
  try:
247
- tok = yield None
256
+ tok = yield from self._next_tok()
248
257
  except GeneratorExit:
249
258
  raise JsonStreamParseError('Expected continuation') from None
250
259
 
omlish/lang/__init__.py CHANGED
@@ -184,12 +184,11 @@ from .functions import ( # noqa
184
184
  )
185
185
 
186
186
  from .generators import ( # noqa
187
- CoroutineGenerator,
188
- Generator,
189
187
  GeneratorLike,
190
188
  GeneratorMappedIterator,
191
189
  autostart,
192
- corogen,
190
+ capture_coroutine,
191
+ capture_generator,
193
192
  genmap,
194
193
  nextgen,
195
194
  )
omlish/lang/generators.py CHANGED
@@ -2,6 +2,7 @@ import abc
2
2
  import functools
3
3
  import typing as ta
4
4
 
5
+ from .classes.restrict import Abstract
5
6
  from .maybes import Maybe
6
7
  from .maybes import empty
7
8
  from .maybes import just
@@ -79,15 +80,29 @@ def adapt_generator_like(gl):
79
80
  ##
80
81
 
81
82
 
82
- class Generator(ta.Generator[O, I, R]):
83
+ class AbstractGeneratorCapture(Abstract, ta.Generic[O, I, R]):
83
84
  def __init__(self, g: ta.Generator[O, I, R]) -> None:
84
85
  super().__init__()
86
+
85
87
  self._g = g
86
88
 
87
89
  @property
88
90
  def g(self) -> ta.Generator[O, I, R]:
89
91
  return self._g
90
92
 
93
+ #
94
+
95
+ def close(self) -> None:
96
+ self._g.close()
97
+
98
+ def __enter__(self) -> ta.Self:
99
+ return self
100
+
101
+ def __exit__(self, exc_type, exc_val, exc_tb):
102
+ self._g.close()
103
+
104
+
105
+ class GeneratorCapture(AbstractGeneratorCapture[O, I, R], ta.Generator[O, I, R]):
91
106
  value: R
92
107
 
93
108
  def __iter__(self):
@@ -114,35 +129,11 @@ class Generator(ta.Generator[O, I, R]):
114
129
  self.value = e.value
115
130
  raise
116
131
 
117
- def close(self):
118
- self._g.close()
119
132
 
133
+ capture_generator = GeneratorCapture
120
134
 
121
- ##
122
-
123
-
124
- class CoroutineGenerator(ta.Generic[O, I, R]):
125
- def __init__(self, g: ta.Generator[O, I, R]) -> None:
126
- super().__init__()
127
- self._g = g
128
-
129
- @property
130
- def g(self) -> ta.Generator[O, I, R]:
131
- return self._g
132
-
133
- #
134
-
135
- def close(self) -> None:
136
- self._g.close()
137
-
138
- def __enter__(self) -> ta.Self:
139
- return self
140
-
141
- def __exit__(self, exc_type, exc_val, exc_tb):
142
- self._g.close()
143
-
144
- #
145
135
 
136
+ class CoroutineGeneratorCapture(AbstractGeneratorCapture[O, I, R]):
146
137
  class Output(ta.NamedTuple, ta.Generic[T]):
147
138
  v: T
148
139
 
@@ -192,7 +183,7 @@ class CoroutineGenerator(ta.Generic[O, I, R]):
192
183
  return self.Yield(o)
193
184
 
194
185
 
195
- corogen = CoroutineGenerator
186
+ capture_coroutine = CoroutineGeneratorCapture
196
187
 
197
188
 
198
189
  ##
@@ -16,6 +16,7 @@ from .types import ( # noqa
16
16
 
17
17
  NotSpecified,
18
18
  is_not_specified,
19
+ check_not_not_specified,
19
20
 
20
21
  Request,
21
22
  request,
@@ -0,0 +1,222 @@
1
+ """
2
+ TODO:
3
+ - kill receive loop on __aexit__
4
+ """
5
+ import builtins
6
+ import json
7
+ import typing as ta
8
+ import uuid
9
+
10
+ import anyio.abc
11
+
12
+ from ... import lang
13
+ from ... import marshal as msh
14
+ from ...asyncs import anyio as aiu
15
+ from ...io.buffers import DelimitingBuffer
16
+ from .types import Error
17
+ from .types import Id
18
+ from .types import Message
19
+ from .types import NotSpecified
20
+ from .types import Object
21
+ from .types import Request
22
+ from .types import Response
23
+ from .types import detect_message_type
24
+ from .types import notification
25
+ from .types import request
26
+
27
+
28
+ ##
29
+
30
+
31
+ @lang.cached_function
32
+ def _create_id() -> str:
33
+ return str(uuid.uuid4())
34
+
35
+
36
+ class JsonrpcConnection:
37
+ def __init__(
38
+ self,
39
+ tg: anyio.abc.TaskGroup,
40
+ stream: anyio.abc.ByteStream,
41
+ *,
42
+ request_handler: ta.Callable[['JsonrpcConnection', Request], ta.Awaitable[None]] | None = None,
43
+ notification_handler: ta.Callable[['JsonrpcConnection', Request], ta.Awaitable[None]] | None = None,
44
+ default_timeout: float | None = 30.,
45
+ ) -> None:
46
+ super().__init__()
47
+
48
+ self._tg = tg
49
+ self._stream = stream
50
+ self._request_handler = request_handler
51
+ self._notification_handler = notification_handler
52
+ self._default_timeout = default_timeout
53
+
54
+ self._buf = DelimitingBuffer(b'\n')
55
+ self._response_futures_by_id: dict[Id, aiu.Future[Response]] = {}
56
+ self._send_lock = anyio.Lock()
57
+ self._received_eof = False
58
+ self._running = True
59
+
60
+ #
61
+
62
+ class Error(Exception):
63
+ """Base class for JSON-RPC related errors."""
64
+
65
+ class TimeoutError(Error, builtins.TimeoutError): # noqa
66
+ """Raised when a request times out."""
67
+
68
+ class ConnectionError(Error, builtins.ConnectionError): # noqa
69
+ """Raised when there are connection-related issues."""
70
+
71
+ class ProtocolError(Error):
72
+ """Raised when there are protocol-related issues."""
73
+
74
+ #
75
+
76
+ async def __aenter__(self) -> 'JsonrpcConnection':
77
+ await self._tg.start(self._receive_loop)
78
+ return self
79
+
80
+ async def __aexit__(self, exc_type: type[BaseException] | None, *_: object) -> None:
81
+ self._running = False
82
+
83
+ ##
84
+
85
+ async def _handle_message(self, msg: Message) -> None:
86
+ if isinstance(msg, Response):
87
+ msg_id = msg.id
88
+ try:
89
+ resp_fut = self._response_futures_by_id[msg_id]
90
+ except KeyError:
91
+ raise NotImplementedError from None
92
+ resp_fut.set_value(msg)
93
+
94
+ elif isinstance(msg, Request):
95
+ if msg.is_notification:
96
+ if (mh := self._notification_handler) is not None:
97
+ await mh(self, msg)
98
+
99
+ else: # noqa
100
+ if (rh := self._request_handler) is not None:
101
+ await rh(self, msg)
102
+
103
+ else:
104
+ raise TypeError(msg)
105
+
106
+ #
107
+
108
+ CLOSED_EXCEPTIONS: ta.ClassVar[tuple[type[Exception], ...]] = (
109
+ anyio.ClosedResourceError,
110
+ anyio.EndOfStream,
111
+ )
112
+
113
+ ERROR_EXCEPTIONS: ta.ClassVar[tuple[type[Exception], ...]] = (
114
+ OSError,
115
+ anyio.BrokenResourceError,
116
+ )
117
+
118
+ async def _receive_message_batch(self) -> list[Message] | None:
119
+ if self._received_eof:
120
+ return None
121
+
122
+ while True:
123
+ try:
124
+ data = await self._stream.receive()
125
+ except self.CLOSED_EXCEPTIONS:
126
+ data = b''
127
+ except self.ERROR_EXCEPTIONS as e:
128
+ raise JsonrpcConnection.ConnectionError('Failed to receive message') from e
129
+
130
+ if not data:
131
+ self._received_eof = True
132
+
133
+ lines = list(self._buf.feed(data))
134
+ if lines:
135
+ break
136
+
137
+ if not data:
138
+ return None
139
+
140
+ msgs: list[Message] = []
141
+ for line in lines:
142
+ if isinstance(line, DelimitingBuffer.Incomplete):
143
+ raise ConnectionError('Received incomplete message')
144
+
145
+ try:
146
+ dct = json.loads(line.decode('utf-8'))
147
+ except (UnicodeDecodeError, json.JSONDecodeError) as e:
148
+ raise JsonrpcConnection.ProtocolError from e
149
+
150
+ mcls = detect_message_type(dct)
151
+ try:
152
+ msg = msh.unmarshal(dct, mcls)
153
+ except Exception as e:
154
+ raise JsonrpcConnection.ProtocolError from e
155
+
156
+ msgs.append(msg)
157
+
158
+ return msgs
159
+
160
+ async def _receive_loop(
161
+ self,
162
+ *,
163
+ task_status: anyio.abc.TaskStatus[ta.Any] = anyio.TASK_STATUS_IGNORED,
164
+ ) -> None:
165
+ task_status.started()
166
+
167
+ while self._running:
168
+ msgs = await self._receive_message_batch()
169
+ if msgs is None:
170
+ break
171
+
172
+ for msg in msgs:
173
+ await self._handle_message(msg)
174
+
175
+ ##
176
+
177
+ async def send_message(self, msg: Message) -> None:
178
+ async with self._send_lock:
179
+ try:
180
+ await self._stream.send(json.dumps(msh.marshal(msg)).encode() + b'\n')
181
+ except self.ERROR_EXCEPTIONS as e:
182
+ raise ConnectionError('Failed to send message') from e
183
+
184
+ #
185
+
186
+ async def request(
187
+ self,
188
+ method: str,
189
+ params: Object | None = None,
190
+ *,
191
+ timeout: float | None = None,
192
+ ) -> ta.Any:
193
+ msg_id = _create_id()
194
+ req = request(msg_id, method, params)
195
+
196
+ fut = aiu.create_future[Response]()
197
+ self._response_futures_by_id[msg_id] = fut
198
+
199
+ try:
200
+ await self.send_message(req)
201
+
202
+ timeout_val = timeout if timeout is not None else self._default_timeout
203
+ try:
204
+ with anyio.fail_after(timeout_val):
205
+ await fut
206
+ except TimeoutError as e:
207
+ raise JsonrpcConnection.TimeoutError(f'Request timed out after {timeout_val} seconds') from e
208
+
209
+ response = fut.outcome.must().unwrap()
210
+
211
+ if response.error is not NotSpecified:
212
+ error = ta.cast(Error, response.error)
213
+ raise JsonrpcConnection.Error(f'Error {error.code}: {error.message}')
214
+
215
+ return response.result
216
+
217
+ finally:
218
+ self._response_futures_by_id.pop(msg_id, None) # noqa
219
+
220
+ async def notify(self, method: str, params: Object | None = None) -> None:
221
+ msg = notification(method, params)
222
+ await self.send_message(msg)
@@ -18,6 +18,8 @@ from ... import lang
18
18
  from ... import marshal as msh
19
19
 
20
20
 
21
+ T = ta.TypeVar('T')
22
+
21
23
  NUMBER_TYPES: tuple[type, ...] = (int, float)
22
24
  Number: ta.TypeAlias = int | float
23
25
 
@@ -44,6 +46,11 @@ def is_not_specified(v: ta.Any) -> bool:
44
46
  return v is NotSpecified
45
47
 
46
48
 
49
+ def check_not_not_specified(v: T | type[NotSpecified]) -> T:
50
+ check.arg(not is_not_specified(v))
51
+ return ta.cast(T, v)
52
+
53
+
47
54
  ##
48
55
 
49
56
 
@@ -87,10 +94,22 @@ class Response(lang.Final):
87
94
 
88
95
  _: dc.KW_ONLY
89
96
 
97
+ #
98
+
90
99
  result: ta.Any = dc.field(default=NotSpecified)
91
100
  error: ta.Union['Error', type[NotSpecified]] = dc.field(default=NotSpecified)
92
101
  dc.validate(lambda self: is_not_specified(self.result) ^ is_not_specified(self.error))
93
102
 
103
+ @property
104
+ def is_result(self) -> bool:
105
+ return not is_not_specified(self.result)
106
+
107
+ @property
108
+ def is_error(self) -> bool:
109
+ return not is_not_specified(self.error)
110
+
111
+ #
112
+
94
113
  jsonrpc: str = dc.field(default=VERSION)
95
114
  dc.validate(lambda self: self.jsonrpc == VERSION)
96
115
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: omlish
3
- Version: 0.0.0.dev307
3
+ Version: 0.0.0.dev308
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -1,5 +1,5 @@
1
1
  omlish/.manifests.json,sha256=orgsRvtpHu8tdhaCvlP9v3P495OJopYYiHKjK68WtWg,8587
2
- omlish/__about__.py,sha256=YdK-L7JBeMEmm3Dl7hWjoFj3BouojWQPvOl_zSLUgMA,3478
2
+ omlish/__about__.py,sha256=8uwTWCC1I_m-H13aDRaDT3swnjnC8reB6e7B8azZYSA,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
@@ -102,7 +102,7 @@ omlish/asyncs/anyio/backends.py,sha256=jJIymWoiedaEJJm82gvKiJ41EWLQZ-bcyNHpbDpKK
102
102
  omlish/asyncs/anyio/futures.py,sha256=Nm1gLerZEnHk-rlsmr0UfK168IWIK6zA8EebZFtoY_E,2052
103
103
  omlish/asyncs/anyio/signals.py,sha256=ySSut5prdnoy0-5Ws5V1M4cC2ON_vY550vU10d2NHk8,893
104
104
  omlish/asyncs/anyio/streams.py,sha256=Zum2qd1t3EiH6yzGWFwxFw79m-IH2VY5sTUTiluFfIY,2164
105
- omlish/asyncs/anyio/subprocesses.py,sha256=jjMjlcwtIiy-_y-spPn3eTC5dzrqFNSAMTPaIcXH9S8,3002
105
+ omlish/asyncs/anyio/subprocesses.py,sha256=nyl1A9z3rymxQMvIekWHU3IAiKBu1CcEqm-Ag1cGRPY,3018
106
106
  omlish/asyncs/anyio/sync.py,sha256=ZmSNhSsEkPwlXThrpefhtVTxw4GJ9F0P-yKyo5vbbSk,1574
107
107
  omlish/asyncs/anyio/utils.py,sha256=X2Rz1DGrCJ0zkt1O5cHoMRaYKTPndBj6dzLhb09mVtE,1672
108
108
  omlish/asyncs/asyncio/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -321,8 +321,8 @@ omlish/formats/xml.py,sha256=VJfqHR60dhAtjeG8WXFMozFqesTBSGvv264d67eDFXc,3514
321
321
  omlish/formats/yaml.py,sha256=jGPQlTE0vSV-p0O7TJRNlf6o1uq4gx8PrHZe1ApJ_o8,7386
322
322
  omlish/formats/edn/__init__.py,sha256=H3q5B-dibXvQV8pmuWizTo6Xk75M7M0M7VPCLt86rpo,195
323
323
  omlish/formats/edn/codec.py,sha256=k6-Ra3P3Rlv6JA69-jPLI4nCe5XVes_QJbcsj5DYzMM,454
324
- omlish/formats/edn/lexing.py,sha256=plwbFwHLOmrr5_QhmzvMTmTK55Ot0DxRgKY6ASSl_-Y,6966
325
- omlish/formats/edn/parsing.py,sha256=rtoOnDo8TuTo_GAhrNoVHu7Ys7CboALdgOF2PevAJYk,10152
324
+ omlish/formats/edn/lexing.py,sha256=LaIaGql9NtRlgi6bs4XhZ-wtabiUs99PoYN7_yAKMNE,6892
325
+ omlish/formats/edn/parsing.py,sha256=Y1CBxtdlbnn5zwU5nlxX3uw17u2POST8tabtVV1q0X4,9835
326
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
@@ -345,8 +345,8 @@ omlish/formats/json/backends/ujson.py,sha256=BNJCU4kluGHdqTUKLJEuHhE2m2TmqR7HEN2
345
345
  omlish/formats/json/stream/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
346
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/lexing.py,sha256=ItsWvtl5SZH-HwQtPy8Cpf4nszqDzvUTdIOEmSRiZ-E,6807
349
- omlish/formats/json/stream/parsing.py,sha256=yvH5Llql3Ri_1xDhi1s9CKL6XLJVSQ8vYJ_dz3KAX-4,6223
348
+ omlish/formats/json/stream/lexing.py,sha256=0XbkpKm4rmn5DLRyqnVpyvBXMi_MjVEI1k6-TIgQWRM,7208
349
+ omlish/formats/json/stream/parsing.py,sha256=AXsg0N5s0jEvdfEQrzprplZDNkB62l6Q3Pv8rIx3984,6454
350
350
  omlish/formats/json/stream/rendering.py,sha256=uuJc__MR0G5kypYMAAudBNjBfiIzA_GGli-DWT90428,3730
351
351
  omlish/formats/json/stream/utils.py,sha256=UhBRuWbb25wrdQWl8Ttq7xGRLoa329TvNdecGCZxgzg,1197
352
352
  omlish/formats/json5/Json5.g4,sha256=ZUmgJPvj8lSMUD_v3wijp10ZQExYB5mu5Q089dYEJSU,2389
@@ -470,7 +470,7 @@ omlish/iterators/iterators.py,sha256=RxW35yQ5ed8vBQ22IqpDXFx-i5JiLQdp7-pkMZXhJJ8
470
470
  omlish/iterators/recipes.py,sha256=wOwOZg-zWG9Zc3wcAxJFSe2rtavVBYwZOfG09qYEx_4,472
471
471
  omlish/iterators/tools.py,sha256=c4hArZEVV8y9_dFfmRwakusv1cWJLT4MkTkGRjnGN5U,2556
472
472
  omlish/iterators/unique.py,sha256=Nw0pSaNEcHAkve0ugfLPvJcirDOn9ECyC5wIL8JlJKI,1395
473
- omlish/lang/__init__.py,sha256=ldzz3bIIkYhUd-Xmzn62NTOJ6av09vWfJSudkQJvz3M,5862
473
+ omlish/lang/__init__.py,sha256=yJvuoESt6-nZckXYcHctZYEnHCRCjQ2SkRV3ctUljPI,5856
474
474
  omlish/lang/attrs.py,sha256=i7euRF81uNF8QDmUVXSK_BtqLGshaMi4VVdUnMjiMwg,5050
475
475
  omlish/lang/casing.py,sha256=cFUlbDdXLhwnWwcYx4qnM5c4zGX7hIRUfcjiZbxUD28,4636
476
476
  omlish/lang/clsdct.py,sha256=HAGIvBSbCefzRjXriwYSBLO7QHKRv2UsE78jixOb-fA,1828
@@ -481,7 +481,7 @@ omlish/lang/datetimes.py,sha256=mrTtA67JYpfQwSlzdPcBtvm6dAyYM_dXNnlxFwFQH0M,228
481
481
  omlish/lang/descriptors.py,sha256=zBtgO9LjdSTGHNUgiIqswh78WOVoGH6KzS0NbgB1Wls,6572
482
482
  omlish/lang/enums.py,sha256=F9tflHfaAoV2MpyuhZzpfX9-H55M3zNa9hCszsngEo8,111
483
483
  omlish/lang/functions.py,sha256=51CoKtH_-CXUsKvtCexaR3OLZOtIwSdv4f4DtGBZdpA,6029
484
- omlish/lang/generators.py,sha256=5tbjVAywiZH6oAdj1sJLRMtIkC9y3rAkecLT7Z3m7_g,5251
484
+ omlish/lang/generators.py,sha256=yd3ebG2LlA3XQImP8rplt6tSToXwMxhlGRGCkdJ87ME,5230
485
485
  omlish/lang/imports.py,sha256=y9W9Y-d_cQ35QCLuSIPoa6vnEqSErFCz8b-34IH128U,10552
486
486
  omlish/lang/iterables.py,sha256=HOjcxOwyI5bBApDLsxRAGGhTTmw7fdZl2kEckxRVl-0,1994
487
487
  omlish/lang/maybes.py,sha256=pb1YrxmpXy-hWKmWR89GxXqZq1MoUD1uuTaTX30peh0,3697
@@ -688,10 +688,11 @@ omlish/specs/jmespath/lexer.py,sha256=WGxkwQe_dcHWcJcGg9q6K-8_Q0oRdWkw09dYGFNTHb
688
688
  omlish/specs/jmespath/parser.py,sha256=yfkydotVR4LBhrUTsptL_kLYDoGZrRN9zSEs_76kvZM,24441
689
689
  omlish/specs/jmespath/scope.py,sha256=UyDsl9rv_c8DCjJBuVIA2ESu1jrgYvuwEKiaJDQKnT0,1590
690
690
  omlish/specs/jmespath/visitor.py,sha256=HVro_6aBGL0CMBy8NRy6vJzWgwsHGB1qJXldX8H7wSg,16592
691
- omlish/specs/jsonrpc/__init__.py,sha256=QQwr-jkgvwr1ZMlNwl5W1TuHcxx8RuzQVFwWwNhp5sM,515
691
+ omlish/specs/jsonrpc/__init__.py,sha256=ugIdqHXWZjSy1R1SkwoxstO2GCHEF4W95Ogl3_5_DV4,544
692
+ omlish/specs/jsonrpc/conns.py,sha256=Js7DnC48mdnO56-A3wIsgc5ri8CbpAC53USD43eTQSw,6453
692
693
  omlish/specs/jsonrpc/errors.py,sha256=-Zgmlo6bV6J8w5f8h9axQgLquIFBHDgIwcpufEH5NsE,707
693
694
  omlish/specs/jsonrpc/marshal.py,sha256=HM736piPGnBZrg8CMLDX-L5fZpegyF6l6JUjzLoSDtk,1852
694
- omlish/specs/jsonrpc/types.py,sha256=emEiTPWsjsYy0jCC3It1bUEcu9nHp5y7-j73U1D6vl4,2700
695
+ omlish/specs/jsonrpc/types.py,sha256=Se9ecG-_k-kY_Qlt9QD2t3y26oY4sXTcskp6XZfVans,3054
695
696
  omlish/specs/jsonschema/__init__.py,sha256=55P7Yg2MprqDyaifac2ExNzK6blTZuDP4ejrUXZWpt8,1129
696
697
  omlish/specs/jsonschema/types.py,sha256=_H7ma99hD3_Xu42BFGHOXRI5p79tY8WBX8QE36k7lbw,472
697
698
  omlish/specs/jsonschema/keywords/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -852,9 +853,9 @@ omlish/typedvalues/holder.py,sha256=ZTnHiw-K38ciOBLEdwgrltr7Xp8jjEs_0Lp69DH-G-o,
852
853
  omlish/typedvalues/marshal.py,sha256=hWHRLcrGav7lvXJDtb9bNI0ickl4SKPQ6F4BbTpqw3A,4219
853
854
  omlish/typedvalues/reflect.py,sha256=Ih1YgU-srUjsvBn_P7C66f73_VCvcwqE3ffeBnZBgt4,674
854
855
  omlish/typedvalues/values.py,sha256=ym46I-q2QJ_6l4UlERqv3yj87R-kp8nCKMRph0xQ3UA,1307
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,,
856
+ omlish-0.0.0.dev308.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
857
+ omlish-0.0.0.dev308.dist-info/METADATA,sha256=-f4JyYLhz7RVYUCBHyIx0neYBnC4SadbuFbwS9NKl6E,4416
858
+ omlish-0.0.0.dev308.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
859
+ omlish-0.0.0.dev308.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
860
+ omlish-0.0.0.dev308.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
861
+ omlish-0.0.0.dev308.dist-info/RECORD,,