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.
- ominfra/clouds/aws/auth.py +7 -9
- ominfra/clouds/aws/cli.py +1 -1
- ominfra/clouds/aws/journald2aws/driver.py +4 -4
- ominfra/clouds/aws/logs.py +4 -5
- ominfra/clouds/gcp/auth.py +1 -1
- ominfra/configs.py +3 -4
- ominfra/journald/messages.py +3 -3
- ominfra/journald/tailer.py +2 -2
- ominfra/manage/commands/base.py +2 -2
- ominfra/manage/commands/interp.py +3 -3
- ominfra/manage/commands/subprocess.py +3 -4
- ominfra/manage/deploy/paths.py +12 -15
- ominfra/manage/main.py +72 -75
- ominfra/manage/remote/_main.py +6 -7
- ominfra/manage/remote/execution.py +7 -10
- ominfra/manage/remote/spawning.py +3 -3
- ominfra/scripts/journald2aws.py +508 -147
- ominfra/scripts/manage.py +772 -183
- ominfra/scripts/supervisor.py +1144 -783
- ominfra/supervisor/dispatchers.py +1 -1
- ominfra/supervisor/groupsimpl.py +2 -2
- ominfra/supervisor/http.py +7 -7
- ominfra/supervisor/inject.py +4 -4
- ominfra/supervisor/io.py +1 -1
- ominfra/supervisor/main.py +1 -1
- ominfra/supervisor/processimpl.py +2 -2
- ominfra/supervisor/spawningimpl.py +9 -10
- ominfra/supervisor/supervisor.py +3 -3
- ominfra/supervisor/types.py +1 -1
- ominfra/tailscale/cli.py +1 -1
- {ominfra-0.0.0.dev148.dist-info → ominfra-0.0.0.dev150.dist-info}/METADATA +3 -3
- {ominfra-0.0.0.dev148.dist-info → ominfra-0.0.0.dev150.dist-info}/RECORD +36 -36
- {ominfra-0.0.0.dev148.dist-info → ominfra-0.0.0.dev150.dist-info}/LICENSE +0 -0
- {ominfra-0.0.0.dev148.dist-info → ominfra-0.0.0.dev150.dist-info}/WHEEL +0 -0
- {ominfra-0.0.0.dev148.dist-info → ominfra-0.0.0.dev150.dist-info}/entry_points.txt +0 -0
- {ominfra-0.0.0.dev148.dist-info → ominfra-0.0.0.dev150.dist-info}/top_level.txt +0 -0
ominfra/scripts/supervisor.py
CHANGED
@@ -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/
|
144
|
+
# ../../omlish/http/handlers.py
|
139
145
|
HttpHandler = ta.Callable[['HttpHandlerRequest'], 'HttpHandlerResponse']
|
140
146
|
|
141
|
-
# ../../omlish/
|
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/
|
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
|
1575
|
-
|
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
|
-
|
1581
|
-
|
1582
|
-
|
1583
|
-
|
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/
|
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/
|
1798
|
-
|
1669
|
+
# ../../../omlish/lite/cached.py
|
1799
1670
|
|
1800
|
-
class HttpProtocolVersion(ta.NamedTuple):
|
1801
|
-
major: int
|
1802
|
-
minor: int
|
1803
1671
|
|
1804
|
-
|
1805
|
-
return f'HTTP/{self.major}.{self.minor}'
|
1672
|
+
##
|
1806
1673
|
|
1807
1674
|
|
1808
|
-
class
|
1809
|
-
|
1810
|
-
|
1811
|
-
|
1812
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
1829
|
-
|
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
|
-
|
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
|
-
|
1843
|
-
|
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/
|
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
|
-
|
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
|
-
|
1861
|
-
def
|
1862
|
-
|
1737
|
+
class Checks:
|
1738
|
+
def __init__(self) -> None:
|
1739
|
+
super().__init__()
|
1863
1740
|
|
1864
|
-
|
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
|
-
@
|
1867
|
-
def
|
1868
|
-
return
|
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
|
-
|
1872
|
-
|
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
|
1875
|
-
|
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
|
-
|
1878
|
-
def present(self) -> bool:
|
1879
|
-
return bool(self)
|
1761
|
+
#
|
1880
1762
|
|
1881
|
-
def
|
1882
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
1895
|
-
|
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
|
-
|
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
|
-
|
1908
|
-
|
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
|
-
|
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
|
-
|
1921
|
-
|
1922
|
-
|
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
|
-
|
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
|
1934
|
-
|
1935
|
-
|
1936
|
-
|
1937
|
-
|
1938
|
-
if
|
1939
|
-
|
1940
|
-
|
1941
|
-
|
1942
|
-
|
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
|
-
|
1947
|
-
|
1948
|
-
|
1949
|
-
|
1950
|
-
|
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/
|
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
|
-
|
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
|
-
|
3206
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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(
|
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 =
|
3668
|
-
self._p: ta.Optional[Injector] =
|
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
|
-
|
3700
|
-
|
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
|
-
|
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(
|
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
|
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
|
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(
|
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(
|
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 =
|
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 =
|
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
|
-
|
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
|
-
|
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/
|
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/
|
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 =
|
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
|
-
|
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 =
|
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 =
|
6373
|
+
parsed = check.isinstance(parsed, ParsedHttpRequest)
|
6013
6374
|
|
6014
6375
|
# Log
|
6015
6376
|
|
6016
|
-
|
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 =
|
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=
|
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/
|
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
|
-
|
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 =
|
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
|
-
|
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 =
|
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
|
-
|
6433
|
-
wb =
|
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
|
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 =
|
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 =
|
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 =
|
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(
|
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(
|
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(
|
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(
|
8646
|
+
os.dup2(check.not_none(pipes.child_stdin), 0)
|
8286
8647
|
|
8287
|
-
os.dup2(
|
8648
|
+
os.dup2(check.not_none(pipes.child_stdout), 1)
|
8288
8649
|
|
8289
8650
|
if self.config.redirect_stderr:
|
8290
|
-
os.dup2(
|
8651
|
+
os.dup2(check.not_none(pipes.child_stdout), 2)
|
8291
8652
|
else:
|
8292
|
-
os.dup2(
|
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 =
|
8769
|
+
group = check.isinstance(self._process_group_factory(config), ProcessGroup)
|
8409
8770
|
for process in group:
|
8410
8771
|
process.after_setuid()
|
8411
8772
|
|