omlish 0.0.0.dev308__py3-none-any.whl → 0.0.0.dev310__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.dev308'
2
- __revision__ = '78cf17d1a6de1ee32440b0b62de28fdd17f9bedc'
1
+ __version__ = '0.0.0.dev310'
2
+ __revision__ = '7f687bb413cb71d3946d96c270694e90141e72e3'
3
3
 
4
4
 
5
5
  #
omlish/antlr/delimit.py CHANGED
@@ -6,6 +6,9 @@ from .. import check
6
6
  from . import runtime as antlr4
7
7
 
8
8
 
9
+ ##
10
+
11
+
9
12
  class DelimitingLexer(antlr4.Lexer):
10
13
  def __init__(
11
14
  self,
omlish/antlr/dot.py CHANGED
@@ -5,6 +5,9 @@ from . import runtime as antlr4
5
5
  from .utils import yield_contexts
6
6
 
7
7
 
8
+ ##
9
+
10
+
8
11
  def dot_ctx(
9
12
  root: antlr4.ParserRuleContext,
10
13
  *,
omlish/antlr/errors.py CHANGED
@@ -2,6 +2,9 @@
2
2
  from . import runtime as antlr4
3
3
 
4
4
 
5
+ ##
6
+
7
+
5
8
  class ParseError(Exception):
6
9
  pass
7
10
 
omlish/antlr/parsing.py CHANGED
@@ -10,6 +10,9 @@ LexerT = ta.TypeVar('LexerT', bound=antlr4.Lexer)
10
10
  ParserT = ta.TypeVar('ParserT', bound=antlr4.Parser)
11
11
 
12
12
 
13
+ ##
14
+
15
+
13
16
  def is_eof_context(ctx: antlr4.ParserRuleContext) -> bool:
14
17
  return ctx.getChildCount() == 1 and ctx.getChild(0).getSymbol().type == antlr4.Token.EOF
15
18
 
@@ -14,7 +14,7 @@ async def asyncio_wait_until_can_connect(
14
14
  host: ta.Any = None,
15
15
  port: ta.Any = None,
16
16
  *,
17
- timeout: ta.Optional[TimeoutLike] = None,
17
+ timeout: TimeoutLike = None,
18
18
  on_fail: ta.Optional[ta.Callable[[BaseException], None]] = None,
19
19
  sleep_s: float = .1,
20
20
  exception: ta.Union[ta.Type[BaseException], ta.Tuple[ta.Type[BaseException], ...]] = (Exception,),
@@ -131,7 +131,7 @@ class AsyncioProcessCommunicator:
131
131
  async def communicate(
132
132
  self,
133
133
  input: ta.Any = None, # noqa
134
- timeout: ta.Optional[TimeoutLike] = None,
134
+ timeout: TimeoutLike = None,
135
135
  ) -> Communication:
136
136
  return await asyncio_maybe_timeout(self._communicate(input), timeout)
137
137
 
@@ -144,7 +144,7 @@ class AsyncioSubprocesses(AbstractAsyncSubprocesses):
144
144
  self,
145
145
  proc: asyncio.subprocess.Process,
146
146
  input: ta.Any = None, # noqa
147
- timeout: ta.Optional[TimeoutLike] = None,
147
+ timeout: TimeoutLike = None,
148
148
  ) -> ta.Tuple[ta.Optional[bytes], ta.Optional[bytes]]:
149
149
  return await AsyncioProcessCommunicator(proc).communicate(input, timeout) # noqa
150
150
 
@@ -155,7 +155,7 @@ class AsyncioSubprocesses(AbstractAsyncSubprocesses):
155
155
  self,
156
156
  *cmd: str,
157
157
  shell: bool = False,
158
- timeout: ta.Optional[TimeoutLike] = None,
158
+ timeout: TimeoutLike = None,
159
159
  **kwargs: ta.Any,
160
160
  ) -> ta.AsyncGenerator[asyncio.subprocess.Process, None]:
161
161
  with self.prepare_and_wrap( *cmd, shell=shell, **kwargs) as (cmd, kwargs): # noqa
@@ -15,7 +15,7 @@ AwaitableT = ta.TypeVar('AwaitableT', bound=ta.Awaitable)
15
15
 
16
16
  def asyncio_maybe_timeout(
17
17
  fut: AwaitableT,
18
- timeout: ta.Optional[TimeoutLike] = None,
18
+ timeout: TimeoutLike = None,
19
19
  ) -> AwaitableT:
20
20
  if timeout is not None:
21
21
  fut = asyncio.wait_for(fut, Timeout.of(timeout)()) # type: ignore
omlish/daemons/daemon.py CHANGED
@@ -109,7 +109,7 @@ class Daemon:
109
109
 
110
110
  def wait_sync(
111
111
  self,
112
- timeout: lang.TimeoutLike = lang.Timeout.Default,
112
+ timeout: lang.TimeoutLike = lang.Timeout.DEFAULT,
113
113
  *,
114
114
  max_tries: int | None = None,
115
115
  ) -> None:
@@ -140,7 +140,7 @@ class Daemon:
140
140
 
141
141
  return launcher.launch()
142
142
 
143
- def launch(self, timeout: lang.TimeoutLike = lang.Timeout.Default) -> None:
143
+ def launch(self, timeout: lang.TimeoutLike = lang.Timeout.DEFAULT) -> None:
144
144
  self.launch_no_wait()
145
145
 
146
146
  self.wait_sync(timeout)
@@ -156,29 +156,37 @@ class TomlFlags:
156
156
  def set(self, key: TomlKey, flag: int, *, recursive: bool) -> None: # noqa: A003
157
157
  cont = self._flags
158
158
  key_parent, key_stem = key[:-1], key[-1]
159
+
159
160
  for k in key_parent:
160
161
  if k not in cont:
161
162
  cont[k] = {'flags': set(), 'recursive_flags': set(), 'nested': {}}
162
163
  cont = cont[k]['nested']
164
+
163
165
  if key_stem not in cont:
164
166
  cont[key_stem] = {'flags': set(), 'recursive_flags': set(), 'nested': {}}
167
+
165
168
  cont[key_stem]['recursive_flags' if recursive else 'flags'].add(flag)
166
169
 
167
170
  def is_(self, key: TomlKey, flag: int) -> bool:
168
171
  if not key:
169
172
  return False # document root has no flags
173
+
170
174
  cont = self._flags
171
175
  for k in key[:-1]:
172
176
  if k not in cont:
173
177
  return False
178
+
174
179
  inner_cont = cont[k]
175
180
  if flag in inner_cont['recursive_flags']:
176
181
  return True
182
+
177
183
  cont = inner_cont['nested']
184
+
178
185
  key_stem = key[-1]
179
186
  if key_stem in cont:
180
187
  cont = cont[key_stem]
181
188
  return flag in cont['flags'] or flag in cont['recursive_flags']
189
+
182
190
  return False
183
191
 
184
192
 
@@ -196,24 +204,31 @@ class TomlNestedDict:
196
204
  access_lists: bool = True,
197
205
  ) -> dict:
