omlish 0.0.0.dev368__py3-none-any.whl → 0.0.0.dev369__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.
@@ -0,0 +1,86 @@
1
+ # @omlish-lite
2
+ # ruff: noqa: UP006 UP007 UP043 UP045
3
+ # PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
4
+ # --------------------------------------------
5
+ #
6
+ # 1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and the Individual or Organization
7
+ # ("Licensee") accessing and otherwise using this software ("Python") in source or binary form and its associated
8
+ # documentation.
9
+ #
10
+ # 2. Subject to the terms and conditions of this License Agreement, PSF hereby grants Licensee a nonexclusive,
11
+ # royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative
12
+ # works, distribute, and otherwise use Python alone or in any derivative version, provided, however, that PSF's License
13
+ # Agreement and PSF's notice of copyright, i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
14
+ # 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 Python Software Foundation; All Rights Reserved" are retained in Python
15
+ # alone or in any derivative version prepared by Licensee.
16
+ #
17
+ # 3. In the event Licensee prepares a derivative work that is based on or incorporates Python or any part thereof, and
18
+ # wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in
19
+ # any such work a brief summary of the changes made to Python.
20
+ #
21
+ # 4. PSF is making Python available to Licensee on an "AS IS" basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES,
22
+ # EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY
23
+ # OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT INFRINGE ANY THIRD PARTY
24
+ # RIGHTS.
25
+ #
26
+ # 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL
27
+ # DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, OR ANY DERIVATIVE THEREOF, EVEN IF
28
+ # ADVISED OF THE POSSIBILITY THEREOF.
29
+ #
30
+ # 6. This License Agreement will automatically terminate upon a material breach of its terms and conditions.
31
+ #
32
+ # 7. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint
33
+ # venture between PSF and Licensee. This License Agreement does not grant permission to use PSF trademarks or trade
34
+ # name in a trademark sense to endorse or promote products or services of Licensee, or any third party.
35
+ #
36
+ # 8. By copying, installing or otherwise using Python, Licensee agrees to be bound by the terms and conditions of this
37
+ # License Agreement.
38
+ import typing as ta
39
+
40
+ from ....lite.check import check
41
+ from .errors import CoroHttpClientErrors
42
+ from .io import CoroHttpClientIo
43
+
44
+
45
+ #
46
+
47
+
48
+ class CoroHttpClientStatusLine(ta.NamedTuple):
49
+ version: str
50
+ status: int
51
+ reason: str
52
+
53
+ @classmethod
54
+ def read(cls) -> ta.Generator[CoroHttpClientIo.Io, ta.Optional[bytes], 'CoroHttpClientStatusLine']:
55
+ line = str(check.isinstance((yield CoroHttpClientIo.ReadLineIo(CoroHttpClientIo.MAX_LINE + 1)), bytes), 'iso-8859-1') # noqa
56
+ if len(line) > CoroHttpClientIo.MAX_LINE:
57
+ raise CoroHttpClientErrors.LineTooLongError(CoroHttpClientErrors.LineTooLongError.LineType.STATUS)
58
+ if not line:
59
+ # Presumably, the server closed the connection before sending a valid response.
60
+ raise CoroHttpClientErrors.RemoteDisconnectedError('Remote end closed connection without response')
61
+
62
+ version = ''
63
+ reason = ''
64
+ status_str = ''
65
+ try:
66
+ version, status_str, reason = line.split(None, 2)
67
+ except ValueError:
68
+ try:
69
+ version, status_str = line.split(None, 1)
70
+ except ValueError:
71
+ # empty version will cause next test to fail.
72
+ pass
73
+
74
+ if not version.startswith('HTTP/'):
75
+ raise CoroHttpClientErrors.BadStatusLineError(line)
76
+
77
+ # The status code is a three-digit number
78
+ try:
79
+ status = int(status_str)
80
+ except ValueError:
81
+ raise CoroHttpClientErrors.BadStatusLineError(line) from None
82
+
83
+ if status < 100 or status > 999:
84
+ raise CoroHttpClientErrors.BadStatusLineError(line)
85
+
86
+ return cls(version, status, reason)
@@ -0,0 +1,109 @@
1
+ # @omlish-lite
2
+ # ruff: noqa: UP006 UP007 UP043 UP045
3
+ # PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
4
+ # --------------------------------------------
5
+ #
6
+ # 1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and the Individual or Organization
7
+ # ("Licensee") accessing and otherwise using this software ("Python") in source or binary form and its associated
8
+ # documentation.
9
+ #
10
+ # 2. Subject to the terms and conditions of this License Agreement, PSF hereby grants Licensee a nonexclusive,
11
+ # royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative
12
+ # works, distribute, and otherwise use Python alone or in any derivative version, provided, however, that PSF's License
13
+ # Agreement and PSF's notice of copyright, i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
14
+ # 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 Python Software Foundation; All Rights Reserved" are retained in Python
15
+ # alone or in any derivative version prepared by Licensee.
16
+ #
17
+ # 3. In the event Licensee prepares a derivative work that is based on or incorporates Python or any part thereof, and
18
+ # wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in
19
+ # any such work a brief summary of the changes made to Python.
20
+ #
21
+ # 4. PSF is making Python available to Licensee on an "AS IS" basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES,
22
+ # EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY
23
+ # OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT INFRINGE ANY THIRD PARTY
24
+ # RIGHTS.
25
+ #
26
+ # 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL
27
+ # DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, OR ANY DERIVATIVE THEREOF, EVEN IF
28
+ # ADVISED OF THE POSSIBILITY THEREOF.
29
+ #
30
+ # 6. This License Agreement will automatically terminate upon a material breach of its terms and conditions.
31
+ #
32
+ # 7. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint
33
+ # venture between PSF and Licensee. This License Agreement does not grant permission to use PSF trademarks or trade
34
+ # name in a trademark sense to endorse or promote products or services of Licensee, or any third party.
35
+ #
36
+ # 8. By copying, installing or otherwise using Python, Licensee agrees to be bound by the terms and conditions of this
37
+ # License Agreement.
38
+ import http.client
39
+ import re
40
+
41
+
42
+ ##
43
+
44
+
45
+ class CoroHttpClientValidation:
46
+ def __new__(cls, *args, **kwargs): # noqa
47
+ raise TypeError
48
+
49
+ #
50
+
51
+ # These characters are not allowed within HTTP method names to prevent http header injection.
52
+ _CONTAINS_DISALLOWED_METHOD_PCHAR_PAT = re.compile('[\x00-\x1f]')
53
+
54
+ @classmethod
55
+ def validate_method(cls, method: str) -> None:
56
+ """Validate a method name for putrequest."""
57
+
58
+ # prevent http header injection
59
+ match = cls._CONTAINS_DISALLOWED_METHOD_PCHAR_PAT.search(method)
60
+ if match:
61
+ raise ValueError(
62
+ f"method can't contain control characters. {method!r} (found at least {match.group()!r})",
63
+ )
64
+
65
+ #
66
+
67
+ # These characters are not allowed within HTTP URL paths. See https://tools.ietf.org/html/rfc3986#section-3.3 and
68
+ # the # https://tools.ietf.org/html/rfc3986#appendix-A pchar definition.
69
+ # - Prevents CVE-2019-9740. Includes control characters such as \r\n.
70
+ # - We don't restrict chars above \x7f as putrequest() limits us to ASCII.
71
+ _CONTAINS_DISALLOWED_URL_PCHAR_PAT = re.compile('[\x00-\x20\x7f]')
72
+
73
+ @classmethod
74
+ def validate_path(cls, url: str) -> None:
75
+ """Validate a url for putrequest."""
76
+
77
+ # Prevent CVE-2019-9740.
78
+ match = cls._CONTAINS_DISALLOWED_URL_PCHAR_PAT.search(url)
79
+ if match:
80
+ raise http.client.InvalidURL(
81
+ f"URL can't contain control characters. {url!r} (found at least {match.group()!r})",
82
+ )
83
+
84
+ @classmethod
85
+ def validate_host(cls, host: str) -> None:
86
+ """Validate a host so it doesn't contain control characters."""
87
+
88
+ # Prevent CVE-2019-18348.
89
+ match = cls._CONTAINS_DISALLOWED_URL_PCHAR_PAT.search(host)
90
+ if match:
91
+ raise http.client.InvalidURL(
92
+ f"URL can't contain control characters. {host!r} (found at least {match.group()!r})",
93
+ )
94
+
95
+ #
96
+
97
+ # The patterns for both name and value are more lenient than RFC definitions to allow for backwards compatibility.
98
+ _LEGAL_HEADER_NAME_PAT = re.compile(rb'[^:\s][^:\r\n]*')
99
+ _ILLEGAL_HEADER_VALUE_PAT = re.compile(rb'\n(?![ \t])|\r(?![ \t\n])')
100
+
101
+ @classmethod
102
+ def validate_header_name(cls, header: bytes) -> None:
103
+ if not cls._LEGAL_HEADER_NAME_PAT.fullmatch(header):
104
+ raise ValueError(f'Invalid header name {header!r}')
105
+
106
+ @classmethod
107
+ def validate_header_value(cls, value: bytes) -> None:
108
+ if cls._ILLEGAL_HEADER_VALUE_PAT.search(value):
109
+ raise ValueError(f'Invalid header value {value!r}')
File without changes
@@ -3,12 +3,12 @@
3
3
  import socket
