ominfra 0.0.0.dev309__py3-none-any.whl → 0.0.0.dev311__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.
@@ -285,29 +285,37 @@ class TomlFlags:
285
285
  def set(self, key: TomlKey, flag: int, *, recursive: bool) -> None: # noqa: A003
286
286
  cont = self._flags
287
287
  key_parent, key_stem = key[:-1], key[-1]
288
+
288
289
  for k in key_parent:
289
290
  if k not in cont:
290
291
  cont[k] = {'flags': set(), 'recursive_flags': set(), 'nested': {}}
291
292
  cont = cont[k]['nested']
293
+
292
294
  if key_stem not in cont:
293
295
  cont[key_stem] = {'flags': set(), 'recursive_flags': set(), 'nested': {}}
296
+
294
297
  cont[key_stem]['recursive_flags' if recursive else 'flags'].add(flag)
295
298
 
296
299
  def is_(self, key: TomlKey, flag: int) -> bool:
297
300
  if not key:
298
301
  return False # document root has no flags
302
+
299
303
  cont = self._flags
300
304
  for k in key[:-1]:
301
305
  if k not in cont:
302
306
  return False
307
+
303
308
  inner_cont = cont[k]
304
309
  if flag in inner_cont['recursive_flags']:
305
310
  return True
311
+
306
312
  cont = inner_cont['nested']
313
+
307
314
  key_stem = key[-1]
308
315
  if key_stem in cont:
309
316
  cont = cont[key_stem]
310
317
  return flag in cont['flags'] or flag in cont['recursive_flags']
318
+
311
319
  return False
312
320
 
313
321
 
@@ -325,24 +333,31 @@ class TomlNestedDict:
325
333
  access_lists: bool = True,
326
334
  ) -> dict:
327
335
  cont: ta.Any = self.dict
336
+
328
337
  for k in key:
329
338
  if k not in cont:
330
339
  cont[k] = {}
340
+
331
341
  cont = cont[k]
342
+
332
343
  if access_lists and isinstance(cont, list):
333
344
  cont = cont[-1]
345
+
334
346
  if not isinstance(cont, dict):
335
347
  raise KeyError('There is no nest behind this key')
348
+
336
349
  return cont
337
350
 
338
351
  def append_nest_to_list(self, key: TomlKey) -> None:
339
352
  cont = self.get_or_create_nest(key[:-1])
353
+
340
354
  last_key = key[-1]
341
355
  if last_key in cont:
342
356
  list_ = cont[last_key]
343
357
  if not isinstance(list_, list):
344
358
  raise KeyError('An object other than list found behind this key')
345
359
  list_.append({})
360
+
346
361
  else:
347
362
  cont[last_key] = [{}]
348
363
 
@@ -412,23 +427,30 @@ class TomlParser:
412
427
  char = self.src[self.pos]
413
428
  except IndexError:
414
429
  break
430
+
415
431
  if char == '\n':
416
432
  self.pos += 1
417
433
  continue
434
+
418
435
  if char in self.KEY_INITIAL_CHARS:
419
436
  self.key_value_rule(header)
420
437
  self.skip_chars(self.WS)
438
+
421
439
  elif char == '[':
422
440
  try:
423
441
  second_char: ta.Optional[str] = self.src[self.pos + 1]
424
442
  except IndexError:
425
443
  second_char = None
444
+
426
445
  self.flags.finalize_pending()
446
+
427
447
  if second_char == '[':
428
448
  header = self.create_list_rule()
429
449
  else:
430
450
  header = self.create_dict_rule()
451
+
431
452
  self.skip_chars(self.WS)
453
+
432
454
  elif char != '#':
433
455
  raise self.suffixed_err('Invalid statement')
434
456
 
@@ -440,8 +462,10 @@ class TomlParser:
440
462
  char = self.src[self.pos]
441
463
  except IndexError:
442
464
  break
465
+
443
466
  if char != '\n':