198
206
  cont: ta.Any = self.dict
207
+
199
208
  for k in key:
200
209
  if k not in cont:
201
210
  cont[k] = {}
211
+
202
212
  cont = cont[k]
213
+
203
214
  if access_lists and isinstance(cont, list):
204
215
  cont = cont[-1]
216
+
205
217
  if not isinstance(cont, dict):
206
218
  raise KeyError('There is no nest behind this key')
219
+
207
220
  return cont
208
221
 
209
222
  def append_nest_to_list(self, key: TomlKey) -> None:
210
223
  cont = self.get_or_create_nest(key[:-1])
224
+
211
225
  last_key = key[-1]
212
226
  if last_key in cont:
213
227
  list_ = cont[last_key]
214
228
  if not isinstance(list_, list):
215
229
  raise KeyError('An object other than list found behind this key')
216
230
  list_.append({})
231
+
217
232
  else:
218
233
  cont[last_key] = [{}]
219
234
 
@@ -283,23 +298,30 @@ class TomlParser:
283
298
  char = self.src[self.pos]
284
299
  except IndexError:
285
300
  break
301
+
286
302
  if char == '\n':
287
303
  self.pos += 1
288
304
  continue
305
+
289
306
  if char in self.KEY_INITIAL_CHARS:
290
307
  self.key_value_rule(header)
291
308
  self.skip_chars(self.WS)
309
+
292
310
  elif char == '[':
293
311
  try:
294
312
  second_char: ta.Optional[str] = self.src[self.pos + 1]
295
313
  except IndexError:
296
314
  second_char = None
315
+
297
316
  self.flags.finalize_pending()
317
+
298
318
  if second_char == '[':
299
319
  header = self.create_list_rule()
300
320
  else:
301
321
  header = self.create_dict_rule()
322
+
302
323
  self.skip_chars(self.WS)
324
+
303
325
  elif char != '#':
304
326
  raise self.suffixed_err('Invalid statement')
305
327
 
@@ -311,8 +333,10 @@ class TomlParser:
311
333
  char = self.src[self.pos]
312
334
  except IndexError:
313
335
  break
336
+
314
337
  if char != '\n':
315
338
  raise self.suffixed_err('Expected newline or end of document after a statement')
339
+
316
340
  self.pos += 1
317
341
 
318
342
  return self.data.dict
@@ -341,7 +365,9 @@ class TomlParser:
341
365
  if not error_on.isdisjoint(self.src[self.pos:new_pos]):
342
366
  while self.src[self.pos] not in error_on:
343
367
  self.pos += 1
368
+
344
369
  raise self.suffixed_err(f'Found invalid character {self.src[self.pos]!r}')
370
+
345
371
  self.pos = new_pos
346
372
 
347
373
  def skip_comment(self) -> None:
@@ -349,6 +375,7 @@ class TomlParser:
349
375
  char: ta.Optional[str] = self.src[self.pos]
350
376
  except IndexError:
351
377
  char = None
378
+
352
379
  if char == '#':
353
380
  self.pos += 1