4
4
  import typing as ta
5
5
 
6
- from ...io.buffers import IncrementalWriteBuffer
7
- from ...io.buffers import ReadableListBuffer
8
- from ...io.fdio.handlers import SocketFdioHandler
9
- from ...lite.check import check
10
- from ...sockets.addresses import SocketAddress
11
- from ..handlers import HttpHandler
6
+ from ....io.buffers import IncrementalWriteBuffer
7
+ from ....io.buffers import ReadableListBuffer
8
+ from ....io.fdio.handlers import SocketFdioHandler
9
+ from ....lite.check import check
10
+ from ....sockets.addresses import SocketAddress
11
+ from ...handlers import HttpHandler
12
12
  from .server import CoroHttpServer
13
13
 
14
14
 
@@ -62,19 +62,19 @@ import textwrap
62
62
  import time
63
63
  import typing as ta
64
64
 
65
- from ...lite.check import check
66
- from ...sockets.addresses import SocketAddress
67
- from ..handlers import HttpHandler
68
- from ..handlers import HttpHandlerRequest
69
- from ..handlers import HttpHandlerResponseData
70
- from ..handlers import HttpHandlerResponseStreamedData
71
- from ..handlers import UnsupportedMethodHttpHandlerError
72
- from ..parsing import EmptyParsedHttpResult
73
- from ..parsing import HttpRequestParser
74
- from ..parsing import ParsedHttpRequest
75
- from ..parsing import ParseHttpRequestError
76
- from ..versions import HttpProtocolVersion
77
- from ..versions import HttpProtocolVersions
65
+ from ....lite.check import check
66
+ from ....sockets.addresses import SocketAddress
67
+ from ...handlers import HttpHandler
68
+ from ...handlers import HttpHandlerRequest
69
+ from ...handlers import HttpHandlerResponseData
70
+ from ...handlers import HttpHandlerResponseStreamedData
71
+ from ...handlers import UnsupportedMethodHttpHandlerError
72
+ from ...parsing import EmptyParsedHttpResult
73
+ from ...parsing import HttpRequestParser
74
+ from ...parsing import ParsedHttpRequest
75
+ from ...parsing import ParseHttpRequestError
76
+ from ...versions import HttpProtocolVersion
77
+ from ...versions import HttpProtocolVersions
78
78
 