444
467
  raise self.suffixed_err('Expected newline or end of document after a statement')
468
+
445
469
  self.pos += 1
446
470
 
447
471
  return self.data.dict
@@ -470,7 +494,9 @@ class TomlParser:
470
494
  if not error_on.isdisjoint(self.src[self.pos:new_pos]):
471
495
  while self.src[self.pos] not in error_on:
472
496
  self.pos += 1
497
+
473
498
  raise self.suffixed_err(f'Found invalid character {self.src[self.pos]!r}')
499
+
474
500
  self.pos = new_pos
475
501
 
476
502
  def skip_comment(self) -> None:
@@ -478,6 +504,7 @@ class TomlParser:
478
504
  char: ta.Optional[str] = self.src[self.pos]
479
505
  except IndexError:
480
506
  char = None
507
+
481
508
  if char == '#':
482
509
  self.pos += 1
483
510
  self.skip_until(
@@ -501,7 +528,9 @@ class TomlParser:
501
528
 
502
529
  if self.flags.is_(key, TomlFlags.EXPLICIT_NEST) or self.flags.is_(key, TomlFlags.FROZEN):
503
530
  raise self.suffixed_err(f'Cannot declare {key} twice')
531
+
504
532
  self.flags.set(key, TomlFlags.EXPLICIT_NEST, recursive=False)
533
+
505
534
  try:
506
535
  self.data.get_or_create_nest(key)
507
536
  except KeyError:
@@ -509,20 +538,25 @@ class TomlParser:
509
538
 
510
539
  if not self.src.startswith(']', self.pos):
511
540
  raise self.suffixed_err("Expected ']' at the end of a table declaration")
541
+
512
542
  self.pos += 1
513
543
  return key
514
544
 
515
545
  def create_list_rule(self) -> TomlKey:
516
546
  self.pos += 2 # Skip "[["
517
547
  self.skip_chars(self.WS)
548
+
518
549
  key = self.parse_key()
519
550
 
520
551
  if self.flags.is_(key, TomlFlags.FROZEN):
521
552
  raise self.suffixed_err(f'Cannot mutate immutable namespace {key}')
553
+
522
554
  # Free the namespace now that it points to another empty list item...
523
555
  self.flags.unset_all(key)
556
+
524
557
  # ...but this key precisely is still prohibited from table declaration
525
558
  self.flags.set(key, TomlFlags.EXPLICIT_NEST, recursive=False)
559
+
526
560
  try:
527
561
  self.data.append_nest_to_list(key)
528
562
  except KeyError:
@@ -530,6 +564,7 @@ class TomlParser:
530
564
 
531
565
  if not self.src.startswith(']]', self.pos):
532
566
  raise self.suffixed_err("Expected ']]' at the end of an array declaration")
567
+
533
568
  self.pos += 2
534
569
  return key
535
570
 
@@ -543,6 +578,7 @@ class TomlParser:
543
578
  # Check that dotted key syntax does not redefine an existing table
544
579
  if self.flags.is_(cont_key, TomlFlags.EXPLICIT_NEST):
545
580
  raise self.suffixed_err(f'Cannot redefine namespace {cont_key}')
581
+
546
582
  # Containers in the relative path can't be opened with the table syntax or dotted key/value syntax in
547
583
  # following table sections.
548
584
  self.flags.add_pending(cont_key, TomlFlags.EXPLICIT_NEST)
@@ -554,41 +590,54 @@ class TomlParser:
554
590
  nest = self.data.get_or_create_nest(abs_key_parent)
555
591
  except KeyError:
556
592
  raise self.suffixed_err('Cannot overwrite a value') from None
593
+
557
594
  if key_stem in nest:
558
595
  raise self.suffixed_err('Cannot overwrite a value')
596
+
559
597
  # Mark inline table and array namespaces recursively immutable
560
598
  if isinstance(value, (dict, list)):
561
599
  self.flags.set(header + key, TomlFlags.FROZEN, recursive=True)
600
+
562
601
  nest[key_stem] = value
563
602
 
564
603
  def parse_key_value_pair(self) -> ta.Tuple[TomlKey, ta.Any]:
565
604
  key = self.parse_key()
605
+
566
606
  try:
567
607
  char: ta.Optional[str] = self.src[self.pos]
568
608
  except IndexError:
569
609
  char = None
610
+
570
611
  if char != '=':
571
612
  raise self.suffixed_err("Expected '=' after a key in a key/value pair")
613
+
572
614
  self.pos += 1
573
615
  self.skip_chars(self.WS)
616
+
574
617
  value = self.parse_value()
575
618
  return key, value
576
619
 
577
620
  def parse_key(self) -> TomlKey:
578
621
  key_part = self.parse_key_part()
579
622
  key: TomlKey = (key_part,)
623
+
580
624
  self.skip_chars(self.WS)
625
+
581
626
  while True:
582
627
  try:
583
628
  char: ta.Optional[str] = self.src[self.pos]
584
629
  except IndexError:
585
630
  char = None
631
+
586
632
  if char != '.':
587
633
  return key
634
+
588
635
  self.pos += 1
589
636
  self.skip_chars(self.WS)
637
+
590
638
  key_part = self.parse_key_part()
591
639
  key += (key_part,)
640
+
592
641
  self.skip_chars(self.WS)
593
642
 
594
643
  def parse_key_part(self) -> str:
@@ -596,14 +645,18 @@ class TomlParser:
596
645
  char: ta.Optional[str] = self.src[self.pos]
597
646
  except IndexError:
598
647
  char = None
648
+
599
649
  if char in self.BARE_KEY_CHARS:
600
650
  start_pos = self.pos
601
651
  self.skip_chars(self.BARE_KEY_CHARS)
602
652
  return self.src[start_pos:self.pos]
653
+
603
654
  if char == "'":
604
655
  return self.parse_literal_str()
656
+
605
657
  if char == '"':
606
658
  return self.parse_one_line_basic_str()
659
+
607
660
  raise self.suffixed_err('Invalid initial character for a key part')
608
661
 
609
662
  def parse_one_line_basic_str(self) -> str:
@@ -618,6 +671,7 @@ class TomlParser:
618
671
  if self.src.startswith(']', self.pos):
619
672
  self.pos += 1
620
673
  return array
674
+
621
675
  while True:
622
676
  val = self.parse_value()
623
677
  array.append(val)
@@ -627,11 +681,14 @@ class TomlParser:
627
681
  if c == ']':
628
682
  self.pos += 1
629
683
  return array
684
+
630
685
  if c != ',':
631
686
  raise self.suffixed_err('Unclosed array')
687
+
632
688
  self.pos += 1
633
689
 
634
690
  self.skip_comments_and_array_ws()
691
+
635
692
  if self.src.startswith(']', self.pos):
636
693
  self.pos += 1
637
694
  return array
@@ -642,54 +699,72 @@ class TomlParser:
642
699
  flags = TomlFlags()
643
700
 
644
701
  self.skip_chars(self.WS)
702
+
645
703
  if self.src.startswith('}', self.pos):
646
704
  self.pos += 1
647
705
  return nested_dict.dict
706
+
648
707
  while True:
649
708
  key, value = self.parse_key_value_pair()
650
709
  key_parent, key_stem = key[:-1], key[-1]
710
+
651
711
  if flags.is_(key, TomlFlags.FROZEN):
652
712
  raise self.suffixed_err(f'Cannot mutate immutable namespace {key}')
713
+
653
714
  try:
654
715
  nest = nested_dict.get_or_create_nest(key_parent, access_lists=False)
655
716
  except KeyError:
656
717
  raise self.suffixed_err('Cannot overwrite a value') from None
718
+
657
719
  if key_stem in nest:
658
720
  raise self.suffixed_err(f'Duplicate inline table key {key_stem!r}')
721
+
659
722
  nest[key_stem] = value
660
723
  self.skip_chars(self.WS)
724
+
661
725
  c = self.src[self.pos:self.pos + 1]
662
726
  if c == '}':
663
727
  self.pos += 1
664
728
  return nested_dict.dict
729
+
665
730
  if c != ',':
666
731
  raise self.suffixed_err('Unclosed inline table')
732
+
667
733
  if isinstance(value, (dict, list)):
668
734
  flags.set(key, TomlFlags.FROZEN, recursive=True)
735
+
669
736
  self.pos += 1
670
737
  self.skip_chars(self.WS)
671
738
 
672
739
  def parse_basic_str_escape(self, multiline: bool = False) -> str:
673
740
  escape_id = self.src[self.pos:self.pos + 2]
674
741
  self.pos += 2
742
+
675
743
  if multiline and escape_id in {'\\ ', '\\\t', '\\\n'}:
676
744
  # Skip whitespace until next non-whitespace character or end of the doc. Error if non-whitespace is found
677
745
  # before newline.
678
746
  if escape_id != '\\\n':
679
747
  self.skip_chars(self.WS)
748
+
680
749
  try:
681
750
  char = self.src[self.pos]
682
751
  except IndexError:
683
752
  return ''
753
+
684
754
  if char != '\n':
685
755
  raise self.suffixed_err("Unescaped '\\' in a string")
756
+
686
757
  self.pos += 1
758
+
687
759
  self.skip_chars(self.WS_AND_NEWLINE)
688
760
  return ''
761
+
689
762
  if escape_id == '\\u':
690
763
  return self.parse_hex_char(4)
764
+
691
765
  if escape_id == '\\U':
692
766
  return self.parse_hex_char(8)
767
+
693
768
  try:
694
769
  return self.BASIC_STR_ESCAPE_REPLACEMENTS[escape_id]
695
770
  except KeyError:
@@ -704,12 +779,16 @@ class TomlParser:
704
779
 
705
780
  def parse_hex_char(self, hex_len: int) -> str:
706
781
  hex_str = self.src[self.pos:self.pos + hex_len]
782
+
707
783
  if len(hex_str) != hex_len or not self.HEXDIGIT_CHARS.issuperset(hex_str):
708
784
  raise self.suffixed_err('Invalid hex value')
785
+
709
786
  self.pos += hex_len
710
787
  hex_int = int(hex_str, 16)
788
+
711
789
  if not self.is_unicode_scalar_value(hex_int):
712
790
  raise self.suffixed_err('Escaped character is not a Unicode scalar value')
791
+
713
792
  return chr(hex_int)
714
793
 
715
794
  def parse_literal_str(self) -> str:
@@ -735,6 +814,7 @@ class TomlParser:
735
814
  )
