ominfra 0.0.0.dev438__py3-none-any.whl → 0.0.0.dev483__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ominfra might be problematic. Click here for more details.
- ominfra/clouds/aws/instancetypes/cache.json.gz +0 -0
- ominfra/clouds/aws/models/gen/gen.py +8 -5
- ominfra/clouds/aws/models/services/__init__.py +7 -0
- ominfra/clouds/aws/models/services/_dataclasses.py +47718 -0
- ominfra/clouds/aws/models/services/ec2.py +103 -0
- ominfra/clouds/aws/models/services/lambda_.py +129 -0
- ominfra/clouds/aws/models/services/rds.py +210 -77
- ominfra/clouds/aws/models/services/s3.py +2 -0
- ominfra/manage/main.py +1 -2
- ominfra/scripts/journald2aws.py +408 -52
- ominfra/scripts/manage.py +391 -64
- ominfra/scripts/supervisor.py +539 -98
- {ominfra-0.0.0.dev438.dist-info → ominfra-0.0.0.dev483.dist-info}/METADATA +3 -3
- {ominfra-0.0.0.dev438.dist-info → ominfra-0.0.0.dev483.dist-info}/RECORD +18 -17
- {ominfra-0.0.0.dev438.dist-info → ominfra-0.0.0.dev483.dist-info}/WHEEL +0 -0
- {ominfra-0.0.0.dev438.dist-info → ominfra-0.0.0.dev483.dist-info}/entry_points.txt +0 -0
- {ominfra-0.0.0.dev438.dist-info → ominfra-0.0.0.dev483.dist-info}/licenses/LICENSE +0 -0
- {ominfra-0.0.0.dev438.dist-info → ominfra-0.0.0.dev483.dist-info}/top_level.txt +0 -0
ominfra/scripts/supervisor.py
CHANGED
|
@@ -65,6 +65,7 @@ import io
|
|
|
65
65
|
import itertools
|
|
66
66
|
import json
|
|
67
67
|
import logging
|
|
68
|
+
import operator
|
|
68
69
|
import os
|
|
69
70
|
import os.path
|
|
70
71
|
import pwd
|
|
@@ -98,6 +99,91 @@ if sys.version_info < (3, 8):
|
|
|
98
99
|
raise OSError(f'Requires python (3, 8), got {sys.version_info} from {sys.executable}') # noqa
|
|
99
100
|
|
|
100
101
|
|
|
102
|
+
def __omlish_amalg__(): # noqa
|
|
103
|
+
return dict(
|
|
104
|
+
src_files=[
|
|
105
|
+
dict(path='errors.py', sha1='eed49133c64621fb5f081ba7f249e8c4c8745025'),
|
|
106
|
+
dict(path='privileges.py', sha1='80fffb4966565e70b6300381800ff849616a1daa'),
|
|
107
|
+
dict(path='states.py', sha1='7e80da5abde756a47bb01fff1967e35ee9f754e5'),
|
|
108
|
+
dict(path='utils/diag.py', sha1='65f6491a57b3b8ff6dc166c4136c39e49e008c8d'),
|
|
109
|
+
dict(path='utils/fs.py', sha1='f18fd3d60c863e05d91c8e4735b86629334f5181'),
|
|
110
|
+
dict(path='utils/ostypes.py', sha1='81aa9dc830189ae7095c2b8c823e28ce4a808e8d'),
|
|
111
|
+
dict(path='utils/signals.py', sha1='445bab01dcd0144194f330e55accee1277992626'),
|
|
112
|
+
dict(path='utils/strings.py', sha1='c4ced4877e366a64b7d366353ab9e5691c587f38'),
|
|
113
|
+
dict(path='../../omlish/configs/types.py', sha1='f7a5584cd6eccb77d18d729796072a162e9a8790'),
|
|
114
|
+
dict(path='../../omlish/formats/ini/sections.py', sha1='731c92cce82e183d1d4bdc23fc781fad62187394'),
|
|
115
|
+
dict(path='../../omlish/formats/toml/parser.py', sha1='73dac82289350ab951c4bcdbfe61167fa221f26f'),
|
|
116
|
+
dict(path='../../omlish/formats/toml/writer.py', sha1='6ea41d7e724bb1dcf6bd84b88993ff4e8798e021'),
|
|
117
|
+
dict(path='../../omlish/http/versions.py', sha1='197685ffbb62a457a0e8d4047a9df26aebd7dae4'),
|
|
118
|
+
dict(path='../../omlish/io/readers.py', sha1='4b19ab4a87f2fa2a6f6c3cad7e1f3892b7cbd3a4'),
|
|
119
|
+
dict(path='../../omlish/lite/abstract.py', sha1='a2fc3f3697fa8de5247761e9d554e70176f37aac'),
|
|
120
|
+
dict(path='../../omlish/lite/attrops.py', sha1='c1ebfb8573d766d34593c452a2377208d02726dc'),
|
|
121
|
+
dict(path='../../omlish/lite/cached.py', sha1='0c33cf961ac8f0727284303c7a30c5ea98f714f2'),
|
|
122
|
+
dict(path='../../omlish/lite/check.py', sha1='bb6b6b63333699b84462951a854d99ae83195b94'),
|
|
123
|
+
dict(path='../../omlish/lite/json.py', sha1='57eeddc4d23a17931e00284ffa5cb6e3ce089486'),
|
|
124
|
+
dict(path='../../omlish/lite/objects.py', sha1='9566bbf3530fd71fcc56321485216b592fae21e9'),
|
|
125
|
+
dict(path='../../omlish/lite/reflect.py', sha1='c4fec44bf144e9d93293c996af06f6c65fc5e63d'),
|
|
126
|
+
dict(path='../../omlish/lite/strings.py', sha1='89831ecbc34ad80e118a865eceb390ed399dc4d6'),
|
|
127
|
+
dict(path='../../omlish/lite/typing.py', sha1='deaaa560b63d9a0e40991ec0006451f5f0df04c1'),
|
|
128
|
+
dict(path='../../omlish/logs/levels.py', sha1='91405563d082a5eba874da82aac89d83ce7b6152'),
|
|
129
|
+
dict(path='../../omlish/logs/std/filters.py', sha1='f36aab646d84d31e295b33aaaaa6f8b67ff38b3d'),
|
|
130
|
+
dict(path='../../omlish/logs/std/proxy.py', sha1='3e7301a2aa351127f9c85f61b2f85dcc3f15aafb'),
|
|
131
|
+
dict(path='../../omlish/logs/warnings.py', sha1='c4eb694b24773351107fcc058f3620f1dbfb6799'),
|
|
132
|
+
dict(path='../../omlish/sockets/addresses.py', sha1='26533e88a8073f89646c0f77f1fbe0869282ab0e'),
|
|
133
|
+
dict(path='events.py', sha1='d30d903b7d664f76e738ed939b7ec0e6e6861a0a'),
|
|
134
|
+
dict(path='utils/collections.py', sha1='f9c3c8a52e6057e938730746eaa28e48a5b757c6'),
|
|
135
|
+
dict(path='utils/fds.py', sha1='cf9b2a52cc74b2aaebed656ba16888e4322746ec'),
|
|
136
|
+
dict(path='utils/users.py', sha1='d440d9deb2f03b4611bc0eb0ad186f9a994d84f7'),
|
|
137
|
+
dict(path='../../omlish/configs/formats.py', sha1='9bc4f953b4b8700f6f109e6f49e2d70f8e48ce7c'),
|
|
138
|
+
dict(path='../../omlish/configs/processing/names.py', sha1='3ae4c9e921929eb64cee6150cc86f35fee0f2070'),
|
|
139
|
+
dict(path='../../omlish/http/coro/io.py', sha1='2cdf6529c37a37cc0c1db2e02032157cf906d5d6'),
|
|
140
|
+
dict(path='../../omlish/http/parsing.py', sha1='3fea28dc6341908ba7c8fad42bf7bbe711f21b82'),
|
|
141
|
+
dict(path='../../omlish/io/buffers.py', sha1='45a5f79c6d71f02ab82082a48d63ebbd10959031'),
|
|
142
|
+
dict(path='../../omlish/io/fdio/handlers.py', sha1='e81356d4d73a670c35a972476a6338d0b737662b'),
|
|
143
|
+
dict(path='../../omlish/io/fdio/pollers.py', sha1='022d5a8a24412764864ca95186a167698b739baf'),
|
|
144
|
+
dict(path='../../omlish/lite/marshal.py', sha1='96348f5f2a26dc27d842d33cc3927e9da163436b'),
|
|
145
|
+
dict(path='../../omlish/lite/maybes.py', sha1='bdf5136654ccd14b6a072588cad228925bdfbabd'),
|
|
146
|
+
dict(path='../../omlish/lite/runtime.py', sha1='2e752a27ae2bf89b1bb79b4a2da522a3ec360c70'),
|
|
147
|
+
dict(path='../../omlish/logs/infos.py', sha1='4dd104bd468a8c438601dd0bbda619b47d2f1620'),
|
|
148
|
+
dict(path='../../omlish/logs/protocols.py', sha1='05ca4d1d7feb50c4e3b9f22ee371aa7bf4b3dbd1'),
|
|
149
|
+
dict(path='../../omlish/logs/std/json.py', sha1='2a75553131e4d5331bb0cedde42aa183f403fc3b'),
|
|
150
|
+
dict(path='../../omlish/os/journald.py', sha1='7485cad562f8b9b4f71efd41a6177660f7d62e55'),
|
|
151
|
+
dict(path='configs.py', sha1='61f986fc5c9591194f72c3b4ffa4b018770710ed'),
|
|
152
|
+
dict(path='pipes.py', sha1='ad9315c50bffe81ee204227163d85ab366ce5320'),
|
|
153
|
+
dict(path='setup.py', sha1='4be12354bb45cf7773fd98ad9695aa330ae07fe6'),
|
|
154
|
+
dict(path='utils/os.py', sha1='9f7314f1c0c34a8154e9acf38a5b916b2e310b4d'),
|
|
155
|
+
dict(path='../../omlish/http/handlers.py', sha1='40629060bac22ea5e94b720b57001861a4ec9031'),
|
|
156
|
+
dict(path='../../omlish/io/fdio/kqueue.py', sha1='c90ba13e9e5ee795b6af752a6f25f8bcfd7f88a0'),
|
|
157
|
+
dict(path='../../omlish/lite/configs.py', sha1='c8602e0e197ef1133e7e8e248935ac745bfd46cb'),
|
|
158
|
+
dict(path='../../omlish/lite/inject.py', sha1='6f097e3170019a34ff6834d36fcc9cbeed3a7ab4'),
|
|
159
|
+
dict(path='../../omlish/logs/contexts.py', sha1='7456964ade9ac66460e9ade4e242dbdc24b39501'),
|
|
160
|
+
dict(path='../../omlish/logs/standard.py', sha1='818b674f7d15012f25b79f52f6e8e7368b633038'),
|
|
161
|
+
dict(path='types.py', sha1='7ef67f710fb54c3af067aa596cb593f33eafe380'),
|
|
162
|
+
dict(path='../../omlish/http/coro/server/server.py', sha1='c0a980afa8346dbc20570acddb2b3b579bfc1ce0'),
|
|
163
|
+
dict(path='../../omlish/logs/base.py', sha1='a376460b11b9dc0555fd4ead5437af62c2109a4b'),
|
|
164
|
+
dict(path='../../omlish/logs/std/records.py', sha1='8bbf6ef9eccb3a012c6ca416ddf3969450fd8fc9'),
|
|
165
|
+
dict(path='dispatchers.py', sha1='33fe5ae77e33b3cfabb97b1a1c0f06dd0cc54703'),
|
|
166
|
+
dict(path='groupsimpl.py', sha1='4fe587a6eaff7dd874b54450be62f9689283d230'),
|
|
167
|
+
dict(path='process.py', sha1='ec0903adbde7552ba8a6aad9030716ef57fc4a6c'),
|
|
168
|
+
dict(path='../../omlish/http/coro/server/fdio.py', sha1='3f1b4865e589a336f942a763dc11ce42fa5c8857'),
|
|
169
|
+
dict(path='../../omlish/logs/std/loggers.py', sha1='daa35bdc4adea5006e442688017f0de3392579b7'),
|
|
170
|
+
dict(path='groups.py', sha1='a02a602d28793e5c84fbe7bfbcfa6ccce2ee0788'),
|
|
171
|
+
dict(path='spawning.py', sha1='9e65e562395ad04e3f3a314f946b7a4e58a601da'),
|
|
172
|
+
dict(path='../../omlish/logs/modules.py', sha1='99e73cde6872fd5eda6af3dbf0fc9322bdeb641a'),
|
|
173
|
+
dict(path='dispatchersimpl.py', sha1='701947899daef9f68c4277495594031cf73d9a62'),
|
|
174
|
+
dict(path='http.py', sha1='6a144e4c93abefc5f9cdba207e807ea75f8f2d5d'),
|
|
175
|
+
dict(path='io.py', sha1='6ba708a8396c212afdd1d314c9b5804c2d66646e'),
|
|
176
|
+
dict(path='processimpl.py', sha1='7edbbcd39a8ed1fd195c760da894620617a9d969'),
|
|
177
|
+
dict(path='setupimpl.py', sha1='b4b8b8c3e1d71a0e6794fb0a845181f3662a6bfd'),
|
|
178
|
+
dict(path='signals.py', sha1='645361d922557b5cedddbd261b3f1485b96555dd'),
|
|
179
|
+
dict(path='spawningimpl.py', sha1='c770e0017c2388fe59897d12fe67c3b6b7b2ca5a'),
|
|
180
|
+
dict(path='supervisor.py', sha1='a97a13ec71deaf6eacabb1527f373b21b89209af'),
|
|
181
|
+
dict(path='inject.py', sha1='6ad254bcf1c78e0b8a1d7bb3940628857e3bb60c'),
|
|
182
|
+
dict(path='main.py', sha1='f2b43d282aa8b3505636829b0082b16345d2bbfb'),
|
|
183
|
+
],
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
|
|
101
187
|
########################################
|
|
102
188
|
|
|
103
189
|
|
|
@@ -112,7 +198,7 @@ TomlParseFloat = ta.Callable[[str], ta.Any] # ta.TypeAlias
|
|
|
112
198
|
TomlKey = ta.Tuple[str, ...] # ta.TypeAlias
|
|
113
199
|
TomlPos = int # ta.TypeAlias
|
|
114
200
|
|
|
115
|
-
# ../../omlish/lite/
|
|
201
|
+
# ../../omlish/lite/abstract.py
|
|
116
202
|
T = ta.TypeVar('T')
|
|
117
203
|
|
|
118
204
|
# ../../omlish/lite/cached.py
|
|
@@ -1725,6 +1811,36 @@ class HttpProtocolVersions:
|
|
|
1725
1811
|
HTTP_2_0 = HttpProtocolVersion(2, 0)
|
|
1726
1812
|
|
|
1727
1813
|
|
|
1814
|
+
########################################
|
|
1815
|
+
# ../../../omlish/io/readers.py
|
|
1816
|
+
|
|
1817
|
+
|
|
1818
|
+
##
|
|
1819
|
+
|
|
1820
|
+
|
|
1821
|
+
class RawBytesReader(ta.Protocol):
|
|
1822
|
+
def read1(self, n: int = -1, /) -> bytes: ...
|
|
1823
|
+
|
|
1824
|
+
|
|
1825
|
+
class BufferedBytesReader(RawBytesReader, ta.Protocol):
|
|
1826
|
+
def read(self, n: int = -1, /) -> bytes: ...
|
|
1827
|
+
|
|
1828
|
+
def readall(self) -> bytes: ...
|
|
1829
|
+
|
|
1830
|
+
|
|
1831
|
+
#
|
|
1832
|
+
|
|
1833
|
+
|
|
1834
|
+
class AsyncRawBytesReader(ta.Protocol):
|
|
1835
|
+
def read1(self, n: int = -1, /) -> ta.Awaitable[bytes]: ...
|
|
1836
|
+
|
|
1837
|
+
|
|
1838
|
+
class AsyncBufferedBytesReader(AsyncRawBytesReader, ta.Protocol):
|
|
1839
|
+
def read(self, n: int = -1, /) -> ta.Awaitable[bytes]: ...
|
|
1840
|
+
|
|
1841
|
+
def readall(self) -> ta.Awaitable[bytes]: ...
|
|
1842
|
+
|
|
1843
|
+
|
|
1728
1844
|
########################################
|
|
1729
1845
|
# ../../../omlish/lite/abstract.py
|
|
1730
1846
|
|
|
@@ -1740,25 +1856,49 @@ def is_abstract_method(obj: ta.Any) -> bool:
|
|
|
1740
1856
|
return bool(getattr(obj, _IS_ABSTRACT_METHOD_ATTR, False))
|
|
1741
1857
|
|
|
1742
1858
|
|
|
1743
|
-
def
|
|
1859
|
+
def compute_abstract_methods(cls: type) -> ta.FrozenSet[str]:
|
|
1860
|
+
# ~> https://github.com/python/cpython/blob/f3476c6507381ca860eec0989f53647b13517423/Modules/_abc.c#L358
|
|
1861
|
+
|
|
1862
|
+
# Stage 1: direct abstract methods
|
|
1863
|
+
|
|
1864
|
+
abstracts = {
|
|
1865
|
+
a
|
|
1866
|
+
# Get items as a list to avoid mutation issues during iteration
|
|
1867
|
+
for a, v in list(cls.__dict__.items())
|
|
1868
|
+
if is_abstract_method(v)
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1871
|
+
# Stage 2: inherited abstract methods
|
|
1872
|
+
|
|
1873
|
+
for base in cls.__bases__:
|
|
1874
|
+
# Get __abstractmethods__ from base if it exists
|
|
1875
|
+
if (base_abstracts := getattr(base, _ABSTRACT_METHODS_ATTR, None)) is None:
|
|
1876
|
+
continue
|
|
1877
|
+
|
|
1878
|
+
# Iterate over abstract methods in base
|
|
1879
|
+
for key in base_abstracts:
|
|
1880
|
+
# Check if this class has an attribute with this name
|
|
1881
|
+
try:
|
|
1882
|
+
value = getattr(cls, key)
|
|
1883
|
+
except AttributeError:
|
|
1884
|
+
# Attribute not found in this class, skip
|
|
1885
|
+
continue
|
|
1886
|
+
|
|
1887
|
+
# Check if it's still abstract
|
|
1888
|
+
if is_abstract_method(value):
|
|
1889
|
+
abstracts.add(key)
|
|
1890
|
+
|
|
1891
|
+
return frozenset(abstracts)
|
|
1892
|
+
|
|
1893
|
+
|
|
1894
|
+
def update_abstracts(cls: ta.Type[T], *, force: bool = False) -> ta.Type[T]:
|
|
1744
1895
|
if not force and not hasattr(cls, _ABSTRACT_METHODS_ATTR):
|
|
1745
1896
|
# Per stdlib: We check for __abstractmethods__ here because cls might by a C implementation or a python
|
|
1746
1897
|
# implementation (especially during testing), and we want to handle both cases.
|
|
1747
1898
|
return cls
|
|
1748
1899
|
|
|
1749
|
-
abstracts
|
|
1750
|
-
|
|
1751
|
-
for scls in cls.__bases__:
|
|
1752
|
-
for name in getattr(scls, _ABSTRACT_METHODS_ATTR, ()):
|
|
1753
|
-
value = getattr(cls, name, None)
|
|
1754
|
-
if getattr(value, _IS_ABSTRACT_METHOD_ATTR, False):
|
|
1755
|
-
abstracts.add(name)
|
|
1756
|
-
|
|
1757
|
-
for name, value in cls.__dict__.items():
|
|
1758
|
-
if getattr(value, _IS_ABSTRACT_METHOD_ATTR, False):
|
|
1759
|
-
abstracts.add(name)
|
|
1760
|
-
|
|
1761
|
-
setattr(cls, _ABSTRACT_METHODS_ATTR, frozenset(abstracts))
|
|
1900
|
+
abstracts = compute_abstract_methods(cls)
|
|
1901
|
+
setattr(cls, _ABSTRACT_METHODS_ATTR, abstracts)
|
|
1762
1902
|
return cls
|
|
1763
1903
|
|
|
1764
1904
|
|
|
@@ -1812,23 +1952,26 @@ class Abstract:
|
|
|
1812
1952
|
super().__init_subclass__(**kwargs)
|
|
1813
1953
|
|
|
1814
1954
|
if not (Abstract in cls.__bases__ or abc.ABC in cls.__bases__):
|
|
1815
|
-
ams
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1955
|
+
if ams := compute_abstract_methods(cls):
|
|
1956
|
+
amd = {
|
|
1957
|
+
a: mcls
|
|
1958
|
+
for mcls in cls.__mro__[::-1]
|
|
1959
|
+
for a in ams
|
|
1960
|
+
if a in mcls.__dict__
|
|
1961
|
+
}
|
|
1821
1962
|
|
|
1822
|
-
if ams:
|
|
1823
1963
|
raise AbstractTypeError(
|
|
1824
1964
|
f'Cannot subclass abstract class {cls.__name__} with abstract methods: ' +
|
|
1825
1965
|
', '.join(sorted([
|
|
1826
1966
|
'.'.join([
|
|
1827
|
-
*([
|
|
1828
|
-
|
|
1967
|
+
*([
|
|
1968
|
+
*([m] if (m := getattr(c, '__module__')) else []),
|
|
1969
|
+
getattr(c, '__qualname__', getattr(c, '__name__')),
|
|
1970
|
+
] if c is not None else '?'),
|
|
1829
1971
|
a,
|
|
1830
1972
|
])
|
|
1831
|
-
for a
|
|
1973
|
+
for a in ams
|
|
1974
|
+
for c in [amd.get(a)]
|
|
1832
1975
|
])),
|
|
1833
1976
|
)
|
|
1834
1977
|
|
|
@@ -1853,6 +1996,8 @@ TODO:
|
|
|
1853
1996
|
- per-attr repr transform / filter
|
|
1854
1997
|
- __ne__ ? cases where it still matters
|
|
1855
1998
|
- ordering ?
|
|
1999
|
+
- repr_filter: ta.Union[ta.Callable[[ta.Any], ta.Optional[str]], ta.Literal['not_none', 'truthy']]] ?
|
|
2000
|
+
- unify repr/repr_fn/repr_filter
|
|
1856
2001
|
"""
|
|
1857
2002
|
|
|
1858
2003
|
|
|
@@ -1870,6 +2015,8 @@ class AttrOps(ta.Generic[T]):
|
|
|
1870
2015
|
display: ta.Optional[str] = None,
|
|
1871
2016
|
|
|
1872
2017
|
repr: bool = True, # noqa
|
|
2018
|
+
repr_fn: ta.Optional[ta.Callable[[ta.Any], ta.Optional[str]]] = None,
|
|
2019
|
+
|
|
1873
2020
|
hash: bool = True, # noqa
|
|
1874
2021
|
eq: bool = True,
|
|
1875
2022
|
) -> None:
|
|
@@ -1884,6 +2031,8 @@ class AttrOps(ta.Generic[T]):
|
|
|
1884
2031
|
self._display = display
|
|
1885
2032
|
|
|
1886
2033
|
self._repr = repr
|
|
2034
|
+
self._repr_fn = repr_fn
|
|
2035
|
+
|
|
1887
2036
|
self._hash = hash
|
|
1888
2037
|
self._eq = eq
|
|
1889
2038
|
|
|
@@ -1891,21 +2040,30 @@ class AttrOps(ta.Generic[T]):
|
|
|
1891
2040
|
def of(
|
|
1892
2041
|
cls,
|
|
1893
2042
|
o: ta.Union[
|
|
1894
|
-
str,
|
|
1895
|
-
ta.Tuple[str, str],
|
|
1896
2043
|
'AttrOps.Attr',
|
|
2044
|
+
str,
|
|
2045
|
+
ta.Tuple[str, ta.Union[str, ta.Mapping[str, ta.Any]]],
|
|
2046
|
+
ta.Mapping[str, ta.Any],
|
|
1897
2047
|
],
|
|
1898
2048
|
) -> 'AttrOps.Attr':
|
|
1899
2049
|
if isinstance(o, AttrOps.Attr):
|
|
1900
2050
|
return o
|
|
1901
2051
|
elif isinstance(o, str):
|
|
1902
2052
|
return cls(o)
|
|
2053
|
+
elif isinstance(o, tuple):
|
|
2054
|
+
name, x = o
|
|
2055
|
+
kw: ta.Mapping[str, ta.Any]
|
|
2056
|
+
if isinstance(x, str):
|
|
2057
|
+
kw = dict(display=x)
|
|
2058
|
+
elif isinstance(x, ta.Mapping):
|
|
2059
|
+
kw = x
|
|
2060
|
+
else:
|
|
2061
|
+
raise TypeError(x)
|
|
2062
|
+
return cls(name, **kw)
|
|
2063
|
+
elif isinstance(o, ta.Mapping):
|
|
2064
|
+
return cls(**o)
|
|
1903
2065
|
else:
|
|
1904
|
-
|
|
1905
|
-
return cls(
|
|
1906
|
-
name,
|
|
1907
|
-
display=disp,
|
|
1908
|
-
)
|
|
2066
|
+
raise TypeError(o)
|
|
1909
2067
|
|
|
1910
2068
|
@property
|
|
1911
2069
|
def name(self) -> str:
|
|
@@ -1923,19 +2081,34 @@ class AttrOps(ta.Generic[T]):
|
|
|
1923
2081
|
def eq(self) -> bool:
|
|
1924
2082
|
return self._eq
|
|
1925
2083
|
|
|
2084
|
+
@staticmethod
|
|
2085
|
+
def opt_repr(o: ta.Any) -> ta.Optional[str]:
|
|
2086
|
+
return repr(o) if o is not None else None
|
|
2087
|
+
|
|
2088
|
+
@staticmethod
|
|
2089
|
+
def truthy_repr(o: ta.Any) -> ta.Optional[str]:
|
|
2090
|
+
return repr(o) if o else None
|
|
2091
|
+
|
|
2092
|
+
#
|
|
2093
|
+
|
|
1926
2094
|
@ta.overload
|
|
1927
2095
|
def __init__(
|
|
1928
2096
|
self,
|
|
1929
2097
|
*attrs: ta.Sequence[ta.Union[
|
|
1930
2098
|
str,
|
|
1931
|
-
ta.Tuple[str, str],
|
|
2099
|
+
ta.Tuple[str, ta.Union[str, ta.Mapping[str, ta.Any]]],
|
|
2100
|
+
ta.Mapping[str, ta.Any],
|
|
1932
2101
|
Attr,
|
|
1933
2102
|
]],
|
|
2103
|
+
|
|
1934
2104
|
with_module: bool = False,
|
|
1935
2105
|
use_qualname: bool = False,
|
|
1936
2106
|
with_id: bool = False,
|
|
2107
|
+
terse: bool = False,
|
|
1937
2108
|
repr_filter: ta.Optional[ta.Callable[[ta.Any], bool]] = None,
|
|
1938
2109
|
recursive: bool = False,
|
|
2110
|
+
|
|
2111
|
+
cache_hash: ta.Union[bool, str] = False,
|
|
1939
2112
|
subtypes_eq: bool = False,
|
|
1940
2113
|
) -> None:
|
|
1941
2114
|
...
|
|
@@ -1945,16 +2118,20 @@ class AttrOps(ta.Generic[T]):
|
|
|
1945
2118
|
self,
|
|
1946
2119
|
attrs_fn: ta.Callable[[T], ta.Tuple[ta.Union[
|
|
1947
2120
|
ta.Any,
|
|
1948
|
-
ta.Tuple[str, ta.Any],
|
|
2121
|
+
ta.Tuple[ta.Any, ta.Union[str, ta.Mapping[str, ta.Any]]],
|
|
1949
2122
|
Attr,
|
|
1950
2123
|
], ...]],
|
|
1951
2124
|
/,
|
|
1952
2125
|
*,
|
|
2126
|
+
|
|
1953
2127
|
with_module: bool = False,
|
|
1954
2128
|
use_qualname: bool = False,
|
|
1955
2129
|
with_id: bool = False,
|
|
2130
|
+
terse: bool = False,
|
|
1956
2131
|
repr_filter: ta.Optional[ta.Callable[[ta.Any], bool]] = None,
|
|
1957
2132
|
recursive: bool = False,
|
|
2133
|
+
|
|
2134
|
+
cache_hash: ta.Union[bool, str] = False,
|
|
1958
2135
|
subtypes_eq: bool = False,
|
|
1959
2136
|
) -> None:
|
|
1960
2137
|
...
|
|
@@ -1962,11 +2139,15 @@ class AttrOps(ta.Generic[T]):
|
|
|
1962
2139
|
def __init__(
|
|
1963
2140
|
self,
|
|
1964
2141
|
*args,
|
|
2142
|
+
|
|
1965
2143
|
with_module=False,
|
|
1966
2144
|
use_qualname=False,
|
|
1967
2145
|
with_id=False,
|
|
2146
|
+
terse=False,
|
|
1968
2147
|
repr_filter=None,
|
|
1969
2148
|
recursive=False,
|
|
2149
|
+
|
|
2150
|
+
cache_hash=False,
|
|
1970
2151
|
subtypes_eq=False,
|
|
1971
2152
|
) -> None:
|
|
1972
2153
|
if args and len(args) == 1 and callable(args[0]):
|
|
@@ -1977,8 +2158,11 @@ class AttrOps(ta.Generic[T]):
|
|
|
1977
2158
|
self._with_module: bool = with_module
|
|
1978
2159
|
self._use_qualname: bool = use_qualname
|
|
1979
2160
|
self._with_id: bool = with_id
|
|
2161
|
+
self._terse: bool = terse
|
|
1980
2162
|
self._repr_filter: ta.Optional[ta.Callable[[ta.Any], bool]] = repr_filter
|
|
1981
2163
|
self._recursive: bool = recursive
|
|
2164
|
+
|
|
2165
|
+
self._cache_hash: ta.Union[bool, str] = cache_hash
|
|
1982
2166
|
self._subtypes_eq: bool = subtypes_eq
|
|
1983
2167
|
|
|
1984
2168
|
@property
|
|
@@ -2013,20 +2197,27 @@ class AttrOps(ta.Generic[T]):
|
|
|
2013
2197
|
|
|
2014
2198
|
attrs: ta.List[AttrOps.Attr] = []
|
|
2015
2199
|
for o in raw:
|
|
2016
|
-
if isinstance(o, AttrOps.Attr):
|
|
2017
|
-
attrs.append(o)
|
|
2200
|
+
if isinstance(o, (AttrOps.Attr, ta.Mapping)):
|
|
2201
|
+
attrs.append(AttrOps.Attr.of(o))
|
|
2018
2202
|
continue
|
|
2019
2203
|
|
|
2204
|
+
kw: ta.Mapping[str, ta.Any]
|
|
2020
2205
|
if isinstance(o, tuple):
|
|
2021
|
-
|
|
2206
|
+
cap, x = o
|
|
2207
|
+
if isinstance(x, str):
|
|
2208
|
+
kw = dict(display=x)
|
|
2209
|
+
elif isinstance(x, ta.Mapping):
|
|
2210
|
+
kw = x
|
|
2211
|
+
else:
|
|
2212
|
+
raise TypeError(x)
|
|
2022
2213
|
else:
|
|
2023
|
-
|
|
2214
|
+
cap, kw = o, {}
|
|
2024
2215
|
|
|
2025
2216
|
path = tuple(rec(cap))
|
|
2026
2217
|
|
|
2027
2218
|
attrs.append(AttrOps.Attr(
|
|
2028
2219
|
'.'.join(path),
|
|
2029
|
-
|
|
2220
|
+
**kw,
|
|
2030
2221
|
))
|
|
2031
2222
|
|
|
2032
2223
|
return attrs
|
|
@@ -2043,19 +2234,27 @@ class AttrOps(ta.Generic[T]):
|
|
|
2043
2234
|
pass
|
|
2044
2235
|
|
|
2045
2236
|
def _repr(o: T) -> str:
|
|
2046
|
-
vs =
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
if self._repr_filter is None
|
|
2052
|
-
|
|
2237
|
+
vs: ta.List[str] = []
|
|
2238
|
+
for a in self._attrs:
|
|
2239
|
+
if not a._repr: # noqa
|
|
2240
|
+
continue
|
|
2241
|
+
v = getattr(o, a._name) # noqa
|
|
2242
|
+
if self._repr_filter is not None and not self._repr_filter(v):
|
|
2243
|
+
continue
|
|
2244
|
+
if (rfn := a._repr_fn) is None: # noqa
|
|
2245
|
+
rfn = repr
|
|
2246
|
+
if (vr := rfn(v)) is None:
|
|
2247
|
+
continue
|
|
2248
|
+
if self._terse:
|
|
2249
|
+
vs.append(vr)
|
|
2250
|
+
else:
|
|
2251
|
+
vs.append(f'{a._display}={vr}') # noqa
|
|
2053
2252
|
|
|
2054
2253
|
return (
|
|
2055
2254
|
f'{o.__class__.__module__ + "." if self._with_module else ""}'
|
|
2056
2255
|
f'{o.__class__.__qualname__ if self._use_qualname else o.__class__.__name__}'
|
|
2057
2256
|
f'{("@" + hex(id(o))[2:]) if self._with_id else ""}' # noqa
|
|
2058
|
-
f'({vs})'
|
|
2257
|
+
f'({", ".join(vs)})'
|
|
2059
2258
|
)
|
|
2060
2259
|
|
|
2061
2260
|
if self._recursive:
|
|
@@ -2080,6 +2279,8 @@ class AttrOps(ta.Generic[T]):
|
|
|
2080
2279
|
|
|
2081
2280
|
#
|
|
2082
2281
|
|
|
2282
|
+
_DEFAULT_CACHED_HASH_ATTR: ta.ClassVar[str] = '__cached_hash__'
|
|
2283
|
+
|
|
2083
2284
|
_hash: ta.Callable[[T], int]
|
|
2084
2285
|
|
|
2085
2286
|
@property
|
|
@@ -2089,13 +2290,33 @@ class AttrOps(ta.Generic[T]):
|
|
|
2089
2290
|
except AttributeError:
|
|
2090
2291
|
pass
|
|
2091
2292
|
|
|
2092
|
-
def
|
|
2293
|
+
def _calc_hash(o: T) -> int:
|
|
2093
2294
|
return hash(tuple(
|
|
2094
2295
|
getattr(o, a._name) # noqa
|
|
2095
2296
|
for a in self._attrs
|
|
2096
2297
|
if a._hash # noqa
|
|
2097
2298
|
))
|
|
2098
2299
|
|
|
2300
|
+
if (ch := self._cache_hash) is not False:
|
|
2301
|
+
if ch is True:
|
|
2302
|
+
cha = self._DEFAULT_CACHED_HASH_ATTR
|
|
2303
|
+
elif isinstance(ch, str):
|
|
2304
|
+
cha = ch
|
|
2305
|
+
else:
|
|
2306
|
+
raise TypeError(ch)
|
|
2307
|
+
|
|
2308
|
+
def _cached_hash(o: T) -> int:
|
|
2309
|
+
try:
|
|
2310
|
+
return object.__getattribute__(o, cha)
|
|
2311
|
+
except AttributeError:
|
|
2312
|
+
object.__setattr__(o, cha, h := _calc_hash(o))
|
|
2313
|
+
return h
|
|
2314
|
+
|
|
2315
|
+
_hash = _cached_hash
|
|
2316
|
+
|
|
2317
|
+
else:
|
|
2318
|
+
_hash = _calc_hash
|
|
2319
|
+
|
|
2099
2320
|
self._hash = _hash
|
|
2100
2321
|
return _hash
|
|
2101
2322
|
|
|
@@ -2236,6 +2457,62 @@ def async_cached_nullary(fn): # ta.Callable[..., T]) -> ta.Callable[..., T]:
|
|
|
2236
2457
|
return _AsyncCachedNullary(fn)
|
|
2237
2458
|
|
|
2238
2459
|
|
|
2460
|
+
##
|
|
2461
|
+
|
|
2462
|
+
|
|
2463
|
+
cached_property = functools.cached_property
|
|
2464
|
+
|
|
2465
|
+
|
|
2466
|
+
class _cached_property: # noqa
|
|
2467
|
+
"""Backported to pick up https://github.com/python/cpython/commit/056dfc71dce15f81887f0bd6da09d6099d71f979 ."""
|
|
2468
|
+
|
|
2469
|
+
def __init__(self, func):
|
|
2470
|
+
self.func = func
|
|
2471
|
+
self.attrname = None # noqa
|
|
2472
|
+
self.__doc__ = func.__doc__
|
|
2473
|
+
self.__module__ = func.__module__
|
|
2474
|
+
|
|
2475
|
+
_NOT_FOUND = object()
|
|
2476
|
+
|
|
2477
|
+
def __set_name__(self, owner, name):
|
|
2478
|
+
if self.attrname is None:
|
|
2479
|
+
self.attrname = name # noqa
|
|
2480
|
+
elif name != self.attrname:
|
|
2481
|
+
raise TypeError(
|
|
2482
|
+
f'Cannot assign the same cached_property to two different names ({self.attrname!r} and {name!r}).',
|
|
2483
|
+
)
|
|
2484
|
+
|
|
2485
|
+
def __get__(self, instance, owner=None):
|
|
2486
|
+
if instance is None:
|
|
2487
|
+
return self
|
|
2488
|
+
if self.attrname is None:
|
|
2489
|
+
raise TypeError('Cannot use cached_property instance without calling __set_name__ on it.')
|
|
2490
|
+
|
|
2491
|
+
try:
|
|
2492
|
+
cache = instance.__dict__
|
|
2493
|
+
except AttributeError: # not all objects have __dict__ (e.g. class defines slots)
|
|
2494
|
+
raise TypeError(
|
|
2495
|
+
f"No '__dict__' attribute on {type(instance).__name__!r} instance to cache {self.attrname!r} property.",
|
|
2496
|
+
) from None
|
|
2497
|
+
|
|
2498
|
+
val = cache.get(self.attrname, self._NOT_FOUND)
|
|
2499
|
+
|
|
2500
|
+
if val is self._NOT_FOUND:
|
|
2501
|
+
val = self.func(instance)
|
|
2502
|
+
try:
|
|
2503
|
+
cache[self.attrname] = val
|
|
2504
|
+
except TypeError:
|
|
2505
|
+
raise TypeError(
|
|
2506
|
+
f"The '__dict__' attribute on {type(instance).__name__!r} instance does not support item "
|
|
2507
|
+
f"assignment for caching {self.attrname!r} property.",
|
|
2508
|
+
) from None
|
|
2509
|
+
|
|
2510
|
+
return val
|
|
2511
|
+
|
|
2512
|
+
|
|
2513
|
+
globals()['cached_property'] = _cached_property
|
|
2514
|
+
|
|
2515
|
+
|
|
2239
2516
|
########################################
|
|
2240
2517
|
# ../../../omlish/lite/check.py
|
|
2241
2518
|
"""
|
|
@@ -3024,6 +3301,12 @@ def format_num_bytes(num_bytes: int) -> str:
|
|
|
3024
3301
|
|
|
3025
3302
|
##
|
|
3026
3303
|
# A workaround for typing deficiencies (like `Argument 2 to NewType(...) must be subclassable`).
|
|
3304
|
+
#
|
|
3305
|
+
# Note that this problem doesn't happen at runtime - it happens in mypy:
|
|
3306
|
+
#
|
|
3307
|
+
# mypy <(echo "import typing as ta; MyCallback = ta.NewType('MyCallback', ta.Callable[[], None])")
|
|
3308
|
+
# /dev/fd/11:1:22: error: Argument 2 to NewType(...) must be subclassable (got "Callable[[], None]") [valid-newtype]
|
|
3309
|
+
#
|
|
3027
3310
|
|
|
3028
3311
|
|
|
3029
3312
|
@dc.dataclass(frozen=True)
|
|
@@ -4114,6 +4397,72 @@ def build_config_named_children(
|
|
|
4114
4397
|
return lst
|
|
4115
4398
|
|
|
4116
4399
|
|
|
4400
|
+
########################################
|
|
4401
|
+
# ../../../omlish/http/coro/io.py
|
|
4402
|
+
|
|
4403
|
+
|
|
4404
|
+
##
|
|
4405
|
+
|
|
4406
|
+
|
|
4407
|
+
class CoroHttpIo:
|
|
4408
|
+
def __new__(cls, *args, **kwargs): # noqa
|
|
4409
|
+
raise TypeError
|
|
4410
|
+
|
|
4411
|
+
def __init_subclass__(cls, **kwargs): # noqa
|
|
4412
|
+
raise TypeError
|
|
4413
|
+
|
|
4414
|
+
#
|
|
4415
|
+
|
|
4416
|
+
MAX_LINE: ta.ClassVar[int] = 65536
|
|
4417
|
+
|
|
4418
|
+
#
|
|
4419
|
+
|
|
4420
|
+
class Io(Abstract):
|
|
4421
|
+
pass
|
|
4422
|
+
|
|
4423
|
+
#
|
|
4424
|
+
|
|
4425
|
+
class AnyLogIo(Io, Abstract):
|
|
4426
|
+
pass
|
|
4427
|
+
|
|
4428
|
+
#
|
|
4429
|
+
|
|
4430
|
+
@dc.dataclass(frozen=True)
|
|
4431
|
+
class ConnectIo(Io):
|
|
4432
|
+
args: ta.Tuple[ta.Any, ...]
|
|
4433
|
+
kwargs: ta.Optional[ta.Dict[str, ta.Any]] = None
|
|
4434
|
+
|
|
4435
|
+
server_hostname: ta.Optional[str] = None
|
|
4436
|
+
|
|
4437
|
+
#
|
|
4438
|
+
|
|
4439
|
+
class CloseIo(Io):
|
|
4440
|
+
pass
|
|
4441
|
+
|
|
4442
|
+
#
|
|
4443
|
+
|
|
4444
|
+
class AnyReadIo(Io): # noqa
|
|
4445
|
+
pass
|
|
4446
|
+
|
|
4447
|
+
@dc.dataclass(frozen=True)
|
|
4448
|
+
class ReadIo(AnyReadIo):
|
|
4449
|
+
sz: ta.Optional[int]
|
|
4450
|
+
|
|
4451
|
+
@dc.dataclass(frozen=True)
|
|
4452
|
+
class ReadLineIo(AnyReadIo):
|
|
4453
|
+
sz: int
|
|
4454
|
+
|
|
4455
|
+
@dc.dataclass(frozen=True)
|
|
4456
|
+
class PeekIo(AnyReadIo):
|
|
4457
|
+
sz: int
|
|
4458
|
+
|
|
4459
|
+
#
|
|
4460
|
+
|
|
4461
|
+
@dc.dataclass(frozen=True)
|
|
4462
|
+
class WriteIo(Io):
|
|
4463
|
+
data: bytes
|
|
4464
|
+
|
|
4465
|
+
|
|
4117
4466
|
########################################
|
|
4118
4467
|
# ../../../omlish/http/parsing.py
|
|
4119
4468
|
# PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
|
|
@@ -4529,6 +4878,10 @@ class HttpRequestParser:
|
|
|
4529
4878
|
|
|
4530
4879
|
########################################
|
|
4531
4880
|
# ../../../omlish/io/buffers.py
|
|
4881
|
+
"""
|
|
4882
|
+
TODO:
|
|
4883
|
+
- overhaul and just coro-ify pyio?
|
|
4884
|
+
"""
|
|
4532
4885
|
|
|
4533
4886
|
|
|
4534
4887
|
##
|
|
@@ -4707,6 +5060,9 @@ class ReadableListBuffer:
|
|
|
4707
5060
|
|
|
4708
5061
|
self._lst: list[bytes] = []
|
|
4709
5062
|
|
|
5063
|
+
def __bool__(self) -> ta.NoReturn:
|
|
5064
|
+
raise TypeError("Use 'buf is not None' or 'len(buf)'.")
|
|
5065
|
+
|
|
4710
5066
|
def __len__(self) -> int:
|
|
4711
5067
|
return sum(map(len, self._lst))
|
|
4712
5068
|
|
|
@@ -4732,6 +5088,9 @@ class ReadableListBuffer:
|
|
|
4732
5088
|
|
|
4733
5089
|
def read(self, n: ta.Optional[int] = None) -> ta.Optional[bytes]:
|
|
4734
5090
|
if n is None:
|
|
5091
|
+
if not self._lst:
|
|
5092
|
+
return b''
|
|
5093
|
+
|
|
4735
5094
|
o = b''.join(self._lst)
|
|
4736
5095
|
self._lst = []
|
|
4737
5096
|
return o
|
|
@@ -4770,6 +5129,110 @@ class ReadableListBuffer:
|
|
|
4770
5129
|
r = self.read_until_(delim)
|
|
4771
5130
|
return r if isinstance(r, bytes) else None
|
|
4772
5131
|
|
|
5132
|
+
#
|
|
5133
|
+
|
|
5134
|
+
DEFAULT_BUFFERED_READER_CHUNK_SIZE: ta.ClassVar[int] = -1
|
|
5135
|
+
|
|
5136
|
+
@ta.final
|
|
5137
|
+
class _BufferedBytesReader(BufferedBytesReader):
|
|
5138
|
+
def __init__(
|
|
5139
|
+
self,
|
|
5140
|
+
raw: RawBytesReader,
|
|
5141
|
+
buf: 'ReadableListBuffer',
|
|
5142
|
+
*,
|
|
5143
|
+
chunk_size: ta.Optional[int] = None,
|
|
5144
|
+
) -> None:
|
|
5145
|
+
self._raw = raw
|
|
5146
|
+
self._buf = buf
|
|
5147
|
+
self._chunk_size = chunk_size or ReadableListBuffer.DEFAULT_BUFFERED_READER_CHUNK_SIZE
|
|
5148
|
+
|
|
5149
|
+
def read1(self, n: int = -1, /) -> bytes:
|
|
5150
|
+
if n < 0:
|
|
5151
|
+
n = self._chunk_size
|
|
5152
|
+
if not n:
|
|
5153
|
+
return b''
|
|
5154
|
+
if 0 < n <= len(self._buf):
|
|
5155
|
+
return self._buf.read(n) or b''
|
|
5156
|
+
return self._raw.read1(n)
|
|
5157
|
+
|
|
5158
|
+
def read(self, /, n: int = -1) -> bytes:
|
|
5159
|
+
if n < 0:
|
|
5160
|
+
return self.readall()
|
|
5161
|
+
while len(self._buf) < n:
|
|
5162
|
+
if not (b := self._raw.read1(n)):
|
|
5163
|
+
break
|
|
5164
|
+
self._buf.feed(b)
|
|
5165
|
+
return self._buf.read(n) or b''
|
|
5166
|
+
|
|
5167
|
+
def readall(self) -> bytes:
|
|
5168
|
+
buf = io.BytesIO()
|
|
5169
|
+
buf.write(self._buf.read() or b'')
|
|
5170
|
+
while (b := self._raw.read1(self._chunk_size)):
|
|
5171
|
+
buf.write(b)
|
|
5172
|
+
return buf.getvalue()
|
|
5173
|
+
|
|
5174
|
+
def new_buffered_reader(
|
|
5175
|
+
self,
|
|
5176
|
+
raw: RawBytesReader,
|
|
5177
|
+
*,
|
|
5178
|
+
chunk_size: ta.Optional[int] = None,
|
|
5179
|
+
) -> BufferedBytesReader:
|
|
5180
|
+
return self._BufferedBytesReader(
|
|
5181
|
+
raw,
|
|
5182
|
+
self,
|
|
5183
|
+
chunk_size=chunk_size,
|
|
5184
|
+
)
|
|
5185
|
+
|
|
5186
|
+
@ta.final
|
|
5187
|
+
class _AsyncBufferedBytesReader(AsyncBufferedBytesReader):
|
|
5188
|
+
def __init__(
|
|
5189
|
+
self,
|
|
5190
|
+
raw: AsyncRawBytesReader,
|
|
5191
|
+
buf: 'ReadableListBuffer',
|
|
5192
|
+
*,
|
|
5193
|
+
chunk_size: ta.Optional[int] = None,
|
|
5194
|
+
) -> None:
|
|
5195
|
+
self._raw = raw
|
|
5196
|
+
self._buf = buf
|
|
5197
|
+
self._chunk_size = chunk_size or ReadableListBuffer.DEFAULT_BUFFERED_READER_CHUNK_SIZE
|
|
5198
|
+
|
|
5199
|
+
async def read1(self, n: int = -1, /) -> bytes:
|
|
5200
|
+
if n < 0:
|
|
5201
|
+
n = self._chunk_size
|
|
5202
|
+
if not n:
|
|
5203
|
+
return b''
|
|
5204
|
+
if 0 < n <= len(self._buf):
|
|
5205
|
+
return self._buf.read(n) or b''
|
|
5206
|
+
return await self._raw.read1(n)
|
|
5207
|
+
|
|
5208
|
+
async def read(self, /, n: int = -1) -> bytes:
|
|
5209
|
+
if n < 0:
|
|
5210
|
+
return await self.readall()
|
|
5211
|
+
while len(self._buf) < n:
|
|
5212
|
+
if not (b := await self._raw.read1(n)):
|
|
5213
|
+
break
|
|
5214
|
+
self._buf.feed(b)
|
|
5215
|
+
return self._buf.read(n) or b''
|
|
5216
|
+
|
|
5217
|
+
async def readall(self) -> bytes:
|
|
5218
|
+
buf = io.BytesIO()
|
|
5219
|
+
buf.write(self._buf.read() or b'')
|
|
5220
|
+
while b := await self._raw.read1(self._chunk_size):
|
|
5221
|
+
buf.write(b)
|
|
5222
|
+
return buf.getvalue()
|
|
5223
|
+
|
|
5224
|
+
def new_async_buffered_reader(
|
|
5225
|
+
self,
|
|
5226
|
+
raw: AsyncRawBytesReader,
|
|
5227
|
+
*,
|
|
5228
|
+
chunk_size: ta.Optional[int] = None,
|
|
5229
|
+
) -> AsyncBufferedBytesReader:
|
|
5230
|
+
return self._AsyncBufferedBytesReader(
|
|
5231
|
+
raw,
|
|
5232
|
+
self,
|
|
5233
|
+
chunk_size=chunk_size,
|
|
5234
|
+
)
|
|
5235
|
+
|
|
4773
5236
|
|
|
4774
5237
|
##
|
|
4775
5238
|
|
|
@@ -6014,8 +6477,6 @@ class _JustMaybe(_Maybe[T]):
|
|
|
6014
6477
|
__slots__ = ('_v', '_hash')
|
|
6015
6478
|
|
|
6016
6479
|
def __init__(self, v: T) -> None:
|
|
6017
|
-
super().__init__()
|
|
6018
|
-
|
|
6019
6480
|
self._v = v
|
|
6020
6481
|
|
|
6021
6482
|
@property
|
|
@@ -6073,6 +6534,13 @@ class _EmptyMaybe(_Maybe[T]):
|
|
|
6073
6534
|
Maybe._empty = _EmptyMaybe() # noqa
|
|
6074
6535
|
|
|
6075
6536
|
|
|
6537
|
+
##
|
|
6538
|
+
|
|
6539
|
+
|
|
6540
|
+
setattr(Maybe, 'just', _JustMaybe) # noqa
|
|
6541
|
+
setattr(Maybe, 'empty', functools.partial(operator.attrgetter('_empty'), Maybe))
|
|
6542
|
+
|
|
6543
|
+
|
|
6076
6544
|
########################################
|
|
6077
6545
|
# ../../../omlish/lite/runtime.py
|
|
6078
6546
|
|
|
@@ -9392,48 +9860,21 @@ class CoroHttpServer:
|
|
|
9392
9860
|
|
|
9393
9861
|
#
|
|
9394
9862
|
|
|
9395
|
-
class Io(Abstract):
|
|
9396
|
-
pass
|
|
9397
|
-
|
|
9398
|
-
#
|
|
9399
|
-
|
|
9400
|
-
class AnyLogIo(Io):
|
|
9401
|
-
pass
|
|
9402
|
-
|
|
9403
9863
|
@dc.dataclass(frozen=True)
|
|
9404
|
-
class ParsedRequestLogIo(AnyLogIo):
|
|
9864
|
+
class ParsedRequestLogIo(CoroHttpIo.AnyLogIo):
|
|
9405
9865
|
request: ParsedHttpRequest
|
|
9406
9866
|
|
|
9407
9867
|
@dc.dataclass(frozen=True)
|
|
9408
|
-
class ErrorLogIo(AnyLogIo):
|
|
9868
|
+
class ErrorLogIo(CoroHttpIo.AnyLogIo):
|
|
9409
9869
|
error: 'CoroHttpServer.Error'
|
|
9410
9870
|
|
|
9411
9871
|
#
|
|
9412
9872
|
|
|
9413
|
-
class AnyReadIo(Io): # noqa
|
|
9414
|
-
pass
|
|
9415
|
-
|
|
9416
|
-
@dc.dataclass(frozen=True)
|
|
9417
|
-
class ReadIo(AnyReadIo):
|
|
9418
|
-
sz: int
|
|
9419
|
-
|
|
9420
|
-
@dc.dataclass(frozen=True)
|
|
9421
|
-
class ReadLineIo(AnyReadIo):
|
|
9422
|
-
sz: int
|
|
9423
|
-
|
|
9424
|
-
#
|
|
9425
|
-
|
|
9426
|
-
@dc.dataclass(frozen=True)
|
|
9427
|
-
class WriteIo(Io):
|
|
9428
|
-
data: bytes
|
|
9429
|
-
|
|
9430
|
-
#
|
|
9431
|
-
|
|
9432
9873
|
@dc.dataclass(frozen=True)
|
|
9433
9874
|
class CoroHandleResult:
|
|
9434
9875
|
close_reason: ta.Literal['response', 'internal', None] = None
|
|
9435
9876
|
|
|
9436
|
-
def coro_handle(self) -> ta.Generator[Io, ta.Optional[bytes], CoroHandleResult]:
|
|
9877
|
+
def coro_handle(self) -> ta.Generator[CoroHttpIo.Io, ta.Optional[bytes], CoroHandleResult]:
|
|
9437
9878
|
return self._coro_run_handler(self._coro_handle_one())
|
|
9438
9879
|
|
|
9439
9880
|
class Close(Exception): # noqa
|
|
@@ -9442,20 +9883,20 @@ class CoroHttpServer:
|
|
|
9442
9883
|
def _coro_run_handler(
|
|
9443
9884
|
self,
|
|
9444
9885
|
gen: ta.Generator[
|
|
9445
|
-
ta.Union[AnyLogIo, AnyReadIo, _Response],
|
|
9886
|
+
ta.Union[CoroHttpIo.AnyLogIo, CoroHttpIo.AnyReadIo, _Response],
|
|
9446
9887
|
ta.Optional[bytes],
|
|
9447
9888
|
None,
|
|
9448
9889
|
],
|
|
9449
|
-
) -> ta.Generator[Io, ta.Optional[bytes], CoroHandleResult]:
|
|
9890
|
+
) -> ta.Generator[CoroHttpIo.Io, ta.Optional[bytes], CoroHandleResult]:
|
|
9450
9891
|
i: ta.Optional[bytes]
|
|
9451
9892
|
o: ta.Any = next(gen)
|
|
9452
9893
|
while True:
|
|
9453
9894
|
try:
|
|
9454
|
-
if isinstance(o,
|
|
9895
|
+
if isinstance(o, CoroHttpIo.AnyLogIo):
|
|
9455
9896
|
i = None
|
|
9456
9897
|
yield o
|
|
9457
9898
|
|
|
9458
|
-
elif isinstance(o,
|
|
9899
|
+
elif isinstance(o, CoroHttpIo.AnyReadIo):
|
|
9459
9900
|
i = check.isinstance((yield o), bytes)
|
|
9460
9901
|
|
|
9461
9902
|
elif isinstance(o, self._Response):
|
|
@@ -9463,10 +9904,10 @@ class CoroHttpServer:
|
|
|
9463
9904
|
|
|
9464
9905
|
r = self._preprocess_response(o)
|
|
9465
9906
|
hb = self._build_response_head_bytes(r)
|
|
9466
|
-
check.none((yield
|
|
9907
|
+
check.none((yield CoroHttpIo.WriteIo(hb)))
|
|
9467
9908
|
|
|
9468
9909
|
for b in self._yield_response_data(r):
|
|
9469
|
-
yield
|
|
9910
|
+
yield CoroHttpIo.WriteIo(b)
|
|
9470
9911
|
|
|
9471
9912
|
o.close()
|
|
9472
9913
|
if o.close_connection:
|
|
@@ -9494,7 +9935,7 @@ class CoroHttpServer:
|
|
|
9494
9935
|
raise
|
|
9495
9936
|
|
|
9496
9937
|
def _coro_handle_one(self) -> ta.Generator[
|
|
9497
|
-
ta.Union[AnyLogIo, AnyReadIo, _Response],
|
|
9938
|
+
ta.Union[CoroHttpIo.AnyLogIo, CoroHttpIo.AnyReadIo, _Response],
|
|
9498
9939
|
ta.Optional[bytes],
|
|
9499
9940
|
None,
|
|
9500
9941
|
]:
|
|
@@ -9504,7 +9945,7 @@ class CoroHttpServer:
|
|
|
9504
9945
|
sz = next(gen)
|
|
9505
9946
|
while True:
|
|
9506
9947
|
try:
|
|
9507
|
-
line = check.isinstance((yield
|
|
9948
|
+
line = check.isinstance((yield CoroHttpIo.ReadLineIo(sz)), bytes)
|
|
9508
9949
|
sz = gen.send(line)
|
|
9509
9950
|
except StopIteration as e:
|
|
9510
9951
|
parsed = e.value
|
|
@@ -9543,7 +9984,7 @@ class CoroHttpServer:
|
|
|
9543
9984
|
|
|
9544
9985
|
request_data: ta.Optional[bytes]
|
|
9545
9986
|
if (cl := parsed.headers.get('Content-Length')) is not None:
|
|
9546
|
-
request_data = check.isinstance((yield
|
|
9987
|
+
request_data = check.isinstance((yield CoroHttpIo.ReadIo(int(cl))), bytes)
|
|
9547
9988
|
else:
|
|
9548
9989
|
request_data = None
|
|
9549
9990
|
|
|
@@ -10603,7 +11044,7 @@ class CoroHttpServerConnectionFdioHandler(SocketFdioHandler):
|
|
|
10603
11044
|
*,
|
|
10604
11045
|
read_size: int = 0x10000,
|
|
10605
11046
|
write_size: int = 0x10000,
|
|
10606
|
-
log_handler: ta.Optional[ta.Callable[[CoroHttpServer,
|
|
11047
|
+
log_handler: ta.Optional[ta.Callable[[CoroHttpServer, CoroHttpIo.AnyLogIo], None]] = None,
|
|
10607
11048
|
) -> None:
|
|
10608
11049
|
check.state(not sock.getblocking())
|
|
10609
11050
|
|
|
@@ -10623,13 +11064,13 @@ class CoroHttpServerConnectionFdioHandler(SocketFdioHandler):
|
|
|
10623
11064
|
)
|
|
10624
11065
|
self._srv_coro: ta.Optional[
|
|
10625
11066
|
ta.Generator[
|
|
10626
|
-
|
|
11067
|
+
CoroHttpIo.Io,
|
|
10627
11068
|
ta.Optional[bytes],
|
|
10628
11069
|
CoroHttpServer.CoroHandleResult,
|
|
10629
11070
|
],
|
|
10630
11071
|
] = self._coro_srv.coro_handle()
|
|
10631
11072
|
|
|
10632
|
-
self._cur_io: ta.Optional[
|
|
11073
|
+
self._cur_io: ta.Optional[CoroHttpIo.Io] = None
|
|
10633
11074
|
self._next_io()
|
|
10634
11075
|
|
|
10635
11076
|
#
|
|
@@ -10652,22 +11093,22 @@ class CoroHttpServerConnectionFdioHandler(SocketFdioHandler):
|
|
|
10652
11093
|
o = None
|
|
10653
11094
|
break
|
|
10654
11095
|
|
|
10655
|
-
if isinstance(o,
|
|
11096
|
+
if isinstance(o, CoroHttpIo.AnyLogIo):
|
|
10656
11097
|
if self._log_handler is not None:
|
|
10657
11098
|
self._log_handler(self._coro_srv, o)
|
|
10658
11099
|
o = None
|
|
10659
11100
|
|
|
10660
|
-
elif isinstance(o,
|
|
11101
|
+
elif isinstance(o, CoroHttpIo.ReadIo):
|
|
10661
11102
|
if (d := self._read_buf.read(o.sz)) is None:
|
|
10662
11103
|
break
|
|
10663
11104
|
o = None
|
|
10664
11105
|
|
|
10665
|
-
elif isinstance(o,
|
|
11106
|
+
elif isinstance(o, CoroHttpIo.ReadLineIo):
|
|
10666
11107
|
if (d := self._read_buf.read_until(b'\n')) is None:
|
|
10667
11108
|
break
|
|
10668
11109
|
o = None
|
|
10669
11110
|
|
|
10670
|
-
elif isinstance(o,
|
|
11111
|
+
elif isinstance(o, CoroHttpIo.WriteIo):
|
|
10671
11112
|
check.none(self._write_buf)
|
|
10672
11113
|
self._write_buf = IncrementalWriteBuffer(o.data, write_size=self._write_size)
|
|
10673
11114
|
break
|
|
@@ -10701,11 +11142,11 @@ class CoroHttpServerConnectionFdioHandler(SocketFdioHandler):
|
|
|
10701
11142
|
|
|
10702
11143
|
self._read_buf.feed(buf)
|
|
10703
11144
|
|
|
10704
|
-
if isinstance(self._cur_io,
|
|
11145
|
+
if isinstance(self._cur_io, CoroHttpIo.AnyReadIo):
|
|
10705
11146
|
self._next_io()
|
|
10706
11147
|
|
|
10707
11148
|
def on_writable(self) -> None:
|
|
10708
|
-
check.isinstance(self._cur_io,
|
|
11149
|
+
check.isinstance(self._cur_io, CoroHttpIo.WriteIo)
|
|
10709
11150
|
wb = check.not_none(self._write_buf)
|
|
10710
11151
|
while wb.rem > 0:
|
|
10711
11152
|
def send(d: bytes) -> int:
|