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.
ominfra/scripts/manage.py CHANGED
@@ -1524,29 +1524,37 @@ class TomlFlags:
1524
1524
  def set(self, key: TomlKey, flag: int, *, recursive: bool) -> None: # noqa: A003
1525
1525
  cont = self._flags
1526
1526
  key_parent, key_stem = key[:-1], key[-1]
1527
+
1527
1528
  for k in key_parent:
1528
1529
  if k not in cont:
1529
1530
  cont[k] = {'flags': set(), 'recursive_flags': set(), 'nested': {}}
1530
1531
  cont = cont[k]['nested']
1532
+
1531
1533
  if key_stem not in cont:
1532
1534
  cont[key_stem] = {'flags': set(), 'recursive_flags': set(), 'nested': {}}
1535
+
1533
1536
  cont[key_stem]['recursive_flags' if recursive else 'flags'].add(flag)
1534
1537
 
1535
1538
  def is_(self, key: TomlKey, flag: int) -> bool:
1536
1539
  if not key:
1537
1540
  return False # document root has no flags
1541
+
1538
1542
  cont = self._flags
1539
1543
  for k in key[:-1]:
1540
1544
  if k not in cont:
1541
1545
  return False
1546
+
1542
1547
  inner_cont = cont[k]
1543
1548
  if flag in inner_cont['recursive_flags']:
1544
1549
  return True
1550
+
1545
1551
  cont = inner_cont['nested']
1552
+
1546
1553
  key_stem = key[-1]
1547
1554
  if key_stem in cont:
1548
1555
  cont = cont[key_stem]
1549
1556
  return flag in cont['flags'] or flag in cont['recursive_flags']
1557
+
1550
1558
  return False
1551
1559
 
1552
1560
 
@@ -1564,24 +1572,31 @@ class TomlNestedDict:
1564
1572
  access_lists: bool = True,
1565
1573
  ) -> dict:
1566
1574
  cont: ta.Any = self.dict
1575
+
1567
1576
  for k in key:
1568
1577
  if k not in cont:
1569
1578
  cont[k] = {}
1579
+
1570
1580
  cont = cont[k]
1581
+
1571
1582
  if access_lists and isinstance(cont, list):
1572
1583
  cont = cont[-1]
1584
+
1573
1585
  if not isinstance(cont, dict):
1574
1586
  raise KeyError('There is no nest behind this key')
1587
+
1575
1588
  return cont
1576
1589
 
1577
1590
  def append_nest_to_list(self, key: TomlKey) -> None:
1578
1591
  cont = self.get_or_create_nest(key[:-1])
1592
+
1579
1593
  last_key = key[-1]
1580
1594
  if last_key in cont:
1581
1595
  list_ = cont[last_key]
1582
1596
  if not isinstance(list_, list):
1583
1597
  raise KeyError('An object other than list found behind this key')
1584
1598
  list_.append({})
1599
+
1585
1600
  else:
1586
1601
  cont[last_key] = [{}]
1587
1602
 
@@ -1651,23 +1666,30 @@ class TomlParser:
1651
1666
  char = self.src[self.pos]
1652
1667
  except IndexError:
1653
1668
  break
1669
+
1654
1670
  if char == '\n':
1655
1671
  self.pos += 1
1656
1672
  continue
1673
+
1657
1674
  if char in self.KEY_INITIAL_CHARS:
1658
1675
  self.key_value_rule(header)
1659
1676
  self.skip_chars(self.WS)
1677
+
1660
1678
  elif char == '[':
1661
1679
  try:
1662
1680
  second_char: ta.Optional[str] = self.src[self.pos + 1]
1663
1681
  except IndexError:
1664
1682
  second_char = None
1683
+
1665
1684
  self.flags.finalize_pending()
1685
+
1666
1686
  if second_char == '[':
1667
1687
  header = self.create_list_rule()
1668
1688
  else:
1669
1689
  header = self.create_dict_rule()
1690
+
1670
1691
  self.skip_chars(self.WS)
1692
+
1671
1693
  elif char != '#':
1672
1694
  raise self.suffixed_err('Invalid statement')
1673
1695
 
@@ -1679,8 +1701,10 @@ class TomlParser:
1679
1701
  char = self.src[self.pos]
1680
1702
  except IndexError:
1681
1703
  break
1704
+
1682
1705
  if char != '\n':