79
79
 
80
80
  CoroHttpServerFactory = ta.Callable[[SocketAddress], 'CoroHttpServer']
@@ -9,22 +9,22 @@ import contextlib
9
9
  import functools
10
10
  import typing as ta
11
11
 
12
- from ...lite.check import check
13
- from ...sockets.addresses import SocketAndAddress
14
- from ...sockets.bind import CanSocketBinder
15
- from ...sockets.bind import SocketBinder
16
- from ...sockets.server.handlers import ExecutorSocketServerHandler
17
- from ...sockets.server.handlers import SocketHandlerSocketServerHandler
18
- from ...sockets.server.handlers import SocketServerHandler
19
- from ...sockets.server.handlers import SocketWrappingSocketServerHandler
20
- from ...sockets.server.handlers import StandardSocketServerHandler
21
- from ...sockets.server.server import SocketServer
22
- from ...sockets.server.ssl import SslErrorHandlingSocketServerHandler
23
- from ...sockets.server.threading import ThreadingSocketServerHandler
24
- from ..handlers import HttpHandler
25
- from ..parsing import HttpRequestParser
26
- from ..versions import HttpProtocolVersion
27
- from ..versions import HttpProtocolVersions
12
+ from ....lite.check import check
13
+ from ....sockets.addresses import SocketAndAddress
14
+ from ....sockets.bind import CanSocketBinder
15
+ from ....sockets.bind import SocketBinder
16
+ from ....sockets.server.handlers import ExecutorSocketServerHandler
17
+ from ....sockets.server.handlers import SocketHandlerSocketServerHandler
18
+ from ....sockets.server.handlers import SocketServerHandler
19
+ from ....sockets.server.handlers import SocketWrappingSocketServerHandler
20
+ from ....sockets.server.handlers import StandardSocketServerHandler
21
+ from ....sockets.server.server import SocketServer
22
+ from ....sockets.server.ssl import SslErrorHandlingSocketServerHandler
23
+ from ....sockets.server.threading import ThreadingSocketServerHandler
24
+ from ...handlers import HttpHandler
25
+ from ...parsing import HttpRequestParser
26
+ from ...versions import HttpProtocolVersion
27
+ from ...versions import HttpProtocolVersions
28
28
  from .server import CoroHttpServer