354
381
  self.skip_until(
@@ -372,7 +399,9 @@ class TomlParser:
372
399
 
373
400
  if self.flags.is_(key, TomlFlags.EXPLICIT_NEST) or self.flags.is_(key, TomlFlags.FROZEN):
374
401
  raise self.suffixed_err(f'Cannot declare {key} twice')
402
+
375
403
  self.flags.set(key, TomlFlags.EXPLICIT_NEST, recursive=False)
404
+
376
405
  try:
377
406
  self.data.get_or_create_nest(key)
378
407
  except KeyError:
@@ -380,20 +409,25 @@ class TomlParser:
380
409
 
381
410
  if not self.src.startswith(']', self.pos):
382
411
  raise self.suffixed_err("Expected ']' at the end of a table declaration")
412
+
383
413
  self.pos += 1
384
414
  return key
385
415
 
386
416
  def create_list_rule(self) -> TomlKey:
387
417
  self.pos += 2 # Skip "[["
388
418
  self.skip_chars(self.WS)
419
+
389
420
  key = self.parse_key()
390
421
 
391
422
  if self.flags.is_(key, TomlFlags.FROZEN):
392
423
  raise self.suffixed_err(f'Cannot mutate immutable namespace {key}')
424
+
393
425
  # Free the namespace now that it points to another empty list item...
394
426
  self.flags.unset_all(key)
427
+
395
428
  # ...but this key precisely is still prohibited from table declaration
396
429
  self.flags.set(key, TomlFlags.EXPLICIT_NEST, recursive=False)
430
+
397
431
  try:
398
432
  self.data.append_nest_to_list(key)
399
433
  except KeyError:
@@ -401,6 +435,7 @@ class TomlParser:
401
435
 
402
436
  if not self.src.startswith(']]', self.pos):
403
437
  raise self.suffixed_err("Expected ']]' at the end of an array declaration")
438
+
404
439
  self.pos += 2
405
440
  return key
406
441
 
@@ -414,6 +449,7 @@ class TomlParser:
414
449
  # Check that dotted key syntax does not redefine an existing table
415
450
  if self.flags.is_(cont_key, TomlFlags.EXPLICIT_NEST):
416
451
  raise self.suffixed_err(f'Cannot redefine namespace {cont_key}')
452
+
417
453
  # Containers in the relative path can't be opened with the table syntax or dotted key/value syntax in
418
454
  # following table sections.
419
455
  self.flags.add_pending(cont_key, TomlFlags.EXPLICIT_NEST)
@@ -425,41 +461,54 @@ class TomlParser:
425
461
  nest = self.data.get_or_create_nest(abs_key_parent)
426
462
  except KeyError:
427
463
  raise self.suffixed_err('Cannot overwrite a value') from None
464
+
428
465
  if key_stem in nest:
429
466
  raise self.suffixed_err('Cannot overwrite a value')
467
+
430
468
  # Mark inline table and array namespaces recursively immutable
431
469
  if isinstance(value, (dict, list)):
432
470
  self.flags.set(header + key, TomlFlags.FROZEN, recursive=True)
471
+
433
472
  nest[key_stem] = value
434
473
 
435
474
  def parse_key_value_pair(self) -> ta.Tuple[TomlKey, ta.Any]:
436
475
  key = self.parse_key()
476
+
437
477
  try:
438
478
  char: ta.Optional[str] = self.src[self.pos]
439
479
  except IndexError:
440
480
  char = None
481
+
441
482
  if char != '=':
442
483
  raise self.suffixed_err("Expected '=' after a key in a key/value pair")
484
+
443
485
  self.pos += 1
444
486
  self.skip_chars(self.WS)
487
+
445
488
  value = self.parse_value()
446
489
  return key, value
447
490
 
448
491
  def parse_key(self) -> TomlKey:
449
492
  key_part = self.parse_key_part()
450
493
  key: TomlKey = (key_part,)
494
+
451
495
  self.skip_chars(self.WS)
496
+
452
497
  while True:
453
498
  try:
454
499
  char: ta.Optional[str] = self.src[self.pos]
455
500
  except IndexError:
456
501
  char = None
502
+
457
503
  if char != '.':
458
504
  return key
505
+
459
506
  self.pos += 1
460
507
  self.skip_chars(self.WS)
508
+
461
509
  key_part = self.parse_key_part()
462
510
  key += (key_part,)
511
+
463
512
  self.skip_chars(self.WS)
464
513
 
465
514
  def parse_key_part(self) -> str:
@@ -467,14 +516,18 @@ class TomlParser:
467
516
  char: ta.Optional[str] = self.src[self.pos]
468
517
  except IndexError:
469
518
  char = None
519
+
470
520
  if char in self.BARE_KEY_CHARS:
471
521
  start_pos = self.pos
472
522
  self.skip_chars(self.BARE_KEY_CHARS)
473
523
  return self.src[start_pos:self.pos]
524
+
474
525
  if char == "'":
475
526
  return self.parse_literal_str()
527
+
476
528
  if char == '"':
477
529
  return self.parse_one_line_basic_str()
530
+
478
531
  raise self.suffixed_err('Invalid initial character for a key part')
479
532
 
480
533
  def parse_one_line_basic_str(self) -> str:
@@ -489,6 +542,7 @@ class TomlParser:
489
542
  if self.src.startswith(']', self.pos):
490
543
  self.pos += 1
491
544
  return array
545
+
492
546
  while True:
493
547
  val = self.parse_value()
494
548
  array.append(val)
@@ -498,11 +552,14 @@ class TomlParser:
498
552
  if c == ']':
499
553
  self.pos += 1
500
554
  return array
555
+
501
556
  if c != ',':
502
557
  raise self.suffixed_err('Unclosed array')
558
+
503
559
  self.pos += 1
504
560
 
505
561
  self.skip_comments_and_array_ws()
562
+
506
563
  if self.src.startswith(']', self.pos):
507
564
  self.pos += 1
508
565
  return array
@@ -513,54 +570,72 @@ class TomlParser:
513
570
  flags = TomlFlags()
514
571
 
515
572
  self.skip_chars(self.WS)
573
+
516
574
  if self.src.startswith('}', self.pos):
517
575
  self.pos += 1
518
576
  return nested_dict.dict
577
+
519
578
  while True:
520
579
  key, value = self.parse_key_value_pair()
521
580
  key_parent, key_stem = key[:-1], key[-1]
581
+
522
582
  if flags.is_(key, TomlFlags.FROZEN):
523
583
  raise self.suffixed_err(f'Cannot mutate immutable namespace {key}')
584
+
524
585
  try:
525
586
  nest = nested_dict.get_or_create_nest(key_parent, access_lists=False)
526
587
  except KeyError:
527
588
  raise self.suffixed_err('Cannot overwrite a value') from None
589
+
528
590
  if key_stem in nest:
529
591
  raise self.suffixed_err(f'Duplicate inline table key {key_stem!r}')
592
+
530
593
  nest[key_stem] = value
531
594
  self.skip_chars(self.WS)
595
+
532
596
  c = self.src[self.pos:self.pos + 1]
533
597
  if c == '}':
534
598
  self.pos += 1
535
599
  return nested_dict.dict
600
+
536
601
  if c != ',':
537
602
  raise self.suffixed_err('Unclosed inline table')
603
+
538
604
  if isinstance(value, (dict, list)):
539
605
  flags.set(key, TomlFlags.FROZEN, recursive=True)
606
+
540
607
  self.pos += 1
541
608
  self.skip_chars(self.WS)
542
609
 
543
610
  def parse_basic_str_escape(self, multiline: bool = False) -> str:
544
611
  escape_id = self.src[self.pos:self.pos + 2]
545
612
  self.pos += 2
613
+
546
614
  if multiline and escape_id in {'\\ ', '\\\t', '\\\n'}:
547
615
  # Skip whitespace until next non-whitespace character or end of the doc. Error if non-whitespace is found
548
616
  # before newline.
549
617
  if escape_id != '\\\n':
550
618
  self.skip_chars(self.WS)
619
+
551
620
  try:
552
621
  char = self.src[self.pos]
553
622
  except IndexError:
554
623
  return ''
624
+
555
625
  if char != '\n':
556
626
  raise self.suffixed_err("Unescaped '\\' in a string")
627
+
557
628
  self.pos += 1
629
+
558
630
  self.skip_chars(self.WS_AND_NEWLINE)
559
631
  return ''
632
+
560
633
  if escape_id == '\\u':
561
634
  return self.parse_hex_char(4)
635
+
562
636
  if escape_id == '\\U':
563
637
  return self.parse_hex_char(8)
638
+
564
639
  try:
565
640
  return self.BASIC_STR_ESCAPE_REPLACEMENTS[escape_id]
566
641
  except KeyError:
@@ -575,12 +650,16 @@ class TomlParser:
575
650
 
576
651
  def parse_hex_char(self, hex_len: int) -> str:
577
652
  hex_str = self.src[self.pos:self.pos + hex_len]
653
+
578
654
  if len(hex_str) != hex_len or not self.HEXDIGIT_CHARS.issuperset(hex_str):
579
655
  raise self.suffixed_err('Invalid hex value')
656
+
580
657
  self.pos += hex_len
581
658
  hex_int = int(hex_str, 16)
659
+
582
660
  if not self.is_unicode_scalar_value(hex_int):
583
661
  raise self.suffixed_err('Escaped character is not a Unicode scalar value')
662
+
584
663
  return chr(hex_int)
585
664
 
586
665
  def parse_literal_str(self) -> str:
@@ -606,6 +685,7 @@ class TomlParser:
606
685
  )