1683
1706
  raise self.suffixed_err('Expected newline or end of document after a statement')
1707
+
1684
1708
  self.pos += 1
1685
1709
 
1686
1710
  return self.data.dict
@@ -1709,7 +1733,9 @@ class TomlParser:
1709
1733
  if not error_on.isdisjoint(self.src[self.pos:new_pos]):
1710
1734
  while self.src[self.pos] not in error_on:
1711
1735
  self.pos += 1
1736
+
1712
1737
  raise self.suffixed_err(f'Found invalid character {self.src[self.pos]!r}')
1738
+
1713
1739
  self.pos = new_pos
1714
1740
 
1715
1741
  def skip_comment(self) -> None:
@@ -1717,6 +1743,7 @@ class TomlParser:
1717
1743
  char: ta.Optional[str] = self.src[self.pos]
1718
1744
  except IndexError:
1719
1745
  char = None
1746
+
1720
1747
  if char == '#':
1721
1748
  self.pos += 1
1722
1749
  self.skip_until(
@@ -1740,7 +1767,9 @@ class TomlParser:
1740
1767
 
1741
1768
  if self.flags.is_(key, TomlFlags.EXPLICIT_NEST) or self.flags.is_(key, TomlFlags.FROZEN):
1742
1769
  raise self.suffixed_err(f'Cannot declare {key} twice')
1770
+
1743
1771
  self.flags.set(key, TomlFlags.EXPLICIT_NEST, recursive=False)
1772
+
1744
1773
  try:
1745
1774
  self.data.get_or_create_nest(key)
1746
1775
  except KeyError:
@@ -1748,20 +1777,25 @@ class TomlParser:
1748
1777
 
1749
1778
  if not self.src.startswith(']', self.pos):
1750
1779
  raise self.suffixed_err("Expected ']' at the end of a table declaration")
1780
+
1751
1781
  self.pos += 1
1752
1782
  return key
1753
1783
 
1754
1784
  def create_list_rule(self) -> TomlKey:
1755
1785
  self.pos += 2 # Skip "[["
1756
1786
  self.skip_chars(self.WS)
1787
+
1757
1788
  key = self.parse_key()
1758
1789
 
1759
1790
  if self.flags.is_(key, TomlFlags.FROZEN):
1760
1791
  raise self.suffixed_err(f'Cannot mutate immutable namespace {key}')
1792
+
1761
1793
  # Free the namespace now that it points to another empty list item...
1762
1794
  self.flags.unset_all(key)
1795
+
1763
1796
  # ...but this key precisely is still prohibited from table declaration
1764
1797
  self.flags.set(key, TomlFlags.EXPLICIT_NEST, recursive=False)
1798
+
1765
1799
  try:
1766
1800
  self.data.append_nest_to_list(key)
1767
1801
  except KeyError:
@@ -1769,6 +1803,7 @@ class TomlParser:
1769
1803
 
1770
1804
  if not self.src.startswith(']]', self.pos):
1771
1805
  raise self.suffixed_err("Expected ']]' at the end of an array declaration")
1806
+
1772
1807
  self.pos += 2
1773
1808
  return key
1774
1809
 
@@ -1782,6 +1817,7 @@ class TomlParser:
1782
1817
  # Check that dotted key syntax does not redefine an existing table
1783
1818
  if self.flags.is_(cont_key, TomlFlags.EXPLICIT_NEST):
1784
1819
  raise self.suffixed_err(f'Cannot redefine namespace {cont_key}')
1820
+
1785
1821
  # Containers in the relative path can't be opened with the table syntax or dotted key/value syntax in
1786
1822
  # following table sections.
1787
1823
  self.flags.add_pending(cont_key, TomlFlags.EXPLICIT_NEST)
@@ -1793,41 +1829,54 @@ class TomlParser:
1793
1829
  nest = self.data.get_or_create_nest(abs_key_parent)
1794
1830
  except KeyError:
1795
1831
  raise self.suffixed_err('Cannot overwrite a value') from None
1832
+
1796
1833
  if key_stem in nest:
1797
1834
  raise self.suffixed_err('Cannot overwrite a value')
1835
+
1798
1836
  # Mark inline table and array namespaces recursively immutable
1799
1837
  if isinstance(value, (dict, list)):
1800
1838
  self.flags.set(header + key, TomlFlags.FROZEN, recursive=True)
1839
+
1801
1840
  nest[key_stem] = value
1802
1841
 
1803
1842
  def parse_key_value_pair(self) -> ta.Tuple[TomlKey, ta.Any]:
1804
1843
  key = self.parse_key()
1844
+
1805
1845
  try:
1806
1846
  char: ta.Optional[str] = self.src[self.pos]
1807
1847
  except IndexError:
1808
1848
  char = None
1849
+
1809
1850
  if char != '=':
1810
1851
  raise self.suffixed_err("Expected '=' after a key in a key/value pair")
1852
+
1811
1853
  self.pos += 1
1812
1854
  self.skip_chars(self.WS)
1855
+
1813
1856
  value = self.parse_value()
1814
1857
  return key, value
1815
1858
 
1816
1859
  def parse_key(self) -> TomlKey:
1817
1860
  key_part = self.parse_key_part()
1818
1861
  key: TomlKey = (key_part,)
1862
+
1819
1863
  self.skip_chars(self.WS)
1864
+
1820
1865
  while True:
1821
1866
  try:
1822
1867
  char: ta.Optional[str] = self.src[self.pos]
1823
1868
  except IndexError:
1824
1869
  char = None
1870
+
1825
1871
  if char != '.':
1826
1872
  return key
1873
+
1827
1874
  self.pos += 1
1828
1875
  self.skip_chars(self.WS)
1876
+
1829
1877
  key_part = self.parse_key_part()
1830
1878
  key += (key_part,)
1879
+
1831
1880
  self.skip_chars(self.WS)
1832
1881
 
1833
1882
  def parse_key_part(self) -> str:
@@ -1835,14 +1884,18 @@ class TomlParser:
1835
1884
  char: ta.Optional[str] = self.src[self.pos]
1836
1885
  except IndexError:
1837
1886
  char = None
1887
+
1838
1888
  if char in self.BARE_KEY_CHARS:
1839
1889
  start_pos = self.pos
1840
1890
  self.skip_chars(self.BARE_KEY_CHARS)
1841
1891
  return self.src[start_pos:self.pos]
1892
+
1842
1893
  if char == "'":
1843
1894
  return self.parse_literal_str()
1895
+
1844
1896
  if char == '"':
1845
1897
  return self.parse_one_line_basic_str()
1898
+
1846
1899
  raise self.suffixed_err('Invalid initial character for a key part')
1847
1900
 
1848
1901
  def parse_one_line_basic_str(self) -> str:
@@ -1857,6 +1910,7 @@ class TomlParser:
1857
1910
  if self.src.startswith(']', self.pos):
1858
1911
  self.pos += 1
1859
1912
  return array
1913
+
1860
1914
  while True:
1861
1915
  val = self.parse_value()
1862
1916
  array.append(val)
@@ -1866,11 +1920,14 @@ class TomlParser:
1866
1920
  if c == ']':
1867
1921
  self.pos += 1
1868
1922
  return array
1923
+
1869
1924
  if c != ',':
1870
1925
  raise self.suffixed_err('Unclosed array')
1926
+
1871
1927
  self.pos += 1
1872
1928
 
1873
1929
  self.skip_comments_and_array_ws()
1930
+
1874
1931
  if self.src.startswith(']', self.pos):
1875
1932
  self.pos += 1
1876
1933
  return array
@@ -1881,54 +1938,72 @@ class TomlParser:
1881
1938
  flags = TomlFlags()
1882
1939
 
1883
1940
  self.skip_chars(self.WS)
1941
+
1884
1942
  if self.src.startswith('}', self.pos):
1885
1943
  self.pos += 1
1886
1944
  return nested_dict.dict
1945
+
1887
1946
  while True:
1888
1947
  key, value = self.parse_key_value_pair()
1889
1948
  key_parent, key_stem = key[:-1], key[-1]
1949
+
1890
1950
  if flags.is_(key, TomlFlags.FROZEN):
1891
1951
  raise self.suffixed_err(f'Cannot mutate immutable namespace {key}')
1952
+
1892
1953
  try:
1893
1954
  nest = nested_dict.get_or_create_nest(key_parent, access_lists=False)
1894
1955
  except KeyError:
1895
1956
  raise self.suffixed_err('Cannot overwrite a value') from None
1957
+
1896
1958
  if key_stem in nest:
1897
1959
  raise self.suffixed_err(f'Duplicate inline table key {key_stem!r}')
1960
+
1898
1961
  nest[key_stem] = value
1899
1962
  self.skip_chars(self.WS)
1963
+
1900
1964
  c = self.src[self.pos:self.pos + 1]
1901
1965
  if c == '}':
1902
1966
  self.pos += 1
1903
1967
  return nested_dict.dict
1968
+
1904
1969
  if c != ',':
1905
1970
  raise self.suffixed_err('Unclosed inline table')
1971
+
1906
1972
  if isinstance(value, (dict, list)):
1907
1973
  flags.set(key, TomlFlags.FROZEN, recursive=True)
1974
+
1908
1975
  self.pos += 1
1909
1976
  self.skip_chars(self.WS)
1910
1977
 
1911
1978
  def parse_basic_str_escape(self, multiline: bool = False) -> str:
1912
1979
  escape_id = self.src[self.pos:self.pos + 2]
1913
1980
  self.pos += 2
1981
+
1914
1982
  if multiline and escape_id in {'\\ ', '\\\t', '\\\n'}:
1915
1983
  # Skip whitespace until next non-whitespace character or end of the doc. Error if non-whitespace is found
1916
1984
  # before newline.
1917
1985
  if escape_id != '\\\n':
1918
1986
  self.skip_chars(self.WS)
1987
+
1919
1988
  try:
1920
1989
  char = self.src[self.pos]
1921
1990
  except IndexError:
1922
1991
  return ''
1992
+
1923
1993
  if char != '\n':
1924
1994
  raise self.suffixed_err("Unescaped '\\' in a string")
1995
+
1925
1996
  self.pos += 1
1997
+
1926
1998
  self.skip_chars(self.WS_AND_NEWLINE)
1927
1999
  return ''
2000
+
1928
2001
  if escape_id == '\\u':
1929
2002
  return self.parse_hex_char(4)
2003
+
1930
2004
  if escape_id == '\\U':
1931
2005
  return self.parse_hex_char(8)
2006
+
1932
2007
  try:
1933
2008
  return self.BASIC_STR_ESCAPE_REPLACEMENTS[escape_id]
1934
2009
  except KeyError:
@@ -1943,12 +2018,16 @@ class TomlParser:
1943
2018
 
1944
2019
  def parse_hex_char(self, hex_len: int) -> str:
1945
2020
  hex_str = self.src[self.pos:self.pos + hex_len]
2021
+
1946
2022
  if len(hex_str) != hex_len or not self.HEXDIGIT_CHARS.issuperset(hex_str):
1947
2023
  raise self.suffixed_err('Invalid hex value')
2024
+
1948
2025
  self.pos += hex_len
1949
2026
  hex_int = int(hex_str, 16)
2027
+
1950
2028
  if not self.is_unicode_scalar_value(hex_int):
1951
2029
  raise self.suffixed_err('Escaped character is not a Unicode scalar value')
2030
+
1952
2031
  return chr(hex_int)
1953
2032
 
1954
2033
  def parse_literal_str(self) -> str:
@@ -1974,6 +2053,7 @@ class TomlParser:
1974
2053
  )
