ominfra 0.0.0.dev148__py3-none-any.whl → 0.0.0.dev150__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. ominfra/clouds/aws/auth.py +7 -9
  2. ominfra/clouds/aws/cli.py +1 -1
  3. ominfra/clouds/aws/journald2aws/driver.py +4 -4
  4. ominfra/clouds/aws/logs.py +4 -5
  5. ominfra/clouds/gcp/auth.py +1 -1
  6. ominfra/configs.py +3 -4
  7. ominfra/journald/messages.py +3 -3
  8. ominfra/journald/tailer.py +2 -2
  9. ominfra/manage/commands/base.py +2 -2
  10. ominfra/manage/commands/interp.py +3 -3
  11. ominfra/manage/commands/subprocess.py +3 -4
  12. ominfra/manage/deploy/paths.py +12 -15
  13. ominfra/manage/main.py +72 -75
  14. ominfra/manage/remote/_main.py +6 -7
  15. ominfra/manage/remote/execution.py +7 -10
  16. ominfra/manage/remote/spawning.py +3 -3
  17. ominfra/scripts/journald2aws.py +508 -147
  18. ominfra/scripts/manage.py +772 -183
  19. ominfra/scripts/supervisor.py +1144 -783
  20. ominfra/supervisor/dispatchers.py +1 -1
  21. ominfra/supervisor/groupsimpl.py +2 -2
  22. ominfra/supervisor/http.py +7 -7
  23. ominfra/supervisor/inject.py +4 -4
  24. ominfra/supervisor/io.py +1 -1
  25. ominfra/supervisor/main.py +1 -1
  26. ominfra/supervisor/processimpl.py +2 -2
  27. ominfra/supervisor/spawningimpl.py +9 -10
  28. ominfra/supervisor/supervisor.py +3 -3
  29. ominfra/supervisor/types.py +1 -1
  30. ominfra/tailscale/cli.py +1 -1
  31. {ominfra-0.0.0.dev148.dist-info → ominfra-0.0.0.dev150.dist-info}/METADATA +3 -3
  32. {ominfra-0.0.0.dev148.dist-info → ominfra-0.0.0.dev150.dist-info}/RECORD +36 -36
  33. {ominfra-0.0.0.dev148.dist-info → ominfra-0.0.0.dev150.dist-info}/LICENSE +0 -0
  34. {ominfra-0.0.0.dev148.dist-info → ominfra-0.0.0.dev150.dist-info}/WHEEL +0 -0
  35. {ominfra-0.0.0.dev148.dist-info → ominfra-0.0.0.dev150.dist-info}/entry_points.txt +0 -0
  36. {ominfra-0.0.0.dev148.dist-info → ominfra-0.0.0.dev150.dist-info}/top_level.txt +0 -0
@@ -34,6 +34,7 @@
34
34
  # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
35
  import abc
36
36
  import base64
37
+ import collections
37
38
  import collections.abc
38
39
  import contextlib
39
40
  import ctypes as ct
@@ -105,6 +106,11 @@ CallableT = ta.TypeVar('CallableT', bound=ta.Callable)
105
106
 
106
107
  # ../../omlish/lite/check.py
107
108
  SizedT = ta.TypeVar('SizedT', bound=ta.Sized)
109
+ CheckMessage = ta.Union[str, ta.Callable[..., ta.Optional[str]], None] # ta.TypeAlias
110
+ CheckLateConfigureFn = ta.Callable[['Checks'], None]
111
+ CheckOnRaiseFn = ta.Callable[[Exception], None] # ta.TypeAlias
112
+ CheckExceptionFactory = ta.Callable[..., Exception] # ta.TypeAlias
113
+ CheckArgsRenderer = ta.Callable[..., ta.Optional[str]] # ta.TypeAlias
108
114
 
109
115
  # ../../omlish/lite/socket.py
110
116
  SocketAddress = ta.Any
@@ -119,12 +125,12 @@ A2 = ta.TypeVar('A2')
119
125
  EventCallback = ta.Callable[['Event'], None]
120
126
  ProcessOutputChannel = ta.Literal['stdout', 'stderr'] # ta.TypeAlias
121
127
 
128
+ # ../../omlish/http/parsing.py
129
+ HttpHeaders = http.client.HTTPMessage # ta.TypeAlias
130
+
122
131
  # ../../omlish/lite/contextmanagers.py
123
132
  ExitStackedT = ta.TypeVar('ExitStackedT', bound='ExitStacked')
124
133
 
125
- # ../../omlish/lite/http/parsing.py
126
- HttpHeaders = http.client.HTTPMessage # ta.TypeAlias
127
-
128
134
  # ../../omlish/lite/inject.py
129
135
  U = ta.TypeVar('U')
130
136
  InjectorKeyCls = ta.Union[type, ta.NewType]
@@ -135,10 +141,10 @@ InjectorBindingOrBindings = ta.Union['InjectorBinding', 'InjectorBindings']
135
141
  # ../configs.py
136
142
  ConfigMapping = ta.Mapping[str, ta.Any]
137
143
 
138
- # ../../omlish/lite/http/handlers.py
144
+ # ../../omlish/http/handlers.py
139
145
  HttpHandler = ta.Callable[['HttpHandlerRequest'], 'HttpHandlerResponse']
140
146
 
141
- # ../../omlish/lite/http/coroserver.py
147
+ # ../../omlish/http/coroserver.py
142
148
  CoroHttpServerFactory = ta.Callable[[SocketAddress], 'CoroHttpServer']
143
149
 
144
150
 
@@ -1431,160 +1437,26 @@ def parse_octal(arg: ta.Union[str, int]) -> int:
1431
1437
 
1432
1438
 
1433
1439
  ########################################
1434
- # ../../../omlish/lite/cached.py
1435
-
1436
-
1437
- ##
1438
-
1439
-
1440
- class _AbstractCachedNullary:
1441
- def __init__(self, fn):
1442
- super().__init__()
1443
- self._fn = fn
1444
- self._value = self._missing = object()
1445
- functools.update_wrapper(self, fn)
1446
-
1447
- def __call__(self, *args, **kwargs): # noqa
1448
- raise TypeError
1449
-
1450
- def __get__(self, instance, owner): # noqa
1451
- bound = instance.__dict__[self._fn.__name__] = self.__class__(self._fn.__get__(instance, owner))
1452
- return bound
1453
-
1454
-
1455
- ##
1456
-
1457
-
1458
- class _CachedNullary(_AbstractCachedNullary):
1459
- def __call__(self, *args, **kwargs): # noqa
1460
- if self._value is self._missing:
1461
- self._value = self._fn()
1462
- return self._value
1463
-
1464
-
1465
- def cached_nullary(fn): # ta.Callable[..., T]) -> ta.Callable[..., T]:
1466
- return _CachedNullary(fn)
1467
-
1468
-
1469
- def static_init(fn: CallableT) -> CallableT:
1470
- fn = cached_nullary(fn)
1471
- fn()
1472
- return fn
1473
-
1474
-
1475
- ##
1476
-
1477
-
1478
- class _AsyncCachedNullary(_AbstractCachedNullary):
1479
- async def __call__(self, *args, **kwargs):
1480
- if self._value is self._missing:
1481
- self._value = await self._fn()
1482
- return self._value
1483
-
1484
-
1485
- def async_cached_nullary(fn): # ta.Callable[..., T]) -> ta.Callable[..., T]:
1486
- return _AsyncCachedNullary(fn)
1487
-
1488
-
1489
- ########################################
1490
- # ../../../omlish/lite/check.py
1491
-
1492
-
1493
- def check_isinstance(v: ta.Any, spec: ta.Union[ta.Type[T], tuple]) -> T:
1494
- if not isinstance(v, spec):
1495
- raise TypeError(v)
1496
- return v
1497
-
1440
+ # ../../../omlish/http/versions.py
1498
1441
 
1499
- def check_not_isinstance(v: T, spec: ta.Union[type, tuple]) -> T:
1500
- if isinstance(v, spec):
1501
- raise TypeError(v)
1502
- return v
1503
-
1504
-
1505
- def check_none(v: T) -> None:
1506
- if v is not None:
1507
- raise ValueError(v)
1508
-
1509
-
1510
- def check_not_none(v: ta.Optional[T]) -> T:
1511
- if v is None:
1512
- raise ValueError
1513
- return v
1514
-
1515
-
1516
- def check_not(v: ta.Any) -> None:
1517
- if v:
1518
- raise ValueError(v)
1519
- return v
1520
-
1521
-
1522
- def check_non_empty_str(v: ta.Optional[str]) -> str:
1523
- if not v:
1524
- raise ValueError
1525
- return v
1526
-
1527
-
1528
- def check_state(v: bool, msg: str = 'Illegal state') -> None:
1529
- if not v:
1530
- raise ValueError(msg)
1531
-
1532
-
1533
- def check_equal(l: T, r: T) -> T:
1534
- if l != r:
1535
- raise ValueError(l, r)
1536
- return l
1537
-
1538
-
1539
- def check_not_equal(l: T, r: T) -> T:
1540
- if l == r:
1541
- raise ValueError(l, r)
1542
- return l
1543
-
1544
-
1545
- def check_is(l: T, r: T) -> T:
1546
- if l is not r:
1547
- raise ValueError(l, r)
1548
- return l
1549
-
1550
-
1551
- def check_is_not(l: T, r: ta.Any) -> T:
1552
- if l is r:
1553
- raise ValueError(l, r)
1554
- return l
1555
-
1556
-
1557
- def check_in(v: T, c: ta.Container[T]) -> T:
1558
- if v not in c:
1559
- raise ValueError(v, c)
1560
- return v
1561
-
1562
-
1563
- def check_not_in(v: T, c: ta.Container[T]) -> T:
1564
- if v in c:
1565
- raise ValueError(v, c)
1566
- return v
1567
-
1568
-
1569
- def check_single(vs: ta.Iterable[T]) -> T:
1570
- [v] = vs
1571
- return v
1572
1442
 
1443
+ class HttpProtocolVersion(ta.NamedTuple):
1444
+ major: int
1445
+ minor: int
1573
1446
 
1574
- def check_empty(v: SizedT) -> SizedT:
1575
- if len(v):
1576
- raise ValueError(v)
1577
- return v
1447
+ def __str__(self) -> str:
1448
+ return f'HTTP/{self.major}.{self.minor}'
1578
1449
 
1579
1450
 
1580
- def check_non_empty(v: SizedT) -> SizedT:
1581
- if not len(v):
1582
- raise ValueError(v)
1583
- return v
1451
+ class HttpProtocolVersions:
1452
+ HTTP_0_9 = HttpProtocolVersion(0, 9)
1453
+ HTTP_1_0 = HttpProtocolVersion(1, 0)
1454
+ HTTP_1_1 = HttpProtocolVersion(1, 1)
1455
+ HTTP_2_0 = HttpProtocolVersion(2, 0)
1584
1456
 
1585
1457
 
1586
1458
  ########################################
1587
- # ../../../omlish/lite/fdio/pollers.py
1459
+ # ../../../omlish/io/fdio/pollers.py
1588
1460
 
1589
1461
 
1590
1462
  ##
@@ -1794,161 +1666,650 @@ else:
1794
1666
 
1795
1667
 
1796
1668
  ########################################
1797
- # ../../../omlish/lite/http/versions.py
1798
-
1669
+ # ../../../omlish/lite/cached.py
1799
1670
 
1800
- class HttpProtocolVersion(ta.NamedTuple):
1801
- major: int
1802
- minor: int
1803
1671
 