607
686
  result = self.src[start_pos:self.pos]
608
687
  self.pos += 3
688
+
609
689
  else:
610
690
  delim = '"'
611
691
  result = self.parse_basic_str(multiline=True)
@@ -613,9 +693,11 @@ class TomlParser:
613
693
  # Add at maximum two extra apostrophes/quotes if the end sequence is 4 or 5 chars long instead of just 3.
614
694
  if not self.src.startswith(delim, self.pos):
615
695
  return result
696
+
616
697
  self.pos += 1
617
698
  if not self.src.startswith(delim, self.pos):
618
699
  return result + delim
700
+
619
701
  self.pos += 1
620
702
  return result + (delim * 2)
621
703
 
@@ -626,6 +708,7 @@ class TomlParser:
626
708
  else:
627
709
  error_on = self.ILLEGAL_BASIC_STR_CHARS
628
710
  parse_escapes = self.parse_basic_str_escape
711
+
629
712
  result = ''
630
713
  start_pos = self.pos
631
714
  while True:
@@ -633,25 +716,31 @@ class TomlParser:
633
716
  char = self.src[self.pos]
634
717
  except IndexError:
635
718
  raise self.suffixed_err('Unterminated string') from None
719
+
636
720
  if char == '"':
637
721
  if not multiline:
638
722
  end_pos = self.pos
639
723
  self.pos += 1
640
724
  return result + self.src[start_pos:end_pos]
725
+
641
726
  if self.src.startswith('"""', self.pos):
642
727
  end_pos = self.pos
643
728
  self.pos += 3
644
729
  return result + self.src[start_pos:end_pos]
730
+
645
731
  self.pos += 1
646
732
  continue
733
+
647
734
  if char == '\\':
648
735
  result += self.src[start_pos:self.pos]
649
736
  parsed_escape = parse_escapes()
650
737
  result += parsed_escape
651
738
  start_pos = self.pos
652
739
  continue
740
+
653
741
  if char in error_on:
654
742
  raise self.suffixed_err(f'Illegal character {char!r}')
743
+
655
744
  self.pos += 1
656
745
 
657
746
  def parse_value(self) -> ta.Any: # noqa: C901
@@ -679,6 +768,7 @@ class TomlParser:
679
768
  if self.src.startswith('true', self.pos):
680
769
  self.pos += 4
681
770
  return True
771
+
682
772
  if char == 'f':
683
773
  if self.src.startswith('false', self.pos):
684
774
  self.pos += 5
@@ -699,8 +789,10 @@ class TomlParser:
699
789
  datetime_obj = self.match_to_datetime(datetime_match)
700
790
  except ValueError as e:
701
791
  raise self.suffixed_err('Invalid date or datetime') from e
792
+
702
793
  self.pos = datetime_match.end()
703
794
  return datetime_obj
795
+
704
796
  localtime_match = self.RE_LOCALTIME.match(self.src, self.pos)
705
797
  if localtime_match:
706
798
  self.pos = localtime_match.end()
@@ -718,6 +810,7 @@ class TomlParser:
718
810
  if first_three in {'inf', 'nan'}:
719
811
  self.pos += 3
720
812
  return self.parse_float(first_three)
813
+
721
814
  first_four = self.src[self.pos:self.pos + 4]
722
815
  if first_four in {'-inf', '+inf', '-nan', '+nan'}:
723
816
  self.pos += 4
@@ -728,11 +821,13 @@ class TomlParser:
728
821
  def coord_repr(self, pos: TomlPos) -> str:
729
822
  if pos >= len(self.src):
730
823
  return 'end of document'
824
+
731
825
  line = self.src.count('\n', 0, pos) + 1
732
826
  if line == 1:
733
827
  column = pos + 1
734
828
  else:
735
829
  column = pos - self.src.rindex('\n', 0, pos)
830
+
736
831
  return f'line {line}, column {column}'
737
832
 
738
833
  def suffixed_err(self, msg: str, *, pos: ta.Optional[TomlPos] = None) -> TomlDecodeError:
@@ -799,11 +894,16 @@ class TomlParser:
799
894
  offset_hour_str,
800
895
  offset_minute_str,
801
896
  ) = match.groups()
897
+
802
898
  year, month, day = int(year_str), int(month_str), int(day_str)
899
+
803
900
  if hour_str is None:
804
901
  return datetime.date(year, month, day)
902
+
805
903
  hour, minute, sec = int(hour_str), int(minute_str), int(sec_str)
904
+
806
905
  micros = int(micros_str.ljust(6, '0')) if micros_str else 0
906
+
807
907
  if offset_sign_str:
808
908
  tz: ta.Optional[datetime.tzinfo] = toml_cached_tz(
809
909
  offset_hour_str, offset_minute_str, offset_sign_str,
@@ -812,6 +912,7 @@ class TomlParser:
812
912
  tz = datetime.UTC
813
913
  else: # local date-time
814
914
  tz = None
915
+
815
916
  return datetime.datetime(year, month, day, hour, minute, sec, micros, tzinfo=tz)
816
917
 
817
918
  @classmethod
omlish/lite/timeouts.py CHANGED
@@ -8,7 +8,7 @@ import time
8
8
  import typing as ta
9
9
 
10
10
 
11
- TimeoutLike = ta.Union['Timeout', ta.Type['Timeout.Default'], ta.Iterable['TimeoutLike'], float] # ta.TypeAlias
11
+ TimeoutLike = ta.Union['Timeout', ta.Type['Timeout.DEFAULT'], ta.Iterable['TimeoutLike'], float, None] # ta.TypeAlias
12
12
 
13
13
 
14
14
  ##
@@ -54,7 +54,7 @@ class Timeout(abc.ABC):
54
54
 
55
55
  #
56
56
 
57
- class Default:
57
+ class DEFAULT: # Noqa
58
58
  def __new__(cls, *args, **kwargs): # noqa
59
59
  raise TypeError
60
60
 
@@ -65,7 +65,7 @@ class Timeout(abc.ABC):
65
65
  @classmethod
66
66
  def of(
67
67
  cls,
68
- obj: ta.Optional[TimeoutLike],
68
+ obj: TimeoutLike,
69
69
  default: ta.Union[TimeoutLike, ta.Type[_NOT_SPECIFIED]] = _NOT_SPECIFIED,
70
70
  ) -> 'Timeout':
71
71
  if obj is None:
@@ -80,8 +80,8 @@ class Timeout(abc.ABC):
80
80
  elif isinstance(obj, ta.Iterable):
81
81
  return CompositeTimeout(*[Timeout.of(c) for c in obj])
82
82
 
83
- elif obj is Timeout.Default:
84
- if default is Timeout._NOT_SPECIFIED or default is Timeout.Default:
83
+ elif obj is Timeout.DEFAULT:
84
+ if default is Timeout._NOT_SPECIFIED or default is Timeout.DEFAULT:
85
85
  raise RuntimeError('Must specify a default timeout')
86
86
 
87
87
  else:
@@ -64,7 +64,7 @@ class PidfilePinner(abc.ABC):
64
64
  self,
65
65
  path: str,
66
66
  *,
67
- timeout: ta.Optional[TimeoutLike] = None,
67
+ timeout: TimeoutLike = None,
68
68
  inheritable: bool = False, # Present to match Pidfile kwargs for convenience, but enforced to be False.
69
69
  **kwargs: ta.Any,
70
70
  ) -> ta.Iterator[int]:
omlish/sockets/ports.py CHANGED
@@ -38,7 +38,7 @@ def get_available_ports(
38
38
  *,
39
39
  host: ta.Optional[str] = None,
40
40
  exclude: ta.Optional[ta.Iterable[int]] = None,
41
- timeout: ta.Optional[TimeoutLike] = None,
41
+ timeout: TimeoutLike = None,
42
42
  ) -> ta.List[int]:
43
43
  exclude = set(exclude or [])
44
44
 
omlish/sockets/wait.py CHANGED
@@ -14,7 +14,7 @@ from ..lite.timeouts import TimeoutLike
14
14
  def socket_can_connect(
15
15
  address: ta.Any,
16
16
  *,
17
- timeout: ta.Optional[TimeoutLike] = None,
17
+ timeout: TimeoutLike = None,
18
18
  on_fail: ta.Optional[ta.Callable[[BaseException], None]] = None,
19
19
  exception: ta.Union[ta.Type[BaseException], ta.Tuple[ta.Type[BaseException], ...]] = (ConnectionRefusedError,),
20
20
  ) -> bool:
@@ -36,7 +36,7 @@ def socket_can_connect(
36
36
  def socket_wait_until_can_connect(
37
37
  address: ta.Any,
38
38
  *,
39
- timeout: ta.Optional[TimeoutLike] = None,
39
+ timeout: TimeoutLike = None,
40
40
  on_fail: ta.Optional[ta.Callable[[BaseException], None]] = None,
41
41
  sleep_s: float = .1,
42
42
  exception: ta.Union[ta.Type[BaseException], ta.Tuple[ta.Type[BaseException], ...]] = (ConnectionRefusedError,),
@@ -1,14 +1,12 @@
1
- """
2
- TODO:
3
- - kill receive loop on __aexit__
4
- """
5
1
  import builtins
2
+ import functools
6
3
  import json
7
4
  import typing as ta
8
5
  import uuid
9
6
 
10
7
  import anyio.abc
11
8
 
9
+ from ... import check
12
10
  from ... import lang
13
11
  from ... import marshal as msh
14
12
  from ...asyncs import anyio as aiu
@@ -54,8 +52,8 @@ class JsonrpcConnection:
54
52
  self._buf = DelimitingBuffer(b'\n')
55
53
  self._response_futures_by_id: dict[Id, aiu.Future[Response]] = {}
56
54
  self._send_lock = anyio.Lock()
55
+ self._shutdown_event = anyio.Event()
57
56
  self._received_eof = False
58
- self._running = True
59
57
 
60
58
  #
61
59
 
@@ -78,7 +76,7 @@ class JsonrpcConnection:
78
76
  return self
79
77
 
80
78
  async def __aexit__(self, exc_type: type[BaseException] | None, *_: object) -> None:
81
- self._running = False
79
+ self._shutdown_event.set()
82
80
 
83
81
  ##
84
82
 
@@ -116,12 +114,28 @@ class JsonrpcConnection:
116
114
  )
117
115
 
118
116
  async def _receive_message_batch(self) -> list[Message] | None:
119
- if self._received_eof:
117
+ check.state(not self._received_eof)
118
+
119
+ if self._shutdown_event.is_set():
120
120
  return None
121
121
 
122
122
  while True:
123
+ maybe_shutdown: lang.Maybe[bool]
124
+ maybe_data: lang.Maybe[lang.Outcome[bytes]]
125
+ (
126
+ maybe_shutdown,
127
+ maybe_data,
128
+ ) = await aiu.gather( # type: ignore
129
+ self._shutdown_event.wait,
130
+ functools.partial(lang.acapture, self._stream.receive),
131
+ take_first=True,
132
+ )
133
+
134
+ if self._shutdown_event.is_set():
135
+ return None
136
+
123
137
  try:
124
- data = await self._stream.receive()
138
+ data = maybe_data.must().unwrap()
125
139
  except self.CLOSED_EXCEPTIONS:
126
140
  data = b''
127
141
  except self.ERROR_EXCEPTIONS as e:
@@ -164,7 +178,7 @@ class JsonrpcConnection:
164
178
  ) -> None:
165
179
  task_status.started()
166
180
 
167
- while self._running:
181
+ while not self._shutdown_event.is_set():
168
182
  msgs = await self._receive_message_batch()
169
183
  if msgs is None:
170
184
  break
@@ -188,7 +202,7 @@ class JsonrpcConnection:
188
202
  method: str,
189
203
  params: Object | None = None,
190
204
  *,
191
- timeout: float | None = None,
205
+ timeout: lang.TimeoutLike | None = lang.Timeout.DEFAULT,
192
206
  ) -> ta.Any:
193
207
  msg_id = _create_id()
194
208
  req = request(msg_id, method, params)
@@ -199,9 +213,9 @@ class JsonrpcConnection:
199
213
  try:
200
214
  await self.send_message(req)
201
215
 
202
- timeout_val = timeout if timeout is not None else self._default_timeout
216
+ timeout_val = lang.Timeout.of(timeout, self._default_timeout)
203
217
  try:
204
- with anyio.fail_after(timeout_val):
218
+ with anyio.fail_after(timeout_val.or_(None)):
205
219
  await fut
206
220
  except TimeoutError as e:
207
221
  raise JsonrpcConnection.TimeoutError(f'Request timed out after {timeout_val} seconds') from e
@@ -22,7 +22,7 @@ class AbstractAsyncSubprocesses(BaseSubprocesses):
22
22
  self,
23
23
  *cmd: str,