1975
2054
  result = self.src[start_pos:self.pos]
1976
2055
  self.pos += 3
2056
+
1977
2057
  else:
1978
2058
  delim = '"'
1979
2059
  result = self.parse_basic_str(multiline=True)
@@ -1981,9 +2061,11 @@ class TomlParser:
1981
2061
  # Add at maximum two extra apostrophes/quotes if the end sequence is 4 or 5 chars long instead of just 3.
1982
2062
  if not self.src.startswith(delim, self.pos):
1983
2063
  return result
2064
+
1984
2065
  self.pos += 1
1985
2066
  if not self.src.startswith(delim, self.pos):
1986
2067
  return result + delim
2068
+
1987
2069
  self.pos += 1
1988
2070
  return result + (delim * 2)
1989
2071
 
@@ -1994,6 +2076,7 @@ class TomlParser:
1994
2076
  else:
1995
2077
  error_on = self.ILLEGAL_BASIC_STR_CHARS
1996
2078
  parse_escapes = self.parse_basic_str_escape
2079
+
1997
2080
  result = ''
1998
2081
  start_pos = self.pos
1999
2082
  while True:
@@ -2001,25 +2084,31 @@ class TomlParser:
2001
2084
  char = self.src[self.pos]
2002
2085
  except IndexError:
2003
2086
  raise self.suffixed_err('Unterminated string') from None
2087
+
2004
2088
  if char == '"':
2005
2089
  if not multiline:
2006
2090
  end_pos = self.pos
2007
2091
  self.pos += 1
2008
2092
  return result + self.src[start_pos:end_pos]
2093
+
2009
2094
  if self.src.startswith('"""', self.pos):
2010
2095
  end_pos = self.pos
2011
2096
  self.pos += 3
2012
2097
  return result + self.src[start_pos:end_pos]
2098
+
2013
2099
  self.pos += 1
2014
2100
  continue
2101
+
2015
2102
  if char == '\\':
2016
2103
  result += self.src[start_pos:self.pos]
2017
2104
  parsed_escape = parse_escapes()
2018
2105
  result += parsed_escape
2019
2106
  start_pos = self.pos
2020
2107
  continue
2108
+
2021
2109
  if char in error_on:
2022
2110
  raise self.suffixed_err(f'Illegal character {char!r}')
2111
+
2023
2112
  self.pos += 1
2024
2113
 
2025
2114
  def parse_value(self) -> ta.Any: # noqa: C901
@@ -2047,6 +2136,7 @@ class TomlParser:
2047
2136
  if self.src.startswith('true', self.pos):
2048
2137
  self.pos += 4
2049
2138
  return True
2139
+
2050
2140
  if char == 'f':
2051
2141
  if self.src.startswith('false', self.pos):
2052
2142
  self.pos += 5
@@ -2067,8 +2157,10 @@ class TomlParser:
2067
2157
  datetime_obj = self.match_to_datetime(datetime_match)
2068
2158
  except ValueError as e:
2069
2159
  raise self.suffixed_err('Invalid date or datetime') from e
2160
+
2070
2161
  self.pos = datetime_match.end()
2071
2162
  return datetime_obj
2163
+
2072
2164
  localtime_match = self.RE_LOCALTIME.match(self.src, self.pos)
2073
2165
  if localtime_match:
2074
2166
  self.pos = localtime_match.end()
@@ -2086,6 +2178,7 @@ class TomlParser:
2086
2178
  if first_three in {'inf', 'nan'}:
2087
2179
  self.pos += 3
2088
2180
  return self.parse_float(first_three)
2181
+
2089
2182
  first_four = self.src[self.pos:self.pos + 4]
2090
2183
  if first_four in {'-inf', '+inf', '-nan', '+nan'}:
2091
2184
  self.pos += 4
@@ -2096,11 +2189,13 @@ class TomlParser:
2096
2189
  def coord_repr(self, pos: TomlPos) -> str:
2097
2190
  if pos >= len(self.src):
2098
2191
  return 'end of document'
2192
+
2099
2193
  line = self.src.count('\n', 0, pos) + 1
2100
2194
  if line == 1:
2101
2195
  column = pos + 1
2102
2196
  else:
2103
2197
  column = pos - self.src.rindex('\n', 0, pos)
2198
+
2104
2199
  return f'line {line}, column {column}'
2105
2200
 
2106
2201
  def suffixed_err(self, msg: str, *, pos: ta.Optional[TomlPos] = None) -> TomlDecodeError:
@@ -2167,11 +2262,16 @@ class TomlParser:
2167
2262
  offset_hour_str,
2168
2263
  offset_minute_str,
2169
2264
  ) = match.groups()
2265
+
2170
2266
  year, month, day = int(year_str), int(month_str), int(day_str)
2267
+
2171
2268
  if hour_str is None:
2172
2269
  return datetime.date(year, month, day)
2270
+
2173
2271
  hour, minute, sec = int(hour_str), int(minute_str), int(sec_str)
2272
+
2174
2273
  micros = int(micros_str.ljust(6, '0')) if micros_str else 0
2274
+
2175
2275
  if offset_sign_str:
2176
2276
  tz: ta.Optional[datetime.tzinfo] = toml_cached_tz(
2177
2277
  offset_hour_str, offset_minute_str, offset_sign_str,
@@ -2180,6 +2280,7 @@ class TomlParser:
2180
2280
  tz = datetime.UTC
2181
2281
  else: # local date-time
2182
2282
  tz = None
2283
+
2183
2284
  return datetime.datetime(year, month, day, hour, minute, sec, micros, tzinfo=tz)
2184
2285
 
2185
2286
  @classmethod