29
29
  from .sockets import CoroHttpServerSocketHandler
30
30
 
@@ -3,10 +3,10 @@
3
3
  import itertools
4
4
  import typing as ta
5
5
 
6
- from ...lite.check import check
7
- from ...sockets.addresses import SocketAddress
8
- from ...sockets.handlers import SocketHandler_
9
- from ...sockets.io import SocketIoPair
6
+ from ....lite.check import check
7
+ from ....sockets.addresses import SocketAddress
8
+ from ....sockets.handlers import SocketHandler_
9
+ from ....sockets.io import SocketIoPair
10
10
  from .server import CoroHttpServer
11
11
  from .server import CoroHttpServerFactory
12
12
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: omlish
3
- Version: 0.0.0.dev368
3
+ Version: 0.0.0.dev369
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -1,5 +1,5 @@
1
1
  omlish/.manifests.json,sha256=aT8yZ-Zh-9wfHl5Ym5ouiWC1i0cy7Q7RlhzavB6VLPI,8587
2
- omlish/__about__.py,sha256=biDAj0KZwKzNN8Ba6UcrJ9VQV3_cdOZt2lA7-prjepc,3478
2
+ omlish/__about__.py,sha256=z2SR3MJ-rRBdt9JGCcv-dKC9J_Pxa9JxjIfu-Cp9uWM,3478
3
3
  omlish/__init__.py,sha256=SsyiITTuK0v74XpKV8dqNaCmjOlan1JZKrHQv5rWKPA,253
4
4
  omlish/c3.py,sha256=rer-TPOFDU6fYq_AWio_AmA-ckZ8JDY5shIzQ_yXfzA,8414
5
5
  omlish/cached.py,sha256=MLap_p0rdGoDIMVhXVHm1tsbcWobJF0OanoodV03Ju8,542
@@ -342,10 +342,19 @@ omlish/http/clients/default.py,sha256=fO8So3pI2z8ateLqt9Sv50UoOJFkUZbgMdoDyWsjBN
342
342
  omlish/http/clients/httpx.py,sha256=Grl9_sG7QNIZj8HqaU7XduAsBDyfXl36RjbYQzQqal0,1787
343
343
  omlish/http/clients/urllib.py,sha256=DVKFPLQzANiZmwnlbFw5pWs5ZPLLvvgCb3UInvCSqPE,2701
344
344
  omlish/http/coro/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