1804
- def __str__(self) -> str:
1805
- return f'HTTP/{self.major}.{self.minor}'
1672
+ ##
1806
1673
 
1807
1674
 
1808
- class HttpProtocolVersions:
1809
- HTTP_0_9 = HttpProtocolVersion(0, 9)
1810
- HTTP_1_0 = HttpProtocolVersion(1, 0)
1811
- HTTP_1_1 = HttpProtocolVersion(1, 1)
1812
- HTTP_2_0 = HttpProtocolVersion(2, 0)
1675
+ class _AbstractCachedNullary:
1676
+ def __init__(self, fn):
1677
+ super().__init__()
1678
+ self._fn = fn
1679
+ self._value = self._missing = object()
1680
+ functools.update_wrapper(self, fn)
1813
1681
 
1682
+ def __call__(self, *args, **kwargs): # noqa
1683
+ raise TypeError
1814
1684
 
1815
- ########################################
1816
- # ../../../omlish/lite/json.py
1685
+ def __get__(self, instance, owner): # noqa
1686
+ bound = instance.__dict__[self._fn.__name__] = self.__class__(self._fn.__get__(instance, owner))
1687
+ return bound
1817
1688
 
1818
1689
 
1819
1690
  ##
1820
1691
 
1821
1692
 
1822
- JSON_PRETTY_INDENT = 2
1693
+ class _CachedNullary(_AbstractCachedNullary):
1694
+ def __call__(self, *args, **kwargs): # noqa
1695
+ if self._value is self._missing:
1696
+ self._value = self._fn()
1697
+ return self._value
1823
1698
 
1824
- JSON_PRETTY_KWARGS: ta.Mapping[str, ta.Any] = dict(
1825
- indent=JSON_PRETTY_INDENT,
1826
- )
1827
1699
 
1828
- json_dump_pretty: ta.Callable[..., bytes] = functools.partial(json.dump, **JSON_PRETTY_KWARGS) # type: ignore
1829
- json_dumps_pretty: ta.Callable[..., str] = functools.partial(json.dumps, **JSON_PRETTY_KWARGS)
1700
+ def cached_nullary(fn): # ta.Callable[..., T]) -> ta.Callable[..., T]:
1701
+ return _CachedNullary(fn)
1702
+
1703
+
1704
+ def static_init(fn: CallableT) -> CallableT:
1705
+ fn = cached_nullary(fn)
1706
+ fn()
1707
+ return fn
1830
1708
 
1831
1709
 
1832
1710
  ##
1833
1711
 
1834
1712
 
1835
- JSON_COMPACT_SEPARATORS = (',', ':')
1713
+ class _AsyncCachedNullary(_AbstractCachedNullary):
1714
+ async def __call__(self, *args, **kwargs):
1715
+ if self._value is self._missing:
1716
+ self._value = await self._fn()
1717
+ return self._value
1836
1718
 
1837
- JSON_COMPACT_KWARGS: ta.Mapping[str, ta.Any] = dict(
1838
- indent=None,
1839
- separators=JSON_COMPACT_SEPARATORS,
1840
- )
1841
1719
 
1842
- json_dump_compact: ta.Callable[..., bytes] = functools.partial(json.dump, **JSON_COMPACT_KWARGS) # type: ignore
1843
- json_dumps_compact: ta.Callable[..., str] = functools.partial(json.dumps, **JSON_COMPACT_KWARGS)
1720
+ def async_cached_nullary(fn): # ta.Callable[..., T]) -> ta.Callable[..., T]:
1721
+ return _AsyncCachedNullary(fn)
1844
1722
 
1845
1723
 
1846
1724
  ########################################
1847
- # ../../../omlish/lite/maybes.py
1725
+ # ../../../omlish/lite/check.py
1726
+ """
1727
+ TODO:
1728
+ - def maybe(v: lang.Maybe[T])
1729
+ - patch / override lite.check ?
1730
+ - checker interface?
1731
+ """
1848
1732
 
1849
1733
 
1850
- class Maybe(ta.Generic[T]):
1851
- @property
1852
- @abc.abstractmethod
1853
- def present(self) -> bool:
1854
- raise NotImplementedError
1734
+ ##
1855
1735
 
1856
- @abc.abstractmethod
1857
- def must(self) -> T:
1858
- raise NotImplementedError
1859
1736
 
1860
- @classmethod
1861
- def just(cls, v: T) -> 'Maybe[T]':
1862
- return tuple.__new__(_Maybe, (v,)) # noqa
1737
+ class Checks:
1738
+ def __init__(self) -> None:
1739
+ super().__init__()
1863
1740
 
1864
- _empty: ta.ClassVar['Maybe']
1741
+ self._config_lock = threading.RLock()
1742
+ self._on_raise_fns: ta.Sequence[CheckOnRaiseFn] = []
1743
+ self._exception_factory: CheckExceptionFactory = Checks.default_exception_factory
1744
+ self._args_renderer: ta.Optional[CheckArgsRenderer] = None
1745
+ self._late_configure_fns: ta.Sequence[CheckLateConfigureFn] = []
1865
1746
 
1866
- @classmethod
1867
- def empty(cls) -> 'Maybe[T]':
1868
- return Maybe._empty
1747
+ @staticmethod
1748
+ def default_exception_factory(exc_cls: ta.Type[Exception], *args, **kwargs) -> Exception:
1749
+ return exc_cls(*args, **kwargs) # noqa
1869
1750
 
1751
+ #
1870
1752
 
1871
- class _Maybe(Maybe[T], tuple):
1872
- __slots__ = ()
1753
+ def register_on_raise(self, fn: CheckOnRaiseFn) -> None:
1754
+ with self._config_lock:
1755
+ self._on_raise_fns = [*self._on_raise_fns, fn]
1873
1756
 
1874
- def __init_subclass__(cls, **kwargs):
1875
- raise TypeError
1757
+ def unregister_on_raise(self, fn: CheckOnRaiseFn) -> None:
1758
+ with self._config_lock:
1759
+ self._on_raise_fns = [e for e in self._on_raise_fns if e != fn]
1876
1760
 
1877
- @property
1878
- def present(self) -> bool:
1879
- return bool(self)
1761
+ #
1880
1762
 
1881
- def must(self) -> T:
1882
- if not self:
1883
- raise ValueError
1884
- return self[0]
1763
+ def set_exception_factory(self, factory: CheckExceptionFactory) -> None:
1764
+ self._exception_factory = factory
1885
1765
 
1766
+ def set_args_renderer(self, renderer: ta.Optional[CheckArgsRenderer]) -> None:
1767
+ self._args_renderer = renderer
1886
1768
 
1887
- Maybe._empty = tuple.__new__(_Maybe, ()) # noqa
1769
+ #
1888
1770
 
1771
+ def register_late_configure(self, fn: CheckLateConfigureFn) -> None:
1772
+ with self._config_lock:
1773
+ self._late_configure_fns = [*self._late_configure_fns, fn]
1889
1774
 
1890
- ########################################
1891
- # ../../../omlish/lite/reflect.py
1775
+ def _late_configure(self) -> None:
1776
+ if not self._late_configure_fns:
1777
+ return
1892
1778
 
1779
+ with self._config_lock:
1780
+ if not (lc := self._late_configure_fns):
1781
+ return
1893
1782
 
1894
- _GENERIC_ALIAS_TYPES = (
1895
- ta._GenericAlias, # type: ignore # noqa
1896
- *([ta._SpecialGenericAlias] if hasattr(ta, '_SpecialGenericAlias') else []), # noqa
1897
- )
1783
+ for fn in lc:
1784
+ fn(self)
1898
1785
 
1786
+ self._late_configure_fns = []
1899
1787
 
1900
- def is_generic_alias(obj, *, origin: ta.Any = None) -> bool:
1901
- return (
1902
- isinstance(obj, _GENERIC_ALIAS_TYPES) and
1903
- (origin is None or ta.get_origin(obj) is origin)
1904
- )
1788
+ #
1905
1789
 
1790
+ class _ArgsKwargs:
1791
+ def __init__(self, *args, **kwargs):
1792
+ self.args = args
1793
+ self.kwargs = kwargs
1906
1794
 
1907
- is_union_alias = functools.partial(is_generic_alias, origin=ta.Union)
1908
- is_callable_alias = functools.partial(is_generic_alias, origin=ta.Callable)
1795
+ def _raise(
1796
+ self,
1797
+ exception_type: ta.Type[Exception],
1798
+ default_message: str,
1799
+ message: CheckMessage,
1800
+ ak: _ArgsKwargs = _ArgsKwargs(),
1801
+ *,
1802
+ render_fmt: ta.Optional[str] = None,
1803
+ ) -> ta.NoReturn:
1804
+ exc_args = ()
1805
+ if callable(message):
1806
+ message = ta.cast(ta.Callable, message)(*ak.args, **ak.kwargs)
1807
+ if isinstance(message, tuple):
1808
+ message, *exc_args = message # type: ignore
1909
1809
 
1810
+ if message is None:
1811
+ message = default_message
1910
1812
 
1911
- def is_optional_alias(spec: ta.Any) -> bool:
1912
- return (
1913
- isinstance(spec, _GENERIC_ALIAS_TYPES) and # noqa
1914
- ta.get_origin(spec) is ta.Union and
1915
- len(ta.get_args(spec)) == 2 and
1916
- any(a in (None, type(None)) for a in ta.get_args(spec))
1917
- )
1813
+ self._late_configure()
1918
1814
 
1815
+ if render_fmt is not None and (af := self._args_renderer) is not None:
1816
+ rendered_args = af(render_fmt, *ak.args)
1817
+ if rendered_args is not None:
1818
+ message = f'{message} : {rendered_args}'
1919
1819
 
1920
- def get_optional_alias_arg(spec: ta.Any) -> ta.Any:
1921
- [it] = [it for it in ta.get_args(spec) if it not in (None, type(None))]
1922
- return it
1820
+ exc = self._exception_factory(
1821
+ exception_type,
1822
+ message,
1823
+ *exc_args,
1824
+ *ak.args,
1825
+ **ak.kwargs,
1826
+ )
1923
1827
 
1828
+ for fn in self._on_raise_fns:
1829
+ fn(exc)
1924
1830
 
1925
- def is_new_type(spec: ta.Any) -> bool:
1926
- if isinstance(ta.NewType, type):
1927
- return isinstance(spec, ta.NewType)
1928
- else:
1929
- # Before https://github.com/python/cpython/commit/c2f33dfc83ab270412bf243fb21f724037effa1a
1930
- return isinstance(spec, types.FunctionType) and spec.__code__ is ta.NewType.__code__.co_consts[1] # type: ignore # noqa
1831
+ raise exc
1931
1832
 
1833
+ #
1932
1834
 
1933
- def deep_subclasses(cls: ta.Type[T]) -> ta.Iterator[ta.Type[T]]:
1934
- seen = set()
1935
- todo = list(reversed(cls.__subclasses__()))
1936
- while todo:
1937
- cur = todo.pop()
1938
- if cur in seen:
1939
- continue
1940
- seen.add(cur)
1941
- yield cur
1942
- todo.extend(reversed(cur.__subclasses__()))
1835
+ def _unpack_isinstance_spec(self, spec: ta.Any) -> tuple:
1836
+ if isinstance(spec, type):
1837
+ return (spec,)
1838
+ if not isinstance(spec, tuple):
1839
+ spec = (spec,)
1840
+ if None in spec:
1841
+ spec = tuple(filter(None, spec)) + (None.__class__,) # noqa
1842
+ if ta.Any in spec:
1843
+ spec = (object,)
1844
+ return spec
1845
+
1846
+ def isinstance(self, v: ta.Any, spec: ta.Union[ta.Type[T], tuple], msg: CheckMessage = None) -> T: # noqa
1847
+ if not isinstance(v, self._unpack_isinstance_spec(spec)):
1848
+ self._raise(
1849
+ TypeError,
1850
+ 'Must be instance',
1851
+ msg,
1852
+ Checks._ArgsKwargs(v, spec),
1853
+ render_fmt='not isinstance(%s, %s)',
1854
+ )
1943
1855
 