736
815
  result = self.src[start_pos:self.pos]
737
816
  self.pos += 3
817
+
738
818
  else:
739
819
  delim = '"'
740
820
  result = self.parse_basic_str(multiline=True)
@@ -742,9 +822,11 @@ class TomlParser:
742
822
  # Add at maximum two extra apostrophes/quotes if the end sequence is 4 or 5 chars long instead of just 3.
743
823
  if not self.src.startswith(delim, self.pos):
744
824
  return result
825
+
745
826
  self.pos += 1
746
827
  if not self.src.startswith(delim, self.pos):
747
828
  return result + delim
829
+
748
830
  self.pos += 1
749
831
  return result + (delim * 2)
750
832
 
@@ -755,6 +837,7 @@ class TomlParser:
755
837
  else:
756
838
  error_on = self.ILLEGAL_BASIC_STR_CHARS
757
839
  parse_escapes = self.parse_basic_str_escape
840
+
758
841
  result = ''
759
842
  start_pos = self.pos
760
843
  while True:
@@ -762,25 +845,31 @@ class TomlParser:
762
845
  char = self.src[self.pos]
763
846
  except IndexError:
764
847
  raise self.suffixed_err('Unterminated string') from None
848
+
765
849
  if char == '"':
766
850
  if not multiline:
767
851
  end_pos = self.pos
768
852
  self.pos += 1
769
853
  return result + self.src[start_pos:end_pos]
854
+
770
855
  if self.src.startswith('"""', self.pos):
771
856
  end_pos = self.pos
772
857
  self.pos += 3
773
858
  return result + self.src[start_pos:end_pos]
859
+
774
860
  self.pos += 1
775
861
  continue
862
+
776
863
  if char == '\\':
777
864
  result += self.src[start_pos:self.pos]
778
865
  parsed_escape = parse_escapes()
779
866
  result += parsed_escape
780
867
  start_pos = self.pos
781
868
  continue
869
+
782
870
  if char in error_on:
783
871
  raise self.suffixed_err(f'Illegal character {char!r}')
872
+
784
873
  self.pos += 1
785
874
 
786
875
  def parse_value(self) -> ta.Any: # noqa: C901
@@ -808,6 +897,7 @@ class TomlParser:
808
897
  if self.src.startswith('true', self.pos):
809
898
  self.pos += 4
810
899
  return True
900
+
811
901
  if char == 'f':
812
902
  if self.src.startswith('false', self.pos):
813
903
  self.pos += 5
@@ -828,8 +918,10 @@ class TomlParser:
828
918
  datetime_obj = self.match_to_datetime(datetime_match)