345
- omlish/http/coro/fdio.py,sha256=Dc7xKlo5bPZMxpiNwZUxYhdd0kDGoxAtQ11KtbAWb0o,4151
346
- omlish/http/coro/server.py,sha256=94KsfrORaPHlbM0JXxwd6C63LP22L_Xp1QGvVm84Rlo,18647
347
- omlish/http/coro/simple.py,sha256=a6ZOPfVndsRz_I3ihJK43yN88mhKTgxVZEtUlSs4NF4,3280
348
- omlish/http/coro/sockets.py,sha256=ziTzdDCsw3mrwskoGBa4stqkm21ReNq6BtrM-ZkxB3k,2257
345
+ omlish/http/coro/client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
346
+ omlish/http/coro/client/client.py,sha256=qzWo10R5LJJ2z32HDVoCHxW5fIeytpluK7DGMIaZ0Og,30890
347
+ omlish/http/coro/client/errors.py,sha256=_jwsO9wfwA22ybvkdKnKS6Kbac_qoGbDmuIJbJdjusc,1254
348
+ omlish/http/coro/client/headers.py,sha256=Mgm5rXFTlpLwUW9Dy-7AhnSbTY-DAhrXs_2XCHPRq-o,4666
349
+ omlish/http/coro/client/io.py,sha256=5FGcTyHT-B99RFKc920aERC14vgRXs094v9aXXbaIxc,809
350
+ omlish/http/coro/client/response.py,sha256=joihD-ft5cDw_dvSDaqmIEFkSS8GQ13bwiJ1VE7xYm4,17716
351
+ omlish/http/coro/client/status.py,sha256=EdiScV6lcbVHWNUTyXp7qOBJKh5QYO2TNUCNADitOI0,4266
352
+ omlish/http/coro/client/validation.py,sha256=Hhy_CLN3Z7ZTVGEtPaHzqzDR50ReHKopHKukl8spLYU,5185
353
+ omlish/http/coro/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
354
+ omlish/http/coro/server/fdio.py,sha256=qZE4g5y4XESsTObSKyVggI-yzig57gSGJb4Z0rcHvgo,4157
355
+ omlish/http/coro/server/server.py,sha256=5gvueSCUzqBqQRf0GJ6wGroD9DiWxQNi6N17MlEtBLU,18660
356
+ omlish/http/coro/server/simple.py,sha256=j1RZ3niKrgGM2qFnjdYWn_eniZzay5j49Ca4L3u8vO4,3296
357
+ omlish/http/coro/server/sockets.py,sha256=24gU6wpIZuzYWKQD8UsHyYfTZlbcUFvkqXq5KVgWpQo,2261
349
358
  omlish/inject/__init__.py,sha256=pY-A8Q4v08-Xa4a-XdZ3lSFC3OwCO2T9HhesB67Q4tQ,1895
350
359
  omlish/inject/binder.py,sha256=3-6KMOcSgFE5bvthy3YUrRzCX5w7YSGmdJ3Tv2yXZGw,4022
351
360
  omlish/inject/bindings.py,sha256=PlvOnUREjvc6F8nOJdzl1k9SAf80icRB4qWFqDop87M,536
@@ -873,9 +882,9 @@ omlish/typedvalues/marshal.py,sha256=AtBz7Jq-BfW8vwM7HSxSpR85JAXmxK2T0xDblmm1HI0
873
882
  omlish/typedvalues/of_.py,sha256=UXkxSj504WI2UrFlqdZJbu2hyDwBhL7XVrc2qdR02GQ,1309
874
883
  omlish/typedvalues/reflect.py,sha256=PAvKW6T4cW7u--iX80w3HWwZUS3SmIZ2_lQjT65uAyk,1026
875
884
  omlish/typedvalues/values.py,sha256=ym46I-q2QJ_6l4UlERqv3yj87R-kp8nCKMRph0xQ3UA,1307
876
- omlish-0.0.0.dev368.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
877
- omlish-0.0.0.dev368.dist-info/METADATA,sha256=Ph1mKrNEK3shLSCZ1tB8AQp7iAlOXVNhKqBCD9XbRIU,4416
878
- omlish-0.0.0.dev368.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
879
- omlish-0.0.0.dev368.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
880
- omlish-0.0.0.dev368.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
881
- omlish-0.0.0.dev368.dist-info/RECORD,,
885
+ omlish-0.0.0.dev369.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
886
+ omlish-0.0.0.dev369.dist-info/METADATA,sha256=bUWJ-6YrZYvPAMHccs62WvjREQptgR2l-rx_ApYK824,4416
887
+ omlish-0.0.0.dev369.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
888
+ omlish-0.0.0.dev369.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
889
+ omlish-0.0.0.dev369.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
890
+ omlish-0.0.0.dev369.dist-info/RECORD,,