1856
+ return v
1944
1857
 
1945
- ########################################
1946
- # ../../../omlish/lite/socket.py
1947
- """
1948
- TODO:
1949
- - SocketClientAddress family / tuple pairs
1950
- + codification of https://docs.python.org/3/library/socket.html#socket-families
1951
- """
1858
+ def of_isinstance(self, spec: ta.Union[ta.Type[T], tuple], msg: CheckMessage = None) -> ta.Callable[[ta.Any], T]:
1859
+ def inner(v):
1860
+ return self.isinstance(v, self._unpack_isinstance_spec(spec), msg)
1861
+
1862
+ return inner
1863
+
1864
+ def cast(self, v: ta.Any, cls: ta.Type[T], msg: CheckMessage = None) -> T: # noqa
1865
+ if not isinstance(v, cls):
1866
+ self._raise(
1867
+ TypeError,
1868
+ 'Must be instance',
1869
+ msg,
1870
+ Checks._ArgsKwargs(v, cls),
1871
+ )
1872
+
1873
+ return v
1874
+
1875
+ def of_cast(self, cls: ta.Type[T], msg: CheckMessage = None) -> ta.Callable[[T], T]:
1876
+ def inner(v):
1877
+ return self.cast(v, cls, msg)
1878
+
1879
+ return inner
1880
+
1881
+ def not_isinstance(self, v: T, spec: ta.Any, msg: CheckMessage = None) -> T: # noqa
1882
+ if isinstance(v, self._unpack_isinstance_spec(spec)):
1883
+ self._raise(
1884
+ TypeError,
1885
+ 'Must not be instance',
1886
+ msg,
1887
+ Checks._ArgsKwargs(v, spec),
1888
+ render_fmt='isinstance(%s, %s)',
1889
+ )
1890
+
1891
+ return v
1892
+
1893
+ def of_not_isinstance(self, spec: ta.Any, msg: CheckMessage = None) -> ta.Callable[[T], T]:
1894
+ def inner(v):
1895
+ return self.not_isinstance(v, self._unpack_isinstance_spec(spec), msg)
1896
+
1897
+ return inner
1898
+
1899
+ ##
1900
+
1901
+ def issubclass(self, v: ta.Type[T], spec: ta.Any, msg: CheckMessage = None) -> ta.Type[T]: # noqa
1902
+ if not issubclass(v, spec):
1903
+ self._raise(
1904
+ TypeError,
1905
+ 'Must be subclass',
1906
+ msg,
1907
+ Checks._ArgsKwargs(v, spec),
1908
+ render_fmt='not issubclass(%s, %s)',
1909
+ )
1910
+
1911
+ return v
1912
+
1913
+ def not_issubclass(self, v: ta.Type[T], spec: ta.Any, msg: CheckMessage = None) -> ta.Type[T]: # noqa
1914
+ if issubclass(v, spec):
1915
+ self._raise(
1916
+ TypeError,
1917
+ 'Must not be subclass',
1918
+ msg,
1919
+ Checks._ArgsKwargs(v, spec),
1920
+ render_fmt='issubclass(%s, %s)',
1921
+ )
1922
+
1923
+ return v
1924
+
1925
+ #
1926
+
1927
+ def in_(self, v: T, c: ta.Container[T], msg: CheckMessage = None) -> T:
1928
+ if v not in c:
1929
+ self._raise(
1930
+ ValueError,
1931
+ 'Must be in',
1932
+ msg,
1933
+ Checks._ArgsKwargs(v, c),
1934
+ render_fmt='%s not in %s',
1935
+ )
1936
+
1937
+ return v
1938
+
1939
+ def not_in(self, v: T, c: ta.Container[T], msg: CheckMessage = None) -> T:
1940
+ if v in c:
1941
+ self._raise(
1942
+ ValueError,
1943
+ 'Must not be in',
1944
+ msg,
1945
+ Checks._ArgsKwargs(v, c),
1946
+ render_fmt='%s in %s',
1947
+ )
1948
+
1949
+ return v
1950
+
1951
+ def empty(self, v: SizedT, msg: CheckMessage = None) -> SizedT:
1952
+ if len(v) != 0:
1953
+ self._raise(
1954
+ ValueError,
1955
+ 'Must be empty',
1956
+ msg,
1957
+ Checks._ArgsKwargs(v),
1958
+ render_fmt='%s',
1959
+ )
1960
+
1961
+ return v
1962
+
1963
+ def iterempty(self, v: ta.Iterable[T], msg: CheckMessage = None) -> ta.Iterable[T]:
1964
+ it = iter(v)
1965
+ try:
1966
+ next(it)
1967
+ except StopIteration:
1968
+ pass
1969
+ else:
1970
+ self._raise(
1971
+ ValueError,
1972
+ 'Must be empty',
1973
+ msg,
1974
+ Checks._ArgsKwargs(v),
1975
+ render_fmt='%s',
1976
+ )
1977
+
1978
+ return v
1979
+
1980
+ def not_empty(self, v: SizedT, msg: CheckMessage = None) -> SizedT:
1981
+ if len(v) == 0:
1982
+ self._raise(
1983
+ ValueError,
1984
+ 'Must not be empty',
1985
+ msg,
1986
+ Checks._ArgsKwargs(v),
1987
+ render_fmt='%s',
1988
+ )
1989
+
1990
+ return v
1991
+
1992
+ def unique(self, it: ta.Iterable[T], msg: CheckMessage = None) -> ta.Iterable[T]:
1993
+ dupes = [e for e, c in collections.Counter(it).items() if c > 1]
1994
+ if dupes:
1995
+ self._raise(
1996
+ ValueError,
1997
+ 'Must be unique',
1998
+ msg,
1999
+ Checks._ArgsKwargs(it, dupes),
2000
+ )
2001
+
2002
+ return it
2003
+
2004
+ def single(self, obj: ta.Iterable[T], message: CheckMessage = None) -> T:
2005
+ try:
2006
+ [value] = obj
2007
+ except ValueError:
2008
+ self._raise(
2009
+ ValueError,
2010
+ 'Must be single',
2011
+ message,
2012
+ Checks._ArgsKwargs(obj),
2013
+ render_fmt='%s',
2014
+ )
2015
+
2016
+ return value
2017
+
2018
+ def opt_single(self, obj: ta.Iterable[T], message: CheckMessage = None) -> ta.Optional[T]:
2019
+ it = iter(obj)
2020
+ try:
2021
+ value = next(it)
2022
+ except StopIteration:
2023
+ return None
2024
+
2025
+ try:
2026
+ next(it)
2027
+ except StopIteration:
2028
+ return value # noqa
2029
+
2030
+ self._raise(
2031
+ ValueError,
2032
+ 'Must be empty or single',
2033
+ message,
2034
+ Checks._ArgsKwargs(obj),
2035
+ render_fmt='%s',
2036
+ )
2037
+
2038
+ raise RuntimeError # noqa
2039
+
2040
+ #
2041
+
2042
+ def none(self, v: ta.Any, msg: CheckMessage = None) -> None:
2043
+ if v is not None:
2044
+ self._raise(
2045
+ ValueError,
2046
+ 'Must be None',
2047
+ msg,
2048
+ Checks._ArgsKwargs(v),
2049
+ render_fmt='%s',
2050
+ )
2051
+
2052
+ def not_none(self, v: ta.Optional[T], msg: CheckMessage = None) -> T:
2053
+ if v is None:
2054
+ self._raise(
2055
+ ValueError,
2056
+ 'Must not be None',
2057
+ msg,
2058
+ Checks._ArgsKwargs(v),
2059
+ render_fmt='%s',
2060
+ )
2061
+
2062
+ return v
2063
+
2064
+ #
2065
+
2066
+ def equal(self, v: T, o: ta.Any, msg: CheckMessage = None) -> T:
2067
+ if o != v:
2068
+ self._raise(
2069
+ ValueError,
2070
+ 'Must be equal',
2071
+ msg,
2072
+ Checks._ArgsKwargs(v, o),
2073
+ render_fmt='%s != %s',
2074
+ )
2075
+
2076
+ return v
2077
+
2078
+ def is_(self, v: T, o: ta.Any, msg: CheckMessage = None) -> T:
2079
+ if o is not v:
2080
+ self._raise(
2081
+ ValueError,
2082
+ 'Must be the same',
2083
+ msg,
2084
+ Checks._ArgsKwargs(v, o),
2085
+ render_fmt='%s is not %s',
2086
+ )
2087
+
2088
+ return v
2089
+
2090
+ def is_not(self, v: T, o: ta.Any, msg: CheckMessage = None) -> T:
2091
+ if o is v:
2092
+ self._raise(
2093
+ ValueError,
2094
+ 'Must not be the same',
2095
+ msg,
2096
+ Checks._ArgsKwargs(v, o),
2097
+ render_fmt='%s is %s',
2098
+ )
2099
+
2100
+ return v
2101
+
2102
+ def callable(self, v: T, msg: CheckMessage = None) -> T: # noqa
2103
+ if not callable(v):
2104
+ self._raise(
2105
+ TypeError,
2106
+ 'Must be callable',
2107
+ msg,
2108
+ Checks._ArgsKwargs(v),
2109
+ render_fmt='%s',
2110
+ )
2111
+
2112
+ return v # type: ignore
2113
+
2114
+ def non_empty_str(self, v: ta.Optional[str], msg: CheckMessage = None) -> str:
2115
+ if not isinstance(v, str) or not v:
2116
+ self._raise(
2117
+ ValueError,
2118
+ 'Must be non-empty str',
2119
+ msg,
2120
+ Checks._ArgsKwargs(v),
2121
+ render_fmt='%s',
2122
+ )
2123
+
2124
+ return v
2125
+
2126
+ def replacing(self, expected: ta.Any, old: ta.Any, new: T, msg: CheckMessage = None) -> T:
2127
+ if old != expected:
2128
+ self._raise(
2129
+ ValueError,
2130
+ 'Must be replacing',
2131
+ msg,
2132
+ Checks._ArgsKwargs(expected, old, new),
2133
+ render_fmt='%s -> %s -> %s',
2134
+ )
2135
+
2136
+ return new
2137
+
2138
+ def replacing_none(self, old: ta.Any, new: T, msg: CheckMessage = None) -> T:
2139
+ if old is not None:
2140
+ self._raise(
2141
+ ValueError,
2142
+ 'Must be replacing None',
2143
+ msg,
2144
+ Checks._ArgsKwargs(old, new),
2145
+ render_fmt='%s -> %s',
2146
+ )
2147
+
2148
+ return new
2149
+
2150
+ #
2151
+
2152
+ def arg(self, v: bool, msg: CheckMessage = None) -> None:
2153
+ if not v:
2154
+ self._raise(
2155
+ RuntimeError,
2156
+ 'Argument condition not met',
2157
+ msg,
2158
+ Checks._ArgsKwargs(v),
2159
+ render_fmt='%s',
2160
+ )
2161
+
2162
+ def state(self, v: bool, msg: CheckMessage = None) -> None:
2163
+ if not v:
2164
+ self._raise(
2165
+ RuntimeError,
2166
+ 'State condition not met',
2167
+ msg,
2168
+ Checks._ArgsKwargs(v),
2169
+ render_fmt='%s',
2170
+ )
2171
+
2172
+
2173
+ check = Checks()
2174
+
2175
+
2176
+ ########################################
2177
+ # ../../../omlish/lite/json.py
2178
+
2179
+
2180
+ ##
2181
+
2182
+
2183
+ JSON_PRETTY_INDENT = 2
2184
+
2185
+ JSON_PRETTY_KWARGS: ta.Mapping[str, ta.Any] = dict(
2186
+ indent=JSON_PRETTY_INDENT,
2187
+ )
2188
+
2189
+ json_dump_pretty: ta.Callable[..., bytes] = functools.partial(json.dump, **JSON_PRETTY_KWARGS) # type: ignore
2190
+ json_dumps_pretty: ta.Callable[..., str] = functools.partial(json.dumps, **JSON_PRETTY_KWARGS)
2191
+
2192
+
2193
+ ##
2194
+
2195
+
2196
+ JSON_COMPACT_SEPARATORS = (',', ':')
2197
+
2198
+ JSON_COMPACT_KWARGS: ta.Mapping[str, ta.Any] = dict(
2199
+ indent=None,
2200
+ separators=JSON_COMPACT_SEPARATORS,
2201
+ )
2202
+
2203
+ json_dump_compact: ta.Callable[..., bytes] = functools.partial(json.dump, **JSON_COMPACT_KWARGS) # type: ignore
2204
+ json_dumps_compact: ta.Callable[..., str] = functools.partial(json.dumps, **JSON_COMPACT_KWARGS)
2205
+
2206
+
2207
+ ########################################
2208
+ # ../../../omlish/lite/maybes.py
2209
+
2210
+
2211
+ class Maybe(ta.Generic[T]):
2212
+ @property
2213
+ @abc.abstractmethod
2214
+ def present(self) -> bool:
2215
+ raise NotImplementedError
2216
+
2217
+ @abc.abstractmethod
2218
+ def must(self) -> T:
2219
+ raise NotImplementedError
2220
+
2221
+ @classmethod
2222
+ def just(cls, v: T) -> 'Maybe[T]':
2223
+ return tuple.__new__(_Maybe, (v,)) # noqa
2224
+
2225
+ _empty: ta.ClassVar['Maybe']
2226
+
2227
+ @classmethod
2228
+ def empty(cls) -> 'Maybe[T]':
2229
+ return Maybe._empty
2230
+
2231
+
2232
+ class _Maybe(Maybe[T], tuple):
2233
+ __slots__ = ()
2234
+
2235
+ def __init_subclass__(cls, **kwargs):
2236
+ raise TypeError
2237
+
2238
+ @property
2239
+ def present(self) -> bool:
2240
+ return bool(self)
2241
+
2242
+ def must(self) -> T:
2243
+ if not self:
2244
+ raise ValueError
2245
+ return self[0]
2246
+
2247
+
2248
+ Maybe._empty = tuple.__new__(_Maybe, ()) # noqa
2249
+
2250
+
2251
+ ########################################
2252
+ # ../../../omlish/lite/reflect.py
2253
+
2254
+
2255
+ _GENERIC_ALIAS_TYPES = (
2256
+ ta._GenericAlias, # type: ignore # noqa
2257
+ *([ta._SpecialGenericAlias] if hasattr(ta, '_SpecialGenericAlias') else []), # noqa
2258
+ )
2259
+
2260
+
2261
+ def is_generic_alias(obj, *, origin: ta.Any = None) -> bool:
2262
+ return (
2263
+ isinstance(obj, _GENERIC_ALIAS_TYPES) and
2264
+ (origin is None or ta.get_origin(obj) is origin)
2265
+ )
2266
+
2267
+
2268
+ is_union_alias = functools.partial(is_generic_alias, origin=ta.Union)
2269
+ is_callable_alias = functools.partial(is_generic_alias, origin=ta.Callable)
2270
+
2271
+
2272
+ def is_optional_alias(spec: ta.Any) -> bool:
2273
+ return (
2274
+ isinstance(spec, _GENERIC_ALIAS_TYPES) and # noqa
2275
+ ta.get_origin(spec) is ta.Union and
2276
+ len(ta.get_args(spec)) == 2 and
2277
+ any(a in (None, type(None)) for a in ta.get_args(spec))
2278
+ )
2279
+
2280
+
2281
+ def get_optional_alias_arg(spec: ta.Any) -> ta.Any:
2282
+ [it] = [it for it in ta.get_args(spec) if it not in (None, type(None))]
2283
+ return it
2284
+
2285
+
2286
+ def is_new_type(spec: ta.Any) -> bool:
2287
+ if isinstance(ta.NewType, type):
2288
+ return isinstance(spec, ta.NewType)
2289
+ else:
2290
+ # Before https://github.com/python/cpython/commit/c2f33dfc83ab270412bf243fb21f724037effa1a
2291
+ return isinstance(spec, types.FunctionType) and spec.__code__ is ta.NewType.__code__.co_consts[1] # type: ignore # noqa
2292
+
2293
+
2294
+ def deep_subclasses(cls: ta.Type[T]) -> ta.Iterator[ta.Type[T]]:
2295
+ seen = set()
2296
+ todo = list(reversed(cls.__subclasses__()))
2297
+ while todo:
2298
+ cur = todo.pop()
2299
+ if cur in seen:
2300
+ continue
2301
+ seen.add(cur)
2302
+ yield cur
2303
+ todo.extend(reversed(cur.__subclasses__()))
2304
+
2305
+
2306
+ ########################################
2307
+ # ../../../omlish/lite/socket.py
2308
+ """
2309
+ TODO:
2310
+ - SocketClientAddress family / tuple pairs
2311
+ + codification of https://docs.python.org/3/library/socket.html#socket-families
2312
+ """
1952
2313
 
