ominfra 0.0.0.dev448__py3-none-any.whl → 0.0.0.dev488__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ominfra/__about__.py +4 -1
- ominfra/clouds/aws/instancetypes/cache.json.gz +0 -0
- ominfra/clouds/aws/models/{base.py → base/__init__.py} +6 -0
- ominfra/clouds/aws/models/base/_dataclasses.py +721 -0
- ominfra/clouds/aws/models/gen/cli.py +2 -1
- ominfra/clouds/aws/models/gen/gen.py +16 -7
- ominfra/clouds/aws/models/services/{ec2.py → ec2/__init__.py} +121 -1
- ominfra/clouds/aws/models/services/ec2/_dataclasses.py +30654 -0
- ominfra/clouds/aws/models/services/{lambda_.py → lambda_/__init__.py} +139 -1
- ominfra/clouds/aws/models/services/lambda_/_dataclasses.py +4182 -0
- ominfra/clouds/aws/models/services/{rds.py → rds/__init__.py} +244 -78
- ominfra/clouds/aws/models/services/rds/_dataclasses.py +8231 -0
- ominfra/clouds/aws/models/services/{s3.py → s3/__init__.py} +9 -1
- ominfra/clouds/aws/models/services/s3/_dataclasses.py +5014 -0
- ominfra/manage/main.py +1 -2
- ominfra/manage/targets/bestpython.sh +1 -1
- ominfra/scripts/journald2aws.py +253 -29
- ominfra/scripts/manage.py +276 -42
- ominfra/scripts/supervisor.py +299 -25
- {ominfra-0.0.0.dev448.dist-info → ominfra-0.0.0.dev488.dist-info}/METADATA +5 -3
- {ominfra-0.0.0.dev448.dist-info → ominfra-0.0.0.dev488.dist-info}/RECORD +25 -20
- {ominfra-0.0.0.dev448.dist-info → ominfra-0.0.0.dev488.dist-info}/WHEEL +0 -0
- {ominfra-0.0.0.dev448.dist-info → ominfra-0.0.0.dev488.dist-info}/entry_points.txt +0 -0
- {ominfra-0.0.0.dev448.dist-info → ominfra-0.0.0.dev488.dist-info}/licenses/LICENSE +0 -0
- {ominfra-0.0.0.dev448.dist-info → ominfra-0.0.0.dev488.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
|
|
|
@@ -3156,6 +3301,12 @@ def format_num_bytes(num_bytes: int) -> str:
|
|
|
3156
3301
|
|
|
3157
3302
|
##
|
|
3158
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
|
+
#
|
|
3159
3310
|
|
|
3160
3311
|
|
|
3161
3312
|
@dc.dataclass(frozen=True)
|
|
@@ -4281,6 +4432,8 @@ class CoroHttpIo:
|
|
|
4281
4432
|
args: ta.Tuple[ta.Any, ...]
|
|
4282
4433
|
kwargs: ta.Optional[ta.Dict[str, ta.Any]] = None
|
|
4283
4434
|
|
|
4435
|
+
server_hostname: ta.Optional[str] = None
|
|
4436
|
+
|
|
4284
4437
|
#
|
|
4285
4438
|
|
|
4286
4439
|
class CloseIo(Io):
|
|
@@ -4725,6 +4878,10 @@ class HttpRequestParser:
|
|
|
4725
4878
|
|
|
4726
4879
|
########################################
|
|
4727
4880
|
# ../../../omlish/io/buffers.py
|
|
4881
|
+
"""
|
|
4882
|
+
TODO:
|
|
4883
|
+
- overhaul and just coro-ify pyio?
|
|
4884
|
+
"""
|
|
4728
4885
|
|
|
4729
4886
|
|
|
4730
4887
|
##
|
|
@@ -4903,6 +5060,9 @@ class ReadableListBuffer:
|
|
|
4903
5060
|
|
|
4904
5061
|
self._lst: list[bytes] = []
|
|
4905
5062
|
|
|
5063
|
+
def __bool__(self) -> ta.NoReturn:
|
|
5064
|
+
raise TypeError("Use 'buf is not None' or 'len(buf)'.")
|
|
5065
|
+
|
|
4906
5066
|
def __len__(self) -> int:
|
|
4907
5067
|
return sum(map(len, self._lst))
|
|
4908
5068
|
|
|
@@ -4928,6 +5088,9 @@ class ReadableListBuffer:
|
|
|
4928
5088
|
|
|
4929
5089
|
def read(self, n: ta.Optional[int] = None) -> ta.Optional[bytes]:
|
|
4930
5090
|
if n is None:
|
|
5091
|
+
if not self._lst:
|
|
5092
|
+
return b''
|
|
5093
|
+
|
|
4931
5094
|
o = b''.join(self._lst)
|
|
4932
5095
|
self._lst = []
|
|
4933
5096
|
return o
|
|
@@ -4966,6 +5129,110 @@ class ReadableListBuffer:
|
|
|
4966
5129
|
r = self.read_until_(delim)
|
|
4967
5130
|
return r if isinstance(r, bytes) else None
|
|
4968
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
|
+
|
|
4969
5236
|
|
|
4970
5237
|
##
|
|
4971
5238
|
|
|
@@ -6267,6 +6534,13 @@ class _EmptyMaybe(_Maybe[T]):
|
|
|
6267
6534
|
Maybe._empty = _EmptyMaybe() # noqa
|
|
6268
6535
|
|
|
6269
6536
|
|
|
6537
|
+
##
|
|
6538
|
+
|
|
6539
|
+
|
|
6540
|
+
setattr(Maybe, 'just', _JustMaybe) # noqa
|
|
6541
|
+
setattr(Maybe, 'empty', functools.partial(operator.attrgetter('_empty'), Maybe))
|
|
6542
|
+
|
|
6543
|
+
|
|
6270
6544
|
########################################
|
|
6271
6545
|
# ../../../omlish/lite/runtime.py
|
|
6272
6546
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ominfra
|
|
3
|
-
Version: 0.0.0.
|
|
3
|
+
Version: 0.0.0.dev488
|
|
4
4
|
Summary: ominfra
|
|
5
5
|
Author: wrmsr
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -14,11 +14,13 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
14
14
|
Requires-Python: >=3.13
|
|
15
15
|
Description-Content-Type: text/markdown
|
|
16
16
|
License-File: LICENSE
|
|
17
|
-
Requires-Dist:
|
|
18
|
-
Requires-Dist: omlish==0.0.0.dev448
|
|
17
|
+
Requires-Dist: omlish==0.0.0.dev488
|
|
19
18
|
Provides-Extra: all
|
|
19
|
+
Requires-Dist: omdev==0.0.0.dev488; extra == "all"
|
|
20
20
|
Requires-Dist: paramiko~=4.0; extra == "all"
|
|
21
21
|
Requires-Dist: asyncssh~=2.21; extra == "all"
|
|
22
|
+
Provides-Extra: omdev
|
|
23
|
+
Requires-Dist: omdev==0.0.0.dev488; extra == "omdev"
|
|
22
24
|
Provides-Extra: ssh
|
|
23
25
|
Requires-Dist: paramiko~=4.0; extra == "ssh"
|
|
24
26
|
Requires-Dist: asyncssh~=2.21; extra == "ssh"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
ominfra/.omlish-manifests.json,sha256=sN48-JQtCfdTxhbjsptBC3imaHlipvaKH9UT5KaYzHI,577
|
|
2
|
-
ominfra/__about__.py,sha256=
|
|
2
|
+
ominfra/__about__.py,sha256=Mcj9ucEgr7TFIg6CQ-fjexk6mdFrh6tGj-Eu6jr7gis,740
|
|
3
3
|
ominfra/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
ominfra/pyremote.py,sha256=hCoh0m-yxAoHOTB_tG8nwqq_CEXxIF0MTZ0A5eaZcSM,16529
|
|
5
5
|
ominfra/systemd.py,sha256=-tk4qeQF9py98AtK5VVGYwcgQ_mJPanEWbemoU-nmbY,1028
|
|
@@ -14,7 +14,7 @@ ominfra/clouds/aws/logs.py,sha256=SW8ebBJrUTDG0dnYIld4zbWNVCkAHzFZq4kpn76yWTo,54
|
|
|
14
14
|
ominfra/clouds/aws/metadata.py,sha256=71LtmJxjdlp_HN19zXQTX4ZLO4KI5LLiQ6fHuF8vUis,2772
|
|
15
15
|
ominfra/clouds/aws/instancetypes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
16
|
ominfra/clouds/aws/instancetypes/__main__.py,sha256=Jsrv3P7LX2Cg08W7ByZfZ1JQT4lgLDPW1qNAmShFuMk,75
|
|
17
|
-
ominfra/clouds/aws/instancetypes/cache.json.gz,sha256=
|
|
17
|
+
ominfra/clouds/aws/instancetypes/cache.json.gz,sha256=0_8njOL6g970ZRMf9yzKqdvoqYjviyeyrpJhTCqCyHI,34838
|
|
18
18
|
ominfra/clouds/aws/instancetypes/cache.py,sha256=tEH7bH6kTTqgXcwsNk5Rf7eCf14vsnEHMV6q-PbZc4M,338
|
|
19
19
|
ominfra/clouds/aws/instancetypes/cli.py,sha256=yNxUZjbud5M9tBZZbfiswa8jGQaKJ3YVwxFIMQTo2sA,2207
|
|
20
20
|
ominfra/clouds/aws/journald2aws/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
|
|
@@ -24,17 +24,22 @@ ominfra/clouds/aws/journald2aws/driver.py,sha256=I6kdHW1OH_xgSx4Nhec5EuXb3svaIVK
|
|
|
24
24
|
ominfra/clouds/aws/journald2aws/main.py,sha256=SfRgPiYCllCHBWYy5T4e7ArqrsFb-xD4xLWBg1JH5EY,2184
|
|
25
25
|
ominfra/clouds/aws/journald2aws/poster.py,sha256=8Uib3-be3yGi_ZiZjnsk2jcJWezSFfZ2v9AQVE2_yjg,2907
|
|
26
26
|
ominfra/clouds/aws/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
27
|
-
ominfra/clouds/aws/models/base.py,sha256=
|
|
27
|
+
ominfra/clouds/aws/models/base/__init__.py,sha256=SC_myxNVJdU4zdWFUQv9HtozRlUlm91-tSvJwJ7Jt-8,3818
|
|
28
|
+
ominfra/clouds/aws/models/base/_dataclasses.py,sha256=8wnM5TojU9sfkNnMub-G5cv3GKz3jYY_nn669GmCWhw,32074
|
|
28
29
|
ominfra/clouds/aws/models/gen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
29
30
|
ominfra/clouds/aws/models/gen/__main__.py,sha256=Jsrv3P7LX2Cg08W7ByZfZ1JQT4lgLDPW1qNAmShFuMk,75
|
|
30
|
-
ominfra/clouds/aws/models/gen/cli.py,sha256=
|
|
31
|
-
ominfra/clouds/aws/models/gen/gen.py,sha256=
|
|
31
|
+
ominfra/clouds/aws/models/gen/cli.py,sha256=BTKyEqHi2X5iBv2nqKPdxNB87tV7AtGCYXh7CO7Kx9w,3929
|
|
32
|
+
ominfra/clouds/aws/models/gen/gen.py,sha256=MuWbi1tz7pgGvwGVZSvQYACWthD944A1xptCavZVbaU,16088
|
|
32
33
|
ominfra/clouds/aws/models/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
33
|
-
ominfra/clouds/aws/models/services/ec2.py,sha256=oKa2jk-6BRrgFnTZNvDG15b6K5wbn6sq5evVG6f7N6U,281283
|
|
34
|
-
ominfra/clouds/aws/models/services/lambda_.py,sha256=dp2I4ZVDb6Dci15XcjPPURUElyzH8cwhM911J_HM7Qo,25823
|
|
35
|
-
ominfra/clouds/aws/models/services/rds.py,sha256=ziHgTwFZwl2FnyOyZMg3yJT_29-e0Z4RXBtWUaFfRr4,60108
|
|
36
|
-
ominfra/clouds/aws/models/services/s3.py,sha256=aWbl4YtAiQyBfcNgerNxfWBIHZsbpFlT66JdRBYnQ9c,51426
|
|
37
34
|
ominfra/clouds/aws/models/services/services.toml,sha256=njiWEctmUUrfzZh-aboCNP9BpYBpxGFAVaGvgtv3pMo,866
|
|
35
|
+
ominfra/clouds/aws/models/services/ec2/__init__.py,sha256=RhRnR54FctU8f5jehTzjYt3pkZu4Oc1YDBAKFDt4orw,285635
|
|
36
|
+
ominfra/clouds/aws/models/services/ec2/_dataclasses.py,sha256=MTxjS0JjH49jlYSdW-KqR3boleAXAoa_BG-fvZeqTfQ,1679698
|
|
37
|
+
ominfra/clouds/aws/models/services/lambda_/__init__.py,sha256=OetGhM6FjJYK543Ne-gBu-bkLwcH79-ZLWz6s0AN_Ag,31516
|
|
38
|
+
ominfra/clouds/aws/models/services/lambda_/_dataclasses.py,sha256=MU5pZixiFQ62FsEjDDHF3HEwYmGVoPoXZzkImA7k1fI,218504
|
|
39
|
+
ominfra/clouds/aws/models/services/rds/__init__.py,sha256=doyw5F_QI92cTs_7yLcRymgvSAdWAgKPdI5q6GtTtt0,65671
|
|
40
|
+
ominfra/clouds/aws/models/services/rds/_dataclasses.py,sha256=Ee1r1KdwsRm3MtbzvVKw7XzEbC2O0rle-6ciK0gCd-g,488347
|
|
41
|
+
ominfra/clouds/aws/models/services/s3/__init__.py,sha256=I-cbhtnO_TjQBc08uv9pYdhLeGjUOUbQhYa0HJQP-2o,51538
|
|
42
|
+
ominfra/clouds/aws/models/services/s3/_dataclasses.py,sha256=UsJMk3SXFLCnhhgmv1DpA3cYdOK-Rk_yIbDiGxdF4Nk,295884
|
|
38
43
|
ominfra/clouds/gcp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
39
44
|
ominfra/clouds/gcp/api.py,sha256=gieBJUNEH2OQ4F02lkm9bGUES1wgE6Ow5x9m4MZZpJ8,278
|
|
40
45
|
ominfra/clouds/gcp/auth.py,sha256=W45WRDiWQ1gscZ6sfe7Ob7_Sh6K2WxSKhCBWxTfoo-o,1365
|
|
@@ -52,7 +57,7 @@ ominfra/manage/bootstrap.py,sha256=QMM7SWBzzI8AkeU_9NVJgpKS5TVPTeB_-6Q9i_2zjEo,4
|
|
|
52
57
|
ominfra/manage/bootstrap_.py,sha256=3gb4VeM_5WGCXy6aEgXld8q8r43fMvA606ZOJqU1eu0,667
|
|
53
58
|
ominfra/manage/config.py,sha256=HW0GPeFp9FDFp3sSuvpL4ntjOEP8XbNE1wZVMIpZNkg,195
|
|
54
59
|
ominfra/manage/inject.py,sha256=tqbvdeiJEyH5s3M2kWpW_K0S9NxxvZuPtcDkx2iZlVw,2100
|
|
55
|
-
ominfra/manage/main.py,sha256=
|
|
60
|
+
ominfra/manage/main.py,sha256=Rq7D8g4YkKZOGk2jFFG3Z03GFIww8VbZW7hNCOV4oJM,4509
|
|
56
61
|
ominfra/manage/marshal.py,sha256=xIsqgtOJS_3m-byZRtZGKr7TVM5AjnmOB6euNCnXbAo,310
|
|
57
62
|
ominfra/manage/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
58
63
|
ominfra/manage/commands/base.py,sha256=pbBHMmqHyFMtqpJW8RiElVyKLh_rKPPD3PiYB0XmQrE,4063
|
|
@@ -107,14 +112,14 @@ ominfra/manage/system/packages.py,sha256=GJLcBCEL0w1TmAUqUd8sGSSoU4Kb5Q1wDbVbX7i
|
|
|
107
112
|
ominfra/manage/system/platforms.py,sha256=Nm_WLP9_2Ec6Ba755NZM8NF5yRtAaxMC5B4dvHXDHuY,1289
|
|
108
113
|
ominfra/manage/targets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
109
114
|
ominfra/manage/targets/bestpython.py,sha256=nzTt6ssuhKPmKSMTt_Vrlx6mIUEAx7T-DsP_MJCiDVM,636
|
|
110
|
-
ominfra/manage/targets/bestpython.sh,sha256=
|
|
115
|
+
ominfra/manage/targets/bestpython.sh,sha256=GyHXYb65knSALeL76405k7Ijw4kacGQz2v5iYqCxMhg,350
|
|
111
116
|
ominfra/manage/targets/connection.py,sha256=mOHCsDVG-DZBhl3Mb7TTr1vhPb0gxDOOMW1xhD1ImiE,5071
|
|
112
117
|
ominfra/manage/targets/inject.py,sha256=3M4wBkxtvymq_yhiotHlTN8iydELMjVCndyp9Bq-4eo,1572
|
|
113
118
|
ominfra/manage/targets/targets.py,sha256=LjSQrDsHEjEQMDHcxtNKmLjy0YGLXJRGPFdUjazzFIM,1918
|
|
114
119
|
ominfra/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
115
|
-
ominfra/scripts/journald2aws.py,sha256=
|
|
116
|
-
ominfra/scripts/manage.py,sha256=
|
|
117
|
-
ominfra/scripts/supervisor.py,sha256=
|
|
120
|
+
ominfra/scripts/journald2aws.py,sha256=trL-pM-eKhkXQzTHqxyZ2OzlHS2-hMmmhLrn_wrahPc,256511
|
|
121
|
+
ominfra/scripts/manage.py,sha256=wAg9PvKF_EThMnmYyGWsx46zq3lespOmmkkRH09-Fyg,486314
|
|
122
|
+
ominfra/scripts/supervisor.py,sha256=NiG-QBeBZC6xmunAJvmNQLXB9zQN-Ea0dq_0gPD_V2s,394159
|
|
118
123
|
ominfra/supervisor/LICENSE.txt,sha256=ZrHY15PVR98y26Yg6iQfa-SXnUaYTDhrUsPVcEO5OKM,1874
|
|
119
124
|
ominfra/supervisor/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
|
|
120
125
|
ominfra/supervisor/__main__.py,sha256=I0yFw-C08OOiZ3BF6lF1Oiv789EQXu-_j6whDhQUTEA,66
|
|
@@ -156,9 +161,9 @@ ominfra/tailscale/api.py,sha256=XASv9C_CWI-u-yX5jVzhJrkJhlwQRkYQWQQG1uJwAd8,1375
|
|
|
156
161
|
ominfra/tailscale/cli.py,sha256=zRV7-tKB7kBah1oTVZlol-vwx1FBlnfzYAPGkeU5jX4,3543
|
|
157
162
|
ominfra/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
158
163
|
ominfra/tools/listresources.py,sha256=ePmo7cUAiBZARkM_3K4GKYZXxV73An_aioS1m-AAJis,6181
|
|
159
|
-
ominfra-0.0.0.
|
|
160
|
-
ominfra-0.0.0.
|
|
161
|
-
ominfra-0.0.0.
|
|
162
|
-
ominfra-0.0.0.
|
|
163
|
-
ominfra-0.0.0.
|
|
164
|
-
ominfra-0.0.0.
|
|
164
|
+
ominfra-0.0.0.dev488.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
|
165
|
+
ominfra-0.0.0.dev488.dist-info/METADATA,sha256=wFmzStBj8h8t1OkvO5xPNUvmc5FM9yZS8kJOAW57yJw,2468
|
|
166
|
+
ominfra-0.0.0.dev488.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
167
|
+
ominfra-0.0.0.dev488.dist-info/entry_points.txt,sha256=kgecQ2MgGrM9qK744BoKS3tMesaC3yjLnl9pa5CRczg,37
|
|
168
|
+
ominfra-0.0.0.dev488.dist-info/top_level.txt,sha256=E-b2OHkk_AOBLXHYZQ2EOFKl-_6uOGd8EjeG-Zy6h_w,8
|
|
169
|
+
ominfra-0.0.0.dev488.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|