829
919
  except ValueError as e:
830
920
  raise self.suffixed_err('Invalid date or datetime') from e
921
+
831
922
  self.pos = datetime_match.end()
832
923
  return datetime_obj
924
+
833
925
  localtime_match = self.RE_LOCALTIME.match(self.src, self.pos)
834
926
  if localtime_match:
835
927
  self.pos = localtime_match.end()
@@ -847,6 +939,7 @@ class TomlParser:
847
939
  if first_three in {'inf', 'nan'}:
848
940
  self.pos += 3
849
941
  return self.parse_float(first_three)
942
+
850
943
  first_four = self.src[self.pos:self.pos + 4]
851
944
  if first_four in {'-inf', '+inf', '-nan', '+nan'}:
852
945
  self.pos += 4
@@ -857,11 +950,13 @@ class TomlParser:
857
950
  def coord_repr(self, pos: TomlPos) -> str:
858
951
  if pos >= len(self.src):
859
952
  return 'end of document'
953
+
860
954
  line = self.src.count('\n', 0, pos) + 1
861
955
  if line == 1:
862
956
  column = pos + 1
863
957
  else:
864
958
  column = pos - self.src.rindex('\n', 0, pos)
959
+
865
960
  return f'line {line}, column {column}'
866
961
 
867
962
  def suffixed_err(self, msg: str, *, pos: ta.Optional[TomlPos] = None) -> TomlDecodeError:
@@ -928,11 +1023,16 @@ class TomlParser:
928
1023
  offset_hour_str,
929
1024
  offset_minute_str,
930
1025
  ) = match.groups()
1026
+
931
1027
  year, month, day = int(year_str), int(month_str), int(day_str)
1028
+
932
1029
  if hour_str is None:
933
1030
  return datetime.date(year, month, day)
1031
+
934
1032
  hour, minute, sec = int(hour_str), int(minute_str), int(sec_str)
1033
+
935
1034
  micros = int(micros_str.ljust(6, '0')) if micros_str else 0
1035
+
936
1036
  if offset_sign_str:
937
1037
  tz: ta.Optional[datetime.tzinfo] = toml_cached_tz(
938
1038
  offset_hour_str, offset_minute_str, offset_sign_str,
@@ -941,6 +1041,7 @@ class TomlParser:
941
1041
  tz = datetime.UTC
942
1042
  else: # local date-time
943
1043
  tz = None
1044
+
944
1045
  return datetime.datetime(year, month, day, hour, minute, sec, micros, tzinfo=tz)
945
1046
 
946
1047
  @classmethod