1953
2314
 
1954
2315
  ##
@@ -2564,250 +2925,7 @@ def get_user(name: str) -> User:
2564
2925
 
2565
2926
 
2566
2927
  ########################################
2567
- # ../../../omlish/lite/contextmanagers.py
2568
-
2569
-
2570
- ##
2571
-
2572
-
2573
- class ExitStacked:
2574
- _exit_stack: ta.Optional[contextlib.ExitStack] = None
2575
-
2576
- def __enter__(self: ExitStackedT) -> ExitStackedT:
2577
- check_state(self._exit_stack is None)
2578
- es = self._exit_stack = contextlib.ExitStack()
2579
- es.__enter__()
2580
- return self
2581
-
2582
- def __exit__(self, exc_type, exc_val, exc_tb):
2583
- if (es := self._exit_stack) is None:
2584
- return None
2585
- self._exit_contexts()
2586
- return es.__exit__(exc_type, exc_val, exc_tb)
2587
-
2588
- def _exit_contexts(self) -> None:
2589
- pass
2590
-
2591
- def _enter_context(self, cm: ta.ContextManager[T]) -> T:
2592
- es = check_not_none(self._exit_stack)
2593
- return es.enter_context(cm)
2594
-
2595
-
2596
- ##
2597
-
2598
-
2599
- @contextlib.contextmanager
2600
- def defer(fn: ta.Callable) -> ta.Generator[ta.Callable, None, None]:
2601
- try:
2602
- yield fn
2603
- finally:
2604
- fn()
2605
-
2606
-
2607
- @contextlib.contextmanager
2608
- def attr_setting(obj, attr, val, *, default=None): # noqa
2609
- not_set = object()
2610
- orig = getattr(obj, attr, not_set)
2611
- try:
2612
- setattr(obj, attr, val)
2613
- if orig is not not_set:
2614
- yield orig
2615
- else:
2616
- yield default
2617
- finally:
2618
- if orig is not_set:
2619
- delattr(obj, attr)
2620
- else:
2621
- setattr(obj, attr, orig)
2622
-
2623
-
2624
- ########################################
2625
- # ../../../omlish/lite/fdio/handlers.py
2626
-
2627
-
2628
- class FdioHandler(abc.ABC):
2629
- @abc.abstractmethod
2630
- def fd(self) -> int:
2631
- raise NotImplementedError
2632
-
2633
- #
2634
-
2635
- @property
2636
- @abc.abstractmethod
2637
- def closed(self) -> bool:
2638
- raise NotImplementedError
2639
-
2640
- @abc.abstractmethod
2641
- def close(self) -> None:
2642
- raise NotImplementedError
2643
-
2644
- #
2645
-
2646
- def readable(self) -> bool:
2647
- return False
2648
-
2649
- def writable(self) -> bool:
2650
- return False
2651
-
2652
- #
2653
-
2654
- def on_readable(self) -> None:
2655
- raise TypeError
2656
-
2657
- def on_writable(self) -> None:
2658
- raise TypeError
2659
-
2660
- def on_error(self, exc: ta.Optional[BaseException] = None) -> None: # noqa
2661
- pass
2662
-
2663
-
2664
- class SocketFdioHandler(FdioHandler, abc.ABC):
2665
- def __init__(
2666
- self,
2667
- addr: SocketAddress,
2668
- sock: socket.socket,
2669
- ) -> None:
2670
- super().__init__()
2671
-
2672
- self._addr = addr
2673
- self._sock: ta.Optional[socket.socket] = sock
2674
-
2675
- def fd(self) -> int:
2676
- return check_not_none(self._sock).fileno()
2677
-
2678
- @property
2679
- def closed(self) -> bool:
2680
- return self._sock is None
2681
-
2682
- def close(self) -> None:
2683
- if self._sock is not None:
2684
- self._sock.close()
2685
- self._sock = None
2686
-
2687
-
2688
- ########################################
2689
- # ../../../omlish/lite/fdio/kqueue.py
2690
-
2691
-
2692
- KqueueFdioPoller: ta.Optional[ta.Type[FdioPoller]]
2693
- if sys.platform == 'darwin' or sys.platform.startswith('freebsd'):
2694
-
2695
- class _KqueueFdioPoller(FdioPoller):
2696
- DEFAULT_MAX_EVENTS = 1000
2697
-
2698
- def __init__(
2699
- self,
2700
- *,
2701
- max_events: int = DEFAULT_MAX_EVENTS,
2702
- ) -> None:
2703
- super().__init__()
2704
-
2705
- self._max_events = max_events
2706
-
2707
- self._kqueue: ta.Optional[ta.Any] = None
2708
-
2709
- #
2710
-
2711
- def _get_kqueue(self) -> 'select.kqueue':
2712
- if (kq := self._kqueue) is not None:
2713
- return kq
2714
- kq = select.kqueue()
2715
- self._kqueue = kq
2716
- return kq
2717
-
2718
- def close(self) -> None:
2719
- if self._kqueue is not None:
2720
- self._kqueue.close()
2721
- self._kqueue = None
2722
-
2723
- def reopen(self) -> None:
2724
- for fd in self._readable:
2725
- self._register_readable(fd)
2726
- for fd in self._writable:
2727
- self._register_writable(fd)
2728
-
2729
- #
2730
-
2731
- def _register_readable(self, fd: int) -> None:
2732
- self._update_registration(fd, 'read', 'add')
2733
-
2734
- def _register_writable(self, fd: int) -> None:
2735
- self._update_registration(fd, 'write', 'add')
2736
-
2737
- def _unregister_readable(self, fd: int) -> None:
2738
- self._update_registration(fd, 'read', 'del')
2739
-
2740
- def _unregister_writable(self, fd: int) -> None:
2741
- self._update_registration(fd, 'write', 'del')
2742
-
2743
- #
2744
-
2745
- _CONTROL_FILTER_BY_READ_OR_WRITE: ta.ClassVar[ta.Mapping[ta.Literal['read', 'write'], int]] = {
2746
- 'read': select.KQ_FILTER_READ,
2747
- 'write': select.KQ_FILTER_WRITE,
2748
- }
2749
-
2750
- _CONTROL_FLAGS_BY_ADD_OR_DEL: ta.ClassVar[ta.Mapping[ta.Literal['add', 'del'], int]] = {
2751
- 'add': select.KQ_EV_ADD,
2752
- 'del': select.KQ_EV_DELETE,
2753
- }
2754
-
2755
- def _update_registration(
2756
- self,
2757
- fd: int,
2758
- read_or_write: ta.Literal['read', 'write'],
2759
- add_or_del: ta.Literal['add', 'del'],
2760
- ) -> None: # noqa
2761
- ke = select.kevent(
2762
- fd,
2763
- filter=self._CONTROL_FILTER_BY_READ_OR_WRITE[read_or_write],
2764
- flags=self._CONTROL_FLAGS_BY_ADD_OR_DEL[add_or_del],
2765
- )
2766
- kq = self._get_kqueue()
2767
- try:
2768
- kq.control([ke], 0)
2769
-
2770
- except OSError as exc:
2771
- if exc.errno == errno.EBADF:
2772
- # log.debug('EBADF encountered in kqueue. Invalid file descriptor %s', ke.ident)
2773
- pass
2774
- elif exc.errno == errno.ENOENT:
2775
- # Can happen when trying to remove an already closed socket
2776
- if add_or_del == 'add':
2777
- raise
2778
- else:
2779
- raise
2780
-
2781
- #
2782
-
2783
- def poll(self, timeout: ta.Optional[float]) -> FdioPoller.PollResult:
2784
- kq = self._get_kqueue()
2785
- try:
2786
- kes = kq.control(None, self._max_events, timeout)
2787
-
2788
- except OSError as exc:
2789
- if exc.errno == errno.EINTR:
2790
- return FdioPoller.PollResult(msg='EINTR encountered in poll', exc=exc)
2791
- else:
2792
- raise
2793
-
2794
- r: ta.List[int] = []
2795
- w: ta.List[int] = []
2796
- for ke in kes:
2797
- if ke.filter == select.KQ_FILTER_READ:
2798
- r.append(ke.ident)
2799
- if ke.filter == select.KQ_FILTER_WRITE:
2800
- w.append(ke.ident)
2801
-
2802
- return FdioPoller.PollResult(r, w)
2803
-
2804
- KqueueFdioPoller = _KqueueFdioPoller
2805
- else:
2806
- KqueueFdioPoller = None
2807
-
2808
-
2809
- ########################################
2810
- # ../../../omlish/lite/http/parsing.py
2928
+ # ../../../omlish/http/parsing.py
2811
2929
  # PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