24
24
  input: ta.Any = None, # noqa
25
- timeout: ta.Optional[TimeoutLike] = None,
25
+ timeout: TimeoutLike = None,
26
26
  check: bool = False,
27
27
  capture_output: ta.Optional[bool] = None,
28
28
  **kwargs: ta.Any,
@@ -31,7 +31,7 @@ class SubprocessRunOutput(ta.Generic[T]):
31
31
  class SubprocessRun:
32
32
  cmd: ta.Sequence[str]
33
33
  input: ta.Any = None
34
- timeout: ta.Optional[TimeoutLike] = None
34
+ timeout: TimeoutLike = None
35
35
  check: bool = False
36
36
  capture_output: ta.Optional[bool] = None
37
37
  kwargs: ta.Optional[ta.Mapping[str, ta.Any]] = None
@@ -67,7 +67,7 @@ class SubprocessRun:
67
67
  cls,
68
68
  *cmd: str,
69
69
  input: ta.Any = None, # noqa
70
- timeout: ta.Optional[TimeoutLike] = None,
70
+ timeout: TimeoutLike = None,
71
71
  check: bool = False, # noqa
72
72
  capture_output: ta.Optional[bool] = None,
73
73
  **kwargs: ta.Any,
@@ -28,7 +28,7 @@ class AbstractSubprocesses(BaseSubprocesses, abc.ABC):
28
28
  self,
29
29
  *cmd: str,
30
30
  input: ta.Any = None, # noqa
31
- timeout: ta.Optional[TimeoutLike] = None,
31
+ timeout: TimeoutLike = None,
32
32
  check: bool = False,
33
33
  capture_output: ta.Optional[bool] = None,
34
34
  **kwargs: ta.Any,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: omlish
3
- Version: 0.0.0.dev308
3
+ Version: 0.0.0.dev310
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=8uwTWCC1I_m-H13aDRaDT3swnjnC8reB6e7B8azZYSA,3478
2
+ omlish/__about__.py,sha256=ntivrO3CNCin3JSqT6Sg7-V7nFZmB_9KZbxtFU9MJwk,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
@@ -18,11 +18,11 @@ omlish/algorithm/distribute.py,sha256=kO60F7HtMF3j-IxuhJdtsfgIR1Vpf1okQfacb4eNuk
18
18
  omlish/algorithm/toposort.py,sha256=cE-zouEVhX05jwGl86JhxB2qgqw5DfQRqpZFR89j7NY,888
19
19
  omlish/algorithm/unify.py,sha256=xUvisdtU8L9uMWt--_osYksJjVBlwxLOLvtdDmFGDDo,833
20
20
  omlish/antlr/__init__.py,sha256=88bMl_28cfSKslgOkMGYXqALgsHz3KC4LFvAVtzj7k8,89
21
- omlish/antlr/delimit.py,sha256=3Byvh9_Ip8ftM_SeSEmMbnNo1jrxk-xm8HnHDp_nDaI,3466
22
- omlish/antlr/dot.py,sha256=W9cgprtAZH6EjUkzWfSbx2XUUYRYLLxFofGWrUp-368,956
23
- omlish/antlr/errors.py,sha256=foYz2109WReT1C7qZsIrb4zCAkZg4vM_UiDOAPC0AqQ,308
21
+ omlish/antlr/delimit.py,sha256=swvxJcECG2e5I3IK62NNbJ7hpLYABRAZUwd2-G9BLtE,3471
22
+ omlish/antlr/dot.py,sha256=LFVo3YYPoLMHMEEUsQepl9zXL1yukNJbqv6Q9E_04qw,961
23
+ omlish/antlr/errors.py,sha256=4J0WuVKbeFoZEP0wePCmn-e7mI1VMwWoE3wkeQO-4nk,313
24
24
  omlish/antlr/input.py,sha256=baeO279AIxR50pymya0eabtnc2A0bSdA5u7jvIGebzA,2090
25
- omlish/antlr/parsing.py,sha256=kXxeGb5luiwhSyIcXO2mLLME7IJLF6-0XMuS4UcDbcw,1414
25
+ omlish/antlr/parsing.py,sha256=SFywjYFvrIhkqNHsxY7YNgYHSV6vlk98zjH0hN6UVhA,1419
26
26
  omlish/antlr/runtime.py,sha256=wYUiJ0qoj4soHFL6fsq91MnUrDSKUEQVmJScKJibOAc,1975
27
27
  omlish/antlr/utils.py,sha256=hi_RFUl222r2gQsmmm5MYg5_vYa3q8u-KP4CC1ZHndA,912
28
28
  omlish/antlr/_runtime/BufferedTokenStream.py,sha256=1Rnhm62MZCWSuQeRs7lRUbdtdyo7Gyg8r4gAETjv-cE,10793
@@ -108,10 +108,10 @@ omlish/asyncs/anyio/utils.py,sha256=X2Rz1DGrCJ0zkt1O5cHoMRaYKTPndBj6dzLhb09mVtE,
108
108
  omlish/asyncs/asyncio/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
109
109
  omlish/asyncs/asyncio/all.py,sha256=u2JpMEs-0AJ0Vd8yU10HvWD8rfKxdFfMiwBu2oDeuuQ,313
110
110
  omlish/asyncs/asyncio/channels.py,sha256=X3S951YTjTRDguMSQRlfu74mPuWkNd2ZEUWboLY58-M,1079
111
- omlish/asyncs/asyncio/sockets.py,sha256=oZAPeC545MGeSpVj_uQfy-BbzXsXHesjCkJSiuqKmAI,1271
111
+ omlish/asyncs/asyncio/sockets.py,sha256=QdXWswN9p9jOlaXUSYnCQZtwu1_jSQNWBiKPt6bws6o,1258
112
112
  omlish/asyncs/asyncio/streams.py,sha256=J_d1hgX4Mx9SfyW4DjOzh91PqzZmjOtiIB95ytF8Ygw,1009
113
- omlish/asyncs/asyncio/subprocesses.py,sha256=Ob5oiyue-YYpvQktzI54QpGsl8E0xEKFOVcb_atJ_R8,6935
114
- omlish/asyncs/asyncio/timeouts.py,sha256=LwFx93KSrefBobQoK4-yH5B6M-pbd7NdNksNzLBfLgQ,459
113
+ omlish/asyncs/asyncio/subprocesses.py,sha256=Mvy5cXHbY-JB5Yl57G05c2O7aEMAjSe29Ed_J63pvx0,6896
114
+ omlish/asyncs/asyncio/timeouts.py,sha256=c-DhZi0yFXhJ6NtHa4EhB1Vrr1QDVd-7HBRkr96Q2So,446
115
115
  omlish/asyncs/asyncio/utils.py,sha256=mDjYNm1cylUhQ8slWXwdPoXasuWfafjzu78GHt2Mdig,2437