2812
2930
  # --------------------------------------------
2813
2931
  #
@@ -3182,28 +3300,493 @@ class HttpRequestParser:
3182
3300
  ):
3183
3301
  close_connection = False
3184
3302
 
3185
- # Check for expect directive
3303
+ # Check for expect directive
3304
+
3305
+ expect = headers.get('Expect', '')
3306
+ if (
3307
+ expect.lower() == '100-continue' and
3308
+ version >= HttpProtocolVersions.HTTP_1_1
3309
+ ):
3310
+ expects_continue = True
3311
+ else:
3312
+ expects_continue = False
3313
+
3314
+ # Return
3315
+
3316
+ return ParsedHttpRequest(
3317
+ method=method,
3318
+ path=path,
3319
+ expects_continue=expects_continue,
3320
+ **result_kwargs(),
3321
+ )
3322
+
3323
+ def parse(self, read_line: ta.Callable[[int], bytes]) -> ParseHttpRequestResult:
3324
+ return self._run_read_line_coro(self.coro_parse(), read_line)
3325
+
3326
+
3327
+ ########################################
3328
+ # ../../../omlish/io/buffers.py
3329
+
3330
+
3331
+ class DelimitingBuffer:
3332
+ """
3333
+ https://github.com/python-trio/trio/issues/796 :|
3334
+ """
3335
+
3336
+ #
3337
+
3338
+ class Error(Exception):
3339
+ def __init__(self, buffer: 'DelimitingBuffer') -> None:
3340
+ super().__init__(buffer)
3341
+ self.buffer = buffer
3342
+
3343
+ def __repr__(self) -> str:
3344
+ return attr_repr(self, 'buffer')
3345
+
3346
+ class ClosedError(Error):
3347
+ pass
3348
+
3349
+ #
3350
+
3351
+ DEFAULT_DELIMITERS: bytes = b'\n'
3352
+
3353
+ def __init__(
3354
+ self,
3355
+ delimiters: ta.Iterable[int] = DEFAULT_DELIMITERS,
3356
+ *,
3357
+ keep_ends: bool = False,
3358
+ max_size: ta.Optional[int] = None,
3359
+ ) -> None:
3360
+ super().__init__()
3361
+
3362
+ self._delimiters = frozenset(check.isinstance(d, int) for d in delimiters)
3363
+ self._keep_ends = keep_ends
3364
+ self._max_size = max_size
3365
+
3366
+ self._buf: ta.Optional[io.BytesIO] = io.BytesIO()
3367
+
3368
+ #
3369
+
3370
+ @property
3371
+ def is_closed(self) -> bool:
3372
+ return self._buf is None
3373
+
3374
+ def tell(self) -> int:
3375
+ if (buf := self._buf) is None:
3376
+ raise self.ClosedError(self)
3377
+ return buf.tell()
3378
+
3379
+ def peek(self) -> bytes:
3380
+ if (buf := self._buf) is None:
3381
+ raise self.ClosedError(self)
3382
+ return buf.getvalue()
3383
+
3384
+ def _find_delim(self, data: ta.Union[bytes, bytearray], i: int) -> ta.Optional[int]:
3385
+ r = None # type: int | None
3386
+ for d in self._delimiters:
3387
+ if (p := data.find(d, i)) >= 0:
3388
+ if r is None or p < r:
3389
+ r = p
3390
+ return r
3391
+
3392
+ def _append_and_reset(self, chunk: bytes) -> bytes:
3393
+ buf = check.not_none(self._buf)
3394
+ if not buf.tell():
3395
+ return chunk
3396
+
3397
+ buf.write(chunk)
3398
+ ret = buf.getvalue()
3399
+ buf.seek(0)
3400
+ buf.truncate()
3401
+ return ret
3402
+
3403
+ class Incomplete(ta.NamedTuple):
3404
+ b: bytes
3405
+
3406
+ def feed(self, data: ta.Union[bytes, bytearray]) -> ta.Generator[ta.Union[bytes, Incomplete], None, None]:
3407
+ if (buf := self._buf) is None:
3408
+ raise self.ClosedError(self)
3409
+
3410
+ if not data:
3411
+ self._buf = None
3412
+
3413
+ if buf.tell():
3414
+ yield self.Incomplete(buf.getvalue())
3415
+
3416
+ return
3417
+
3418
+ l = len(data)
3419
+ i = 0
3420
+ while i < l:
3421
+ if (p := self._find_delim(data, i)) is None:
3422
+ break
3423
+
3424
+ n = p + 1
3425
+ if self._keep_ends:
3426
+ p = n
3427
+
3428
+ yield self._append_and_reset(data[i:p])
3429
+
3430
+ i = n
3431
+
3432
+ if i >= l:
3433
+ return
3434
+
3435
+ if self._max_size is None:
3436
+ buf.write(data[i:])
3437
+ return
3438
+
3439
+ while i < l:
3440
+ remaining_data_len = l - i
3441
+ remaining_buf_capacity = self._max_size - buf.tell()
3442
+
3443
+ if remaining_data_len < remaining_buf_capacity:
3444
+ buf.write(data[i:])
3445
+ return
3446
+
3447
+ p = i + remaining_buf_capacity
3448
+ yield self.Incomplete(self._append_and_reset(data[i:p]))
3449
+ i = p
3450
+
3451
+
3452
+ class ReadableListBuffer:
3453
+ def __init__(self) -> None:
3454
+ super().__init__()
3455
+ self._lst: list[bytes] = []
3456
+
3457
+ def feed(self, d: bytes) -> None:
3458
+ if d:
3459
+ self._lst.append(d)
3460
+
3461
+ def _chop(self, i: int, e: int) -> bytes:
3462
+ lst = self._lst
3463
+ d = lst[i]
3464
+
3465
+ o = b''.join([
3466
+ *lst[:i],
3467
+ d[:e],
3468
+ ])
3469
+
3470
+ self._lst = [
3471
+ *([d[e:]] if e < len(d) else []),
3472
+ *lst[i + 1:],
3473
+ ]
3474
+
3475
+ return o
3476
+
3477
+ def read(self, n: ta.Optional[int] = None) -> ta.Optional[bytes]:
3478
+ if n is None:
3479
+ o = b''.join(self._lst)
3480
+ self._lst = []
3481
+ return o
3482
+
3483
+ if not (lst := self._lst):
3484
+ return None
3485
+
3486
+ c = 0
3487
+ for i, d in enumerate(lst):
3488
+ r = n - c
3489
+ if (l := len(d)) >= r:
3490
+ return self._chop(i, r)
3491
+ c += l
3492
+
3493
+ return None
3494
+
3495
+ def read_until(self, delim: bytes = b'\n') -> ta.Optional[bytes]:
3496
+ if not (lst := self._lst):
3497
+ return None
3498
+
3499
+ for i, d in enumerate(lst):
3500
+ if (p := d.find(delim)) >= 0:
3501
+ return self._chop(i, p + len(delim))
3502
+
3503
+ return None
3504
+
3505
+
3506
+ class IncrementalWriteBuffer:
3507
+ def __init__(
3508
+ self,
3509
+ data: bytes,
3510
+ *,
3511
+ write_size: int = 0x10000,
3512
+ ) -> None:
3513
+ super().__init__()
3514
+
3515
+ check.not_empty(data)
3516
+ self._len = len(data)
3517
+ self._write_size = write_size
3518
+
3519
+ self._lst = [
3520
+ data[i:i + write_size]
3521
+ for i in range(0, len(data), write_size)
3522
+ ]
3523
+ self._pos = 0
3524
+
3525
+ @property
3526
+ def rem(self) -> int:
3527
+ return self._len - self._pos
3528
+
3529
+ def write(self, fn: ta.Callable[[bytes], int]) -> int:
3530
+ lst = check.not_empty(self._lst)
3531
+
3532
+ t = 0
3533
+ for i, d in enumerate(lst): # noqa
3534
+ n = fn(check.not_empty(d))
3535
+ if not n:
3536
+ break
3537
+ t += n
3538
+
3539
+ if t:
3540
+ self._lst = [
3541
+ *([d[n:]] if n < len(d) else []),
3542
+ *lst[i + 1:],
3543
+ ]
3544
+ self._pos += t
3545
+
3546
+ return t
3547
+
3548
+
3549
+ ########################################
3550
+ # ../../../omlish/io/fdio/handlers.py
3551
+
3552
+
3553
+ class FdioHandler(abc.ABC):
3554
+ @abc.abstractmethod
3555
+ def fd(self) -> int:
3556
+ raise NotImplementedError
3557
+
3558
+ #
3559
+
3560
+ @property
3561
+ @abc.abstractmethod
3562
+ def closed(self) -> bool:
3563
+ raise NotImplementedError
3564
+
3565
+ @abc.abstractmethod
3566
+ def close(self) -> None:
3567
+ raise NotImplementedError
3568
+
3569
+ #
3570
+
3571
+ def readable(self) -> bool:
3572
+ return False
3573
+
3574
+ def writable(self) -> bool:
3575
+ return False
3576
+
3577
+ #
3578
+
3579
+ def on_readable(self) -> None:
3580
+ raise TypeError
3581
+
3582
+ def on_writable(self) -> None:
3583
+ raise TypeError
3584
+
3585
+ def on_error(self, exc: ta.Optional[BaseException] = None) -> None: # noqa
3586
+ pass
3587
+
3588
+
3589
+ class SocketFdioHandler(FdioHandler, abc.ABC):
3590
+ def __init__(
3591
+ self,
3592
+ addr: SocketAddress,
3593
+ sock: socket.socket,
3594
+ ) -> None:
3595
+ super().__init__()
3596
+
3597
+ self._addr = addr
3598
+ self._sock: ta.Optional[socket.socket] = sock
3599
+
3600
+ def fd(self) -> int:
3601
+ return check.not_none(self._sock).fileno()
3602
+
3603
+ @property
3604
+ def closed(self) -> bool:
3605
+ return self._sock is None
3606
+
3607
+ def close(self) -> None:
3608
+ if self._sock is not None:
3609
+ self._sock.close()
3610
+ self._sock = None
3611
+
3612
+
3613
+ ########################################
3614
+ # ../../../omlish/io/fdio/kqueue.py
3615
+
3616
+
3617
+ KqueueFdioPoller: ta.Optional[ta.Type[FdioPoller]]
3618
+ if sys.platform == 'darwin' or sys.platform.startswith('freebsd'):
3619
+
3620
+ class _KqueueFdioPoller(FdioPoller):
3621
+ DEFAULT_MAX_EVENTS = 1000
3622
+
3623
+ def __init__(
3624
+ self,
3625
+ *,
3626
+ max_events: int = DEFAULT_MAX_EVENTS,
3627
+ ) -> None:
3628
+ super().__init__()
3629
+
3630
+ self._max_events = max_events
3631
+
3632
+ self._kqueue: ta.Optional[ta.Any] = None
3633
+
3634
+ #
3635
+
3636
+ def _get_kqueue(self) -> 'select.kqueue':
3637
+ if (kq := self._kqueue) is not None:
3638
+ return kq
3639
+ kq = select.kqueue()
3640
+ self._kqueue = kq
3641
+ return kq
3642
+
3643
+ def close(self) -> None:
3644
+ if self._kqueue is not None:
3645
+ self._kqueue.close()
3646
+ self._kqueue = None
3647
+
3648
+ def reopen(self) -> None:
3649
+ for fd in self._readable:
3650
+ self._register_readable(fd)
3651
+ for fd in self._writable:
3652
+ self._register_writable(fd)
3653
+
3654
+ #
3655
+
3656
+ def _register_readable(self, fd: int) -> None:
3657
+ self._update_registration(fd, 'read', 'add')
3658
+
3659
+ def _register_writable(self, fd: int) -> None:
3660
+ self._update_registration(fd, 'write', 'add')
3661
+
3662
+ def _unregister_readable(self, fd: int) -> None:
3663
+ self._update_registration(fd, 'read', 'del')
3664
+
3665
+ def _unregister_writable(self, fd: int) -> None:
3666
+ self._update_registration(fd, 'write', 'del')
3667
+
3668
+ #
3669
+
3670
+ _CONTROL_FILTER_BY_READ_OR_WRITE: ta.ClassVar[ta.Mapping[ta.Literal['read', 'write'], int]] = {
3671
+ 'read': select.KQ_FILTER_READ,
3672
+ 'write': select.KQ_FILTER_WRITE,
3673
+ }
3674
+
3675
+ _CONTROL_FLAGS_BY_ADD_OR_DEL: ta.ClassVar[ta.Mapping[ta.Literal['add', 'del'], int]] = {
3676
+ 'add': select.KQ_EV_ADD,
3677
+ 'del': select.KQ_EV_DELETE,
3678
+ }
3679
+
3680
+ def _update_registration(
3681
+ self,
3682
+ fd: int,
3683
+ read_or_write: ta.Literal['read', 'write'],
3684
+ add_or_del: ta.Literal['add', 'del'],
3685
+ ) -> None: # noqa
3686
+ ke = select.kevent(
3687
+ fd,
3688
+ filter=self._CONTROL_FILTER_BY_READ_OR_WRITE[read_or_write],
3689
+ flags=self._CONTROL_FLAGS_BY_ADD_OR_DEL[add_or_del],
3690
+ )
3691
+ kq = self._get_kqueue()
3692
+ try:
3693
+ kq.control([ke], 0)
3694
+
3695
+ except OSError as exc:
3696
+ if exc.errno == errno.EBADF:
3697
+ # log.debug('EBADF encountered in kqueue. Invalid file descriptor %s', ke.ident)
3698
+ pass
3699
+ elif exc.errno == errno.ENOENT:
3700
+ # Can happen when trying to remove an already closed socket
3701
+ if add_or_del == 'add':
3702
+ raise
3703
+ else:
3704
+ raise
3705
+
3706
+ #
3707
+
3708
+ def poll(self, timeout: ta.Optional[float]) -> FdioPoller.PollResult:
3709
+ kq = self._get_kqueue()
3710
+ try:
3711
+ kes = kq.control(None, self._max_events, timeout)
3712
+
3713
+ except OSError as exc:
3714
+ if exc.errno == errno.EINTR:
3715
+ return FdioPoller.PollResult(msg='EINTR encountered in poll', exc=exc)
3716
+ else:
3717
+ raise
3718
+
3719
+ r: ta.List[int] = []
3720
+ w: ta.List[int] = []
3721
+ for ke in kes:
3722
+ if ke.filter == select.KQ_FILTER_READ:
3723
+ r.append(ke.ident)
3724
+ if ke.filter == select.KQ_FILTER_WRITE:
3725
+ w.append(ke.ident)
3726
+
3727
+ return FdioPoller.PollResult(r, w)
3728
+
3729
+ KqueueFdioPoller = _KqueueFdioPoller
3730
+ else:
3731
+ KqueueFdioPoller = None
3732
+
3733
+
3734
+ ########################################
3735
+ # ../../../omlish/lite/contextmanagers.py
3736
+
3737
+
3738
+ ##
3739
+
3740
+
3741
+ class ExitStacked:
3742
+ _exit_stack: ta.Optional[contextlib.ExitStack] = None
3743
+
3744
+ def __enter__(self: ExitStackedT) -> ExitStackedT:
3745
+ check.state(self._exit_stack is None)
3746
+ es = self._exit_stack = contextlib.ExitStack()
3747
+ es.__enter__()
3748
+ return self
3749
+
3750
+ def __exit__(self, exc_type, exc_val, exc_tb):
3751
+ if (es := self._exit_stack) is None:
3752
+ return None
3753
+ self._exit_contexts()
3754
+ return es.__exit__(exc_type, exc_val, exc_tb)
3755
+
3756
+ def _exit_contexts(self) -> None:
3757
+ pass
3758
+
3759
+ def _enter_context(self, cm: ta.ContextManager[T]) -> T:
3760
+ es = check.not_none(self._exit_stack)
3761
+ return es.enter_context(cm)
3762
+
3763
+
3764
+ ##
3186
3765
 
3187
- expect = headers.get('Expect', '')
3188
- if (
3189
- expect.lower() == '100-continue' and
3190
- version >= HttpProtocolVersions.HTTP_1_1
3191
- ):
3192
- expects_continue = True
3193
- else:
3194
- expects_continue = False
3195
3766
 
3196
- # Return
3767
+ @contextlib.contextmanager
3768
+ def defer(fn: ta.Callable) -> ta.Generator[ta.Callable, None, None]:
3769
+ try:
3770
+ yield fn
3771
+ finally:
3772
+ fn()
3197
3773
 
3198
- return ParsedHttpRequest(
3199
- method=method,
3200
- path=path,
3201
- expects_continue=expects_continue,
3202
- **result_kwargs(),
3203
- )
3204
3774
 
3205
- def parse(self, read_line: ta.Callable[[int], bytes]) -> ParseHttpRequestResult:
3206
- return self._run_read_line_coro(self.coro_parse(), read_line)
3775
+ @contextlib.contextmanager
3776
+ def attr_setting(obj, attr, val, *, default=None): # noqa
3777
+ not_set = object()
3778
+ orig = getattr(obj, attr, not_set)
3779
+ try:
3780
+ setattr(obj, attr, val)
3781
+ if orig is not not_set:
3782
+ yield orig
3783
+ else:
3784
+ yield default
3785
+ finally:
3786
+ if orig is not_set:
3787
+ delattr(obj, attr)
3788
+ else:
3789
+ setattr(obj, attr, orig)
3207
3790
 
3208
3791
 
3209
3792
  ########################################
@@ -3350,7 +3933,7 @@ class FnInjectorProvider(InjectorProvider):
3350
3933
  fn: ta.Any
3351
3934
 
3352
3935
  def __post_init__(self) -> None:
3353
- check_not_isinstance(self.fn, type)
3936
+ check.not_isinstance(self.fn, type)
3354
3937
 
3355
3938
  def provider_fn(self) -> InjectorProviderFn:
3356
3939
  def pfn(i: Injector) -> ta.Any:
@@ -3364,7 +3947,7 @@ class CtorInjectorProvider(InjectorProvider):
3364
3947
  cls_: type
3365
3948
 
3366
3949
  def __post_init__(self) -> None:
3367
- check_isinstance(self.cls_, type)
3950
+ check.isinstance(self.cls_, type)
3368
3951
 
3369
3952
  def provider_fn(self) -> InjectorProviderFn:
3370
3953
  def pfn(i: Injector) -> ta.Any:
@@ -3386,7 +3969,7 @@ class SingletonInjectorProvider(InjectorProvider):
3386
3969
  p: InjectorProvider
3387
3970
 
3388
3971
  def __post_init__(self) -> None:
3389
- check_isinstance(self.p, InjectorProvider)
3972
+ check.isinstance(self.p, InjectorProvider)
3390
3973
 
3391
3974
  def provider_fn(self) -> InjectorProviderFn:
3392
3975
  v = not_set = object()
@@ -3406,7 +3989,7 @@ class LinkInjectorProvider(InjectorProvider):
3406
3989
  k: InjectorKey
3407
3990
 
3408
3991
  def __post_init__(self) -> None:
3409
- check_isinstance(self.k, InjectorKey)
3992
+ check.isinstance(self.k, InjectorKey)
3410
3993
 
3411
3994
  def provider_fn(self) -> InjectorProviderFn:
3412
3995
  def pfn(i: Injector) -> ta.Any:
@@ -3603,7 +4186,7 @@ def build_injection_kwargs_target(
3603
4186
 
3604
4187
  skip_names: ta.Set[str] = set()
3605
4188
  if skip_kwargs is not None:
3606
- skip_names.update(check_not_isinstance(skip_kwargs, str))
4189
+ skip_names.update(check.not_isinstance(skip_kwargs, str))
3607
4190
 
3608
4191
  seen: ta.Set[InjectorKey] = set()
3609
4192
  kws: ta.List[InjectionKwarg] = []
@@ -3664,8 +4247,8 @@ class _Injector(Injector):
3664
4247
  def __init__(self, bs: InjectorBindings, p: ta.Optional[Injector] = None) -> None:
3665
4248
  super().__init__()
3666
4249
 
3667
- self._bs = check_isinstance(bs, InjectorBindings)
3668
- self._p: ta.Optional[Injector] = check_isinstance(p, (Injector, type(None)))
4250
+ self._bs = check.isinstance(bs, InjectorBindings)
4251
+ self._p: ta.Optional[Injector] = check.isinstance(p, (Injector, type(None)))
3669
4252
 
3670
4253
  self._pfm = {k: v.provider_fn() for k, v in build_injector_provider_map(bs).items()}
3671
4254
 
@@ -3696,8 +4279,8 @@ class _Injector(Injector):
3696
4279
  return Maybe.empty()
3697
4280
 
3698
4281
  def handle_provision(self, key: InjectorKey, mv: Maybe) -> Maybe:
3699
- check_in(key, self._seen_keys)
3700
- check_not_in(key, self._provisions)
4282
+ check.in_(key, self._seen_keys)
4283
+ check.not_in(key, self._provisions)
3701
4284
  self._provisions[key] = mv
3702
4285
  return mv
3703
4286
 
@@ -3811,7 +4394,7 @@ class InjectorBinder:
3811
4394
 
3812
4395
  @classmethod
3813
4396
  def bind_as_fn(cls, icls: ta.Type[T]) -> ta.Type[T]:
3814
- check_isinstance(icls, type)
4397
+ check.isinstance(icls, type)
3815
4398
  if icls not in cls._FN_TYPES:
3816
4399
  cls._FN_TYPES = (*cls._FN_TYPES, icls)
3817
4400
  return icls
@@ -3868,7 +4451,7 @@ class InjectorBinder:
3868
4451
  to_fn = obj
3869
4452
  if key is None:
3870
4453
  insp = _injection_inspect(obj)
3871
- key_cls: ta.Any = check_valid_injector_key_cls(check_not_none(insp.type_hints.get('return')))
4454
+ key_cls: ta.Any = check_valid_injector_key_cls(check.not_none(insp.type_hints.get('return')))
3872
4455
  key = InjectorKey(key_cls)
3873
4456
  else:
3874
4457
  if to_const is not None:
@@ -4099,228 +4682,6 @@ class Injection:
4099
4682
  inj = Injection
4100
4683
 
4101
4684
 
4102
- ########################################
4103
- # ../../../omlish/lite/io.py
4104
-
4105
-
4106
- class DelimitingBuffer:
4107
- """
4108
- https://github.com/python-trio/trio/issues/796 :|
4109
- """
4110
-
4111
- #
4112
-
4113
- class Error(Exception):
4114
- def __init__(self, buffer: 'DelimitingBuffer') -> None:
4115
- super().__init__(buffer)
4116
- self.buffer = buffer
4117
-
4118
- def __repr__(self) -> str:
4119
- return attr_repr(self, 'buffer')
4120
-
4121
- class ClosedError(Error):
4122
- pass
4123
-
4124
- #
4125
-
4126
- DEFAULT_DELIMITERS: bytes = b'\n'
4127
-
4128
- def __init__(
4129
- self,
4130
- delimiters: ta.Iterable[int] = DEFAULT_DELIMITERS,
4131
- *,
4132
- keep_ends: bool = False,
4133
- max_size: ta.Optional[int] = None,
4134
- ) -> None:
4135
- super().__init__()
4136
-
4137
- self._delimiters = frozenset(check_isinstance(d, int) for d in delimiters)
4138
- self._keep_ends = keep_ends
4139
- self._max_size = max_size
4140
-
4141
- self._buf: ta.Optional[io.BytesIO] = io.BytesIO()
4142
-
4143
- #
4144
-
4145
- @property
4146
- def is_closed(self) -> bool:
4147
- return self._buf is None
4148
-
4149
- def tell(self) -> int:
4150
- if (buf := self._buf) is None:
4151
- raise self.ClosedError(self)
4152
- return buf.tell()
4153
-
4154
- def peek(self) -> bytes:
4155
- if (buf := self._buf) is None:
4156
- raise self.ClosedError(self)
4157
- return buf.getvalue()
4158
-
4159
- def _find_delim(self, data: ta.Union[bytes, bytearray], i: int) -> ta.Optional[int]:
4160
- r = None # type: int | None
4161
- for d in self._delimiters:
4162
- if (p := data.find(d, i)) >= 0:
4163
- if r is None or p < r:
4164
- r = p
4165
- return r
4166
-
4167
- def _append_and_reset(self, chunk: bytes) -> bytes:
4168
- buf = check_not_none(self._buf)
4169
- if not buf.tell():
4170
- return chunk
4171
-
4172
- buf.write(chunk)
4173
- ret = buf.getvalue()
4174
- buf.seek(0)
4175
- buf.truncate()
4176
- return ret
4177
-
4178
- class Incomplete(ta.NamedTuple):
4179
- b: bytes
4180
-
4181
- def feed(self, data: ta.Union[bytes, bytearray]) -> ta.Generator[ta.Union[bytes, Incomplete], None, None]:
4182
- if (buf := self._buf) is None:
4183
- raise self.ClosedError(self)
4184
-
4185
- if not data:
4186
- self._buf = None
4187
-
4188
- if buf.tell():
4189
- yield self.Incomplete(buf.getvalue())
4190
-
4191
- return
4192
-
4193
- l = len(data)
4194
- i = 0
4195
- while i < l:
4196
- if (p := self._find_delim(data, i)) is None:
4197
- break
4198
-
4199
- n = p + 1
4200
- if self._keep_ends:
4201
- p = n
4202
-
4203
- yield self._append_and_reset(data[i:p])
4204
-
4205
- i = n
4206
-
4207
- if i >= l:
4208
- return
4209
-
4210
- if self._max_size is None:
4211
- buf.write(data[i:])
4212
- return
4213
-
4214
- while i < l:
4215
- remaining_data_len = l - i
4216
- remaining_buf_capacity = self._max_size - buf.tell()
4217
-
4218
- if remaining_data_len < remaining_buf_capacity:
4219
- buf.write(data[i:])
4220
- return
4221
-
4222
- p = i + remaining_buf_capacity
4223
- yield self.Incomplete(self._append_and_reset(data[i:p]))
4224
- i = p
4225
-
4226
-
4227
- class ReadableListBuffer:
4228
- def __init__(self) -> None:
4229
- super().__init__()
4230
- self._lst: list[bytes] = []
4231
-
4232
- def feed(self, d: bytes) -> None:
4233
- if d:
4234
- self._lst.append(d)
4235
-
4236
- def _chop(self, i: int, e: int) -> bytes:
4237
- lst = self._lst
4238
- d = lst[i]
4239
-
4240
- o = b''.join([
4241
- *lst[:i],
4242
- d[:e],
4243
- ])
4244
-
4245
- self._lst = [
4246
- *([d[e:]] if e < len(d) else []),
4247
- *lst[i + 1:],
4248
- ]
4249
-
4250
- return o
4251
-
4252
- def read(self, n: ta.Optional[int] = None) -> ta.Optional[bytes]:
4253
- if n is None:
4254
- o = b''.join(self._lst)
4255
- self._lst = []
4256
- return o
4257
-
4258
- if not (lst := self._lst):
4259
- return None
4260
-
4261
- c = 0
4262
- for i, d in enumerate(lst):
4263
- r = n - c
4264
- if (l := len(d)) >= r:
4265
- return self._chop(i, r)
4266
- c += l
4267
-
4268
- return None
4269
-
4270
- def read_until(self, delim: bytes = b'\n') -> ta.Optional[bytes]:
4271
- if not (lst := self._lst):
4272
- return None
4273
-
4274
- for i, d in enumerate(lst):
4275
- if (p := d.find(delim)) >= 0:
4276
- return self._chop(i, p + len(delim))
4277
-
4278
- return None
4279
-
4280
-
4281
- class IncrementalWriteBuffer:
4282
- def __init__(
4283
- self,
4284
- data: bytes,
4285
- *,
4286
- write_size: int = 0x10000,
4287
- ) -> None:
4288
- super().__init__()
4289
-
4290
- check_non_empty(data)
4291
- self._len = len(data)
4292
- self._write_size = write_size
4293
-
4294
- self._lst = [
4295
- data[i:i + write_size]
4296
- for i in range(0, len(data), write_size)
4297
- ]
4298
- self._pos = 0
4299
-
4300
- @property
4301
- def rem(self) -> int:
4302
- return self._len - self._pos
4303
-
4304
- def write(self, fn: ta.Callable[[bytes], int]) -> int:
4305
- lst = check_non_empty(self._lst)
4306
-
4307
- t = 0
4308
- for i, d in enumerate(lst): # noqa
4309
- n = fn(check_non_empty(d))
4310
- if not n:
4311
- break
4312
- t += n
4313
-
4314
- if t:
4315
- self._lst = [
4316
- *([d[n:]] if n < len(d) else []),
4317
- *lst[i + 1:],
4318
- ]
4319
- self._pos += t
4320
-
4321
- return t
4322
-
4323
-
4324
4685
  ########################################
4325
4686
  # ../../../omlish/lite/journald.py
4326
4687
 
@@ -4789,10 +5150,10 @@ class ProxyObjMarshaler(ObjMarshaler):
4789
5150
  m: ta.Optional[ObjMarshaler] = None
4790
5151
 
4791
5152
  def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
4792
- return check_not_none(self.m).marshal(o, ctx)
5153
+ return check.not_none(self.m).marshal(o, ctx)
4793
5154
 
4794
5155
  def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
4795
- return check_not_none(self.m).unmarshal(o, ctx)
5156
+ return check.not_none(self.m).unmarshal(o, ctx)
4796
5157
 
4797
5158
 
4798
5159
  @dc.dataclass(frozen=True)
@@ -4951,19 +5312,19 @@ class DatetimeObjMarshaler(ObjMarshaler):
4951
5312
 
4952
5313
  class DecimalObjMarshaler(ObjMarshaler):
4953
5314
  def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
4954
- return str(check_isinstance(o, decimal.Decimal))
5315
+ return str(check.isinstance(o, decimal.Decimal))
4955
5316
 
4956
5317
  def unmarshal(self, v: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
4957
- return decimal.Decimal(check_isinstance(v, str))
5318
+ return decimal.Decimal(check.isinstance(v, str))
4958
5319
 
4959
5320
 
4960
5321
  class FractionObjMarshaler(ObjMarshaler):
4961
5322
  def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
4962
- fr = check_isinstance(o, fractions.Fraction)
5323
+ fr = check.isinstance(o, fractions.Fraction)
4963
5324
  return [fr.numerator, fr.denominator]
4964
5325
 
4965
5326
  def unmarshal(self, v: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
4966
- num, denom = check_isinstance(v, list)
5327
+ num, denom = check.isinstance(v, list)
4967
5328
  return fractions.Fraction(num, denom)
4968
5329
 
4969
5330
 
@@ -5265,7 +5626,7 @@ def build_config_named_children(
5265
5626
  lst: ta.List[ConfigMapping] = []
5266
5627
  if isinstance(o, ta.Mapping):
5267
5628
  for k, v in o.items():
5268
- check_isinstance(v, ta.Mapping)
5629
+ check.isinstance(v, ta.Mapping)
5269
5630
  if name_key in v:
5270
5631
  n = v[name_key]
5271
5632
  if k != n:
@@ -5275,7 +5636,7 @@ def build_config_named_children(
5275
5636
  lst.append({name_key: k, **v})
5276
5637
 
5277
5638
  else:
5278
- check_not_isinstance(o, str)
5639
+ check.not_isinstance(o, str)
5279
5640
  lst.extend(o)
5280
5641
 
5281
5642
  seen = set()
@@ -5406,7 +5767,7 @@ class SupervisorSetup(abc.ABC):
5406
5767
 
5407
5768
 
5408
5769
  ########################################
5409
- # ../../../omlish/lite/http/handlers.py
5770
+ # ../../../omlish/http/handlers.py
5410
5771
 
5411
5772
 
5412
5773
  @dc.dataclass(frozen=True)
@@ -5581,7 +5942,7 @@ def parse_logging_level(value: ta.Union[str, int]) -> int:
5581
5942
 
5582
5943
 
5583
5944
  ########################################
5584
- # ../../../omlish/lite/http/coroserver.py
5945
+ # ../../../omlish/http/coroserver.py
5585
5946
  # PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
5586
5947
  # --------------------------------------------
5587
5948
  #
@@ -5961,13 +6322,13 @@ class CoroHttpServer:
5961
6322
  yield o
5962
6323
 
5963
6324
  elif isinstance(o, self.AnyReadIo):
5964
- i = check_isinstance((yield o), bytes)
6325
+ i = check.isinstance((yield o), bytes)
5965
6326
 
5966
6327
  elif isinstance(o, self._Response):
5967
6328
  i = None
5968
6329
  r = self._preprocess_response(o)
5969
6330
  b = self._build_response_bytes(r)
5970
- check_none((yield self.WriteIo(b)))
6331
+ check.none((yield self.WriteIo(b)))
5971
6332
 
5972
6333
  else:
5973
6334
  raise TypeError(o)
@@ -5990,7 +6351,7 @@ class CoroHttpServer:
5990
6351
  sz = next(gen)
5991
6352
  while True:
5992
6353
  try:
5993
- line = check_isinstance((yield self.ReadLineIo(sz)), bytes)
6354
+ line = check.isinstance((yield self.ReadLineIo(sz)), bytes)
5994
6355
  sz = gen.send(line)
5995
6356
  except StopIteration as e:
5996
6357
  parsed = e.value
@@ -6009,11 +6370,11 @@ class CoroHttpServer:
6009
6370
  yield self._build_error_response(err)
6010
6371
  return
6011
6372
 
6012
- parsed = check_isinstance(parsed, ParsedHttpRequest)
6373
+ parsed = check.isinstance(parsed, ParsedHttpRequest)
6013
6374
 
6014
6375
  # Log
6015
6376
 
6016
- check_none((yield self.ParsedRequestLogIo(parsed)))
6377
+ check.none((yield self.ParsedRequestLogIo(parsed)))
6017
6378
 
6018
6379
  # Handle CONTINUE
6019
6380
 
@@ -6029,7 +6390,7 @@ class CoroHttpServer:
6029
6390
 
6030
6391
  request_data: ta.Optional[bytes]
6031
6392
  if (cl := parsed.headers.get('Content-Length')) is not None:
6032
- request_data = check_isinstance((yield self.ReadIo(int(cl))), bytes)
6393
+ request_data = check.isinstance((yield self.ReadIo(int(cl))), bytes)
6033
6394
  else:
6034
6395
  request_data = None
6035
6396
 
@@ -6037,7 +6398,7 @@ class CoroHttpServer:
6037
6398
 
6038
6399
  handler_request = HttpHandlerRequest(
6039
6400
  client_address=self._client_address,
6040
- method=check_not_none(parsed.method),
6401
+ method=check.not_none(parsed.method),
6041
6402
  path=parsed.path,
6042
6403
  headers=parsed.headers,
6043
6404
  data=request_data,
@@ -6321,7 +6682,7 @@ class ProcessGroup(
6321
6682
 
6322
6683
 
6323
6684
  ########################################
6324
- # ../../../omlish/lite/fdio/corohttp.py
6685
+ # ../../../omlish/io/fdio/corohttp.py
6325
6686
 
6326
6687
 
6327
6688
  class CoroHttpServerConnectionFdioHandler(SocketFdioHandler):
@@ -6335,7 +6696,7 @@ class CoroHttpServerConnectionFdioHandler(SocketFdioHandler):
6335
6696
  write_size: int = 0x10000,
6336
6697
  log_handler: ta.Optional[ta.Callable[[CoroHttpServer, CoroHttpServer.AnyLogIo], None]] = None,
6337
6698
  ) -> None:
6338
- check_state(not sock.getblocking())
6699
+ check.state(not sock.getblocking())
6339
6700
 
6340
6701
  super().__init__(addr, sock)
6341
6702
 
@@ -6359,7 +6720,7 @@ class CoroHttpServerConnectionFdioHandler(SocketFdioHandler):
6359
6720
  #
6360
6721
 
6361
6722
  def _next_io(self) -> None: # noqa
6362
- coro = check_not_none(self._srv_coro)
6723
+ coro = check.not_none(self._srv_coro)
6363
6724
 
6364
6725
  d: bytes | None = None
6365
6726
  o = self._cur_io
@@ -6392,7 +6753,7 @@ class CoroHttpServerConnectionFdioHandler(SocketFdioHandler):
6392
6753
  o = None
6393
6754
 
6394
6755
  elif isinstance(o, CoroHttpServer.WriteIo):
6395
- check_none(self._write_buf)
6756
+ check.none(self._write_buf)
6396
6757
  self._write_buf = IncrementalWriteBuffer(o.data, write_size=self._write_size)
6397
6758
  break
6398
6759
 
@@ -6413,7 +6774,7 @@ class CoroHttpServerConnectionFdioHandler(SocketFdioHandler):
6413
6774
 
6414
6775
  def on_readable(self) -> None:
6415
6776
  try:
6416
- buf = check_not_none(self._sock).recv(self._read_size)
6777
+ buf = check.not_none(self._sock).recv(self._read_size)
6417
6778
  except BlockingIOError:
6418
6779
  return
6419
6780
  except ConnectionResetError:
@@ -6429,12 +6790,12 @@ class CoroHttpServerConnectionFdioHandler(SocketFdioHandler):
6429
6790
  self._next_io()
6430
6791
 
6431
6792
  def on_writable(self) -> None:
6432
- check_isinstance(self._cur_io, CoroHttpServer.WriteIo)
6433
- wb = check_not_none(self._write_buf)
6793
+ check.isinstance(self._cur_io, CoroHttpServer.WriteIo)
6794
+ wb = check.not_none(self._write_buf)
6434
6795
  while wb.rem > 0:
6435
6796
  def send(d: bytes) -> int:
6436
6797
  try:
6437
- return check_not_none(self._sock).send(d)
6798
+ return check.not_none(self._sock).send(d)
6438
6799
  except ConnectionResetError:
6439
6800
  self.close()
6440
6801
  return 0
@@ -6827,7 +7188,7 @@ class ProcessGroupImpl(ProcessGroup):
6827
7188
 
6828
7189
  by_name: ta.Dict[str, Process] = {}
6829
7190
  for pconfig in self._config.processes or []:
6830
- p = check_isinstance(self._process_factory(pconfig, self), Process)
7191
+ p = check.isinstance(self._process_factory(pconfig, self), Process)
6831
7192
  if p.name in by_name:
6832
7193
  raise KeyError(f'name {p.name} of process {p} already registered by {by_name[p.name]}')
6833
7194
  by_name[pconfig.name] = p
@@ -7380,7 +7741,7 @@ class SocketServerFdioHandler(SocketFdioHandler):
7380
7741
  return True
7381
7742
 
7382
7743
  def on_readable(self) -> None:
7383
- cli_sock, cli_addr = check_not_none(self._sock).accept()
7744
+ cli_sock, cli_addr = check.not_none(self._sock).accept()
7384
7745
  cli_sock.setblocking(False)
7385
7746
 
7386
7747
  self._on_connect(cli_sock, cli_addr)
@@ -7619,7 +7980,7 @@ class ProcessImpl(Process):
7619
7980
  if stdin_fd is None:
7620
7981
  raise OSError(errno.EPIPE, 'Process has no stdin channel')
7621
7982
 
7622
- dispatcher = check_isinstance(self._dispatchers[stdin_fd], ProcessInputDispatcher)
7983
+ dispatcher = check.isinstance(self._dispatchers[stdin_fd], ProcessInputDispatcher)
7623
7984
  if dispatcher.closed:
7624
7985
  raise OSError(errno.EPIPE, "Process' stdin channel is closed")
7625
7986
 
@@ -8178,21 +8539,21 @@ class ProcessSpawningImpl(ProcessSpawning):
8178
8539
  dispatchers: ta.List[FdioHandler] = []
8179
8540
 
8180
8541
  if pipes.stdout is not None:
8181
- dispatchers.append(check_isinstance(self._output_dispatcher_factory(
8542
+ dispatchers.append(check.isinstance(self._output_dispatcher_factory(
8182
8543
  self.process,
8183
8544
  ProcessCommunicationStdoutEvent,
8184
8545
  pipes.stdout,
8185
8546
  ), ProcessOutputDispatcher))
8186
8547
 
8187
8548
  if pipes.stderr is not None:
8188
- dispatchers.append(check_isinstance(self._output_dispatcher_factory(
8549
+ dispatchers.append(check.isinstance(self._output_dispatcher_factory(
8189
8550
  self.process,
8190
8551
  ProcessCommunicationStderrEvent,
8191
8552
  pipes.stderr,
8192
8553
  ), ProcessOutputDispatcher))
8193
8554
 
8194
8555
  if pipes.stdin is not None:
8195
- dispatchers.append(check_isinstance(self._input_dispatcher_factory(
8556
+ dispatchers.append(check.isinstance(self._input_dispatcher_factory(
8196
8557
  self.process,
8197
8558
  'stdin',
8198
8559
  pipes.stdin,
@@ -8282,14 +8643,14 @@ class ProcessSpawningImpl(ProcessSpawning):
8282
8643
  raise RuntimeError('Unreachable')
8283
8644
 
8284
8645
  def _prepare_child_fds(self, pipes: ProcessPipes) -> None:
8285
- os.dup2(check_not_none(pipes.child_stdin), 0)
8646
+ os.dup2(check.not_none(pipes.child_stdin), 0)
8286
8647
 
8287
- os.dup2(check_not_none(pipes.child_stdout), 1)
8648
+ os.dup2(check.not_none(pipes.child_stdout), 1)
8288
8649
 
8289
8650
  if self.config.redirect_stderr:
8290
- os.dup2(check_not_none(pipes.child_stdout), 2)
8651
+ os.dup2(check.not_none(pipes.child_stdout), 2)
8291
8652
  else:
8292
- os.dup2(check_not_none(pipes.child_stderr), 2)
8653
+ os.dup2(check.not_none(pipes.child_stderr), 2)
8293
8654
 
8294
8655
  for i in range(3, self._server_config.min_fds):
8295
8656
  if i in self._inherited_fds:
@@ -8405,7 +8766,7 @@ class Supervisor:
8405
8766
  if self._process_groups.get(config.name) is not None:
8406
8767
  return False
8407
8768
 
8408
- group = check_isinstance(self._process_group_factory(config), ProcessGroup)
8769
+ group = check.isinstance(self._process_group_factory(config), ProcessGroup)
8409
8770
  for process in group:
8410
8771
  process.after_setuid()
8411
8772