116
116
  omlish/asyncs/bluelet/LICENSE,sha256=VHf3oPQihOHnWyIR8LcXX0dpONa1lgyJnjWC2qVuRR0,559
117
117
  omlish/asyncs/bluelet/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -195,7 +195,7 @@ omlish/configs/processing/names.py,sha256=weHmaTclzgM9lUn3aBtw-kwZ3mc2N-CZlFg3Kd
195
195
  omlish/configs/processing/rewriting.py,sha256=v7PfHtuTn5v_5Y6Au7oMN2Z0nxAMy1iYyO5CXnTvZhs,4226
196
196
  omlish/configs/processing/strings.py,sha256=qFS2oh6z02IaM_q4lTKLdufzkJqAJ6J-Qjrz5S-QJoM,826
197
197
  omlish/daemons/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
198
- omlish/daemons/daemon.py,sha256=3Wkvu8M_EaCKSpKI5UN5OayRXV0oVdF62tBss9_hlr0,3479
198
+ omlish/daemons/daemon.py,sha256=pUwomapIrUwXLnov9jlA5EU1vp4qEYcIiUxKD3SQyVo,3479
199
199
  omlish/daemons/launching.py,sha256=sNOYW939IGI4ZlLQ0bKxzXj6EyeOiwV7Upqhd5XfoHc,3747
200
200
  omlish/daemons/reparent.py,sha256=7uJ9oPGt9Ud7uA8bDl_SHcuqjcsmXa3kkjp9jf29wOw,585
201
201
  omlish/daemons/services.py,sha256=YYp2SMkJ71WgzOcYSXjWHeAyKKxu3j1dfuJvWkl0Dgw,3492
@@ -362,7 +362,7 @@ omlish/formats/json5/_antlr/Json5Visitor.py,sha256=SfHhUMNapeP8g4Dc7SFwRSqeBtUTL
362
362
  omlish/formats/json5/_antlr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
363
363
  omlish/formats/toml/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
364
364
  omlish/formats/toml/codec.py,sha256=5HFGWEPd9IFxPlRMRheX8FEDlRIzLe1moHEOj2_PFKU,342
365
- omlish/formats/toml/parser.py,sha256=c6Hrf6OfVQVtgsYUXL5P5PQQqF-v7r8nkUmprxhV-lI,30536
365
+ omlish/formats/toml/parser.py,sha256=0laC7Br_Colk8QxgmuU_pPg6fhcAQ2rMB2saSlLm9S0,30637
366
366
  omlish/formats/toml/writer.py,sha256=HIp6XvriXaPTLqyLe-fkIiEf1Pyhsp0TcOg5rFBpO3g,3226
367
367
  omlish/funcs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
368
368
  omlish/funcs/genmachine.py,sha256=8K5fNvFwxctZcVyulOqPLhZ_6Nwh8RAN6yawiE4wFio,2606
@@ -529,7 +529,7 @@ omlish/lite/resources.py,sha256=YNSmX1Ohck1aoWRs55a-o5ChVbFJIQhtbqE-XwF55Oc,326
529
529
  omlish/lite/runtime.py,sha256=XQo408zxTdJdppUZqOWHyeUR50VlCpNIExNGHz4U6O4,459
530
530
  omlish/lite/secrets.py,sha256=3Mz3V2jf__XU9qNHcH56sBSw95L3U2UPL24bjvobG0c,816
531
531
  omlish/lite/strings.py,sha256=QGxT1Yh4oI8ycsfeobxnjEhvDob_GiAKLeIhZwo1j24,1986
532
- omlish/lite/timeouts.py,sha256=lhXo0zwpLM7nr2-AliBRui2BO9jh7B8ALxetwOq6hYI,4968
532
+ omlish/lite/timeouts.py,sha256=NX7gfW4FLYBcewMh4Dg_XlWqJkLY1Fom3z_OLSzuK7M,4969
533
533
  omlish/lite/timing.py,sha256=aVu3hEDB_jyTF_ryZI7iU-xg4q8CNwqpp9Apfru_iwY,196
534
534
  omlish/lite/types.py,sha256=fP5EMyBdEp2LmDxcHjUDtwAMdR06ISr9lKOL7smWfHM,140
535
535
  omlish/lite/typing.py,sha256=U3-JaEnkDSYxK4tsu_MzUn3RP6qALBe5FXQXpD-licE,1090
@@ -627,7 +627,7 @@ omlish/os/pidfiles/__main__.py,sha256=AF8TwjK4xgHVnoLAP9dIWgKvT0vGhHJlfDW0tKZ7tx
627
627
  omlish/os/pidfiles/cli.py,sha256=2SSsP4O3VdpsDIMAkWgWSjh_YNIPzCD9l5LNN2qrIjo,2074
628
628
  omlish/os/pidfiles/manager.py,sha256=QphQxIENVVwvBWynLCNU31NwOfLkV43VoTVeYFn2Hac,2351
629
629
  omlish/os/pidfiles/pidfile.py,sha256=9tI5IMVwfPfnni0XMn4x5ptNQgm36n8tLeUNPf50UqU,4394
630
- omlish/os/pidfiles/pinning.py,sha256=v9RlJ4BnJZcaZZXiiRqbmzLluaSOkeeEb_WrbKEClBQ,6643
630
+ omlish/os/pidfiles/pinning.py,sha256=aQgCmvcAqN0lvI70GcSB2TKVX1G4vwbyN_AOHF3-eKE,6630
631
631
  omlish/reflect/__init__.py,sha256=64eHbD6zL6Fhp7FfXb8n9ZHywlODjBN3rm1LMvZ081A,822
632
632
  omlish/reflect/inspect.py,sha256=WCo2YpBYauKw6k758FLlZ_H4Q05rgVPs96fEv9w6zHQ,1538
633
633
  omlish/reflect/ops.py,sha256=RJ6jzrM4ieFsXzWyNXWV43O_WgzEaUvlHSc5N2ezW2A,2044
@@ -649,8 +649,8 @@ omlish/sockets/addresses.py,sha256=vbVeQBkzI513H4vRv-JS89QtRbr9U8v5zqkm3oODl_s,1
649
649
  omlish/sockets/bind.py,sha256=J1SfFFFnVf3H5nqESDX2NGEY8DmjyIMUXZciZM33zQY,8003
650
650
  omlish/sockets/handlers.py,sha256=Gj6xZoo4vommge8XvkehYw3B7O4aql2P4qzZIIa0p24,462
651
651
  omlish/sockets/io.py,sha256=lfhTkB7NnAIx9kuQhAkwgsEUXY78Mp1_WtYrIQNS_k8,1408
652
- omlish/sockets/ports.py,sha256=Wm4mRFFz5MdD8KbdaEfT1c4PbJnsuK_iyJlZJE_-8jo,1402
653
- omlish/sockets/wait.py,sha256=aznyOzGa9oNBc31xnyk1S7TylO8hGx7vFyOVsdY3zFE,1585
652
+ omlish/sockets/ports.py,sha256=NQYVvd8IBbQkPl8TnBtupTiv-Htqhc6QBIXJJ6GprnQ,1389
653
+ omlish/sockets/wait.py,sha256=OtLbcoLYzksl4GU0TNbQpzzVWGxp2iRLgo2cGZZfFFM,1559
654
654
  omlish/sockets/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
655
655
  omlish/sockets/server/handlers.py,sha256=PPsb1X5oU9dN8jfztaMGsRiqWTyEANT-1aSLbS6bUVg,3867
656
656
  omlish/sockets/server/server.py,sha256=FkaishIxJuU4it9tTI7wzlGqJYzFGXzDrd_HgV0jAmU,6253
@@ -689,7 +689,7 @@ omlish/specs/jmespath/parser.py,sha256=yfkydotVR4LBhrUTsptL_kLYDoGZrRN9zSEs_76kv
689
689
  omlish/specs/jmespath/scope.py,sha256=UyDsl9rv_c8DCjJBuVIA2ESu1jrgYvuwEKiaJDQKnT0,1590
690
690
  omlish/specs/jmespath/visitor.py,sha256=HVro_6aBGL0CMBy8NRy6vJzWgwsHGB1qJXldX8H7wSg,16592
691
691
  omlish/specs/jsonrpc/__init__.py,sha256=ugIdqHXWZjSy1R1SkwoxstO2GCHEF4W95Ogl3_5_DV4,544
692
- omlish/specs/jsonrpc/conns.py,sha256=Js7DnC48mdnO56-A3wIsgc5ri8CbpAC53USD43eTQSw,6453
692
+ omlish/specs/jsonrpc/conns.py,sha256=zvWnBHuSoGnvbGVk72Usp4IFsLscrzPozqR2hmFjnDI,7029
693
693
  omlish/specs/jsonrpc/errors.py,sha256=-Zgmlo6bV6J8w5f8h9axQgLquIFBHDgIwcpufEH5NsE,707
694
694
  omlish/specs/jsonrpc/marshal.py,sha256=HM736piPGnBZrg8CMLDX-L5fZpegyF6l6JUjzLoSDtk,1852
695
695
  omlish/specs/jsonrpc/types.py,sha256=Se9ecG-_k-kY_Qlt9QD2t3y26oY4sXTcskp6XZfVans,3054
@@ -787,11 +787,11 @@ omlish/sql/tabledefs/lower.py,sha256=YQf8gl1kxD5Fm-vOxV6G0Feh_D9PP1pYwz_vz6XjTPQ
787
787
  omlish/sql/tabledefs/marshal.py,sha256=x8XG0fJLQ6hlwyu957xqnUhr71ouKiRGBWVueZUEMZU,470
788
788
  omlish/sql/tabledefs/tabledefs.py,sha256=lIhvlt0pk6G7RZAtDFsFXm5j0l9BvRfnP7vNGeydHtE,816
789
789
  omlish/subprocesses/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
790
- omlish/subprocesses/async_.py,sha256=hPQTWFa3k5CE_s9p1JTY4KdTPOsqLJtq3lGMRznrVpY,2373
790
+ omlish/subprocesses/async_.py,sha256=st7452hRImm6dCwD-Cf293VPeB50xxc8sk_EoRNe_fY,2360
791
791
  omlish/subprocesses/base.py,sha256=W6El-PUKKF9KLAks5LB6kzqs_n3FfkblJ-JOv6NFQbY,6133
792
792
  omlish/subprocesses/editor.py,sha256=tVU1EQsEhCM242HheylQvEsqaAZYnT61kMhlzZcdk5U,2628
793
- omlish/subprocesses/run.py,sha256=3jwSnQJvFMDMHmJvtAkrrK5D-i7_8cw12vX84EWTuJo,3668
794
- omlish/subprocesses/sync.py,sha256=HKmKM99_Y7tkJRg_n5onXrw41IZt5M5fqU0281LY-mo,3671
793
+ omlish/subprocesses/run.py,sha256=ViFvLJYQHAExk0novi8wCx4xk7T4WPH6CTT3P55B6-4,3642
794
+ omlish/subprocesses/sync.py,sha256=Lmr6LYQrH37wVnlYRQc-fk4iENn2zFGxJmiU8-biUEQ,3658
795
795
  omlish/subprocesses/utils.py,sha256=MJb6hvKhZceTmBeFVqlc5oM7rDxWkUzSzK9nKvbIvM8,396
796
796
  omlish/subprocesses/wrap.py,sha256=HMvCZrO2H227oGNN03KjB3FI-M5bAICqp19W8oG2f5M,763
797
797
  omlish/term/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -853,9 +853,9 @@ omlish/typedvalues/holder.py,sha256=ZTnHiw-K38ciOBLEdwgrltr7Xp8jjEs_0Lp69DH-G-o,
853
853
  omlish/typedvalues/marshal.py,sha256=hWHRLcrGav7lvXJDtb9bNI0ickl4SKPQ6F4BbTpqw3A,4219
854
854
  omlish/typedvalues/reflect.py,sha256=Ih1YgU-srUjsvBn_P7C66f73_VCvcwqE3ffeBnZBgt4,674
855
855
  omlish/typedvalues/values.py,sha256=ym46I-q2QJ_6l4UlERqv3yj87R-kp8nCKMRph0xQ3UA,1307
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,,
856
+ omlish-0.0.0.dev310.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
857
+ omlish-0.0.0.dev310.dist-info/METADATA,sha256=nL2AYcp2yZlXdDGZI7kx77NdLRrDcwPh868SLgJaUeY,4416
858
+ omlish-0.0.0.dev310.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
859
+ omlish-0.0.0.dev310.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
860
+ omlish-0.0.0.dev310.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
861
+ omlish-0.0.0.dev310.dist-info/RECORD,,