omlish 0.0.0.dev218__py3-none-any.whl → 0.0.0.dev219__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
omlish/__about__.py CHANGED
@@ -1,5 +1,5 @@
1
- __version__ = '0.0.0.dev218'
2
- __revision__ = '0d15b9d5ec9832621506a90856baf7d140dd63ad'
1
+ __version__ = '0.0.0.dev219'
2
+ __revision__ = '5e741e0670fb75899653bd454587a1cf2add710f'
3
3
 
4
4
 
5
5
  #
@@ -42,7 +42,7 @@ class Project(ProjectBase):
42
42
  ],
43
43
 
44
44
  'compress': [
45
- 'lz4 ~= 4.3',
45
+ 'lz4 ~= 4.4',
46
46
  # 'lz4 @ git+https://github.com/wrmsr/python-lz4@wrmsr_20240830_GIL_NOT_USED'
47
47
 
48
48
  'python-snappy ~= 0.7',
@@ -65,7 +65,7 @@ import typing as ta
65
65
 
66
66
  from ...lite.check import check
67
67
  from ...sockets.addresses import SocketAddress
68
- from ...sockets.handlers import SocketHandler # noqa
68
+ from ...sockets.handlers import SocketHandler_
69
69
  from ...sockets.io import SocketIoPair
70
70
  from ..handlers import HttpHandler
71
71
  from ..handlers import HttpHandlerRequest
@@ -557,7 +557,7 @@ class CoroHttpServer:
557
557
  ##
558
558
 
559
559
 
560
- class CoroHttpServerSocketHandler: # SocketHandler
560
+ class CoroHttpServerSocketHandler(SocketHandler_):
561
561
  def __init__(
562
562
  self,
563
563
  server_factory: CoroHttpServerFactory,
omlish/http/handlers.py CHANGED
@@ -1,5 +1,6 @@
1
1
  # ruff: noqa: UP006 UP007
2
2
  # @omlish-lite
3
+ import abc
3
4
  import dataclasses as dc
4
5
  import http.server
5
6
  import typing as ta
@@ -45,3 +46,9 @@ class HttpHandlerError(Exception):
45
46
 
46
47
  class UnsupportedMethodHttpHandlerError(Exception):
47
48
  pass
49
+
50
+
51
+ class HttpHandler_(abc.ABC): # noqa
52
+ @abc.abstractmethod
53
+ def __call__(self, req: HttpHandlerRequest) -> HttpHandlerResponse:
54
+ raise NotImplementedError
omlish/http/sessions.py CHANGED
@@ -9,8 +9,8 @@ import typing as ta
9
9
  import zlib
10
10
 
11
11
  from .. import lang
12
- from .. import secrets as sec
13
12
  from ..funcs import pairs as fpa
13
+ from ..secrets import all as sec
14
14
  from .cookies import dump_cookie
15
15
  from .cookies import parse_cookie
16
16
  from .json import JSON_TAGGER
omlish/http/simple.py ADDED
@@ -0,0 +1,101 @@
1
+ # ruff: noqa: UP006 UP007
2
+ # @omlish-lite
3
+ import concurrent.futures as cf
4
+ import contextlib
5
+ import functools
6
+ import typing as ta
7
+
8
+ from ..lite.check import check
9
+ from ..sockets.addresses import SocketAndAddress
10
+ from ..sockets.bind import CanSocketBinder
11
+ from ..sockets.bind import SocketBinder
12
+ from ..sockets.server.handlers import ExecutorSocketServerHandler
13
+ from ..sockets.server.handlers import SocketHandlerSocketServerHandler
14
+ from ..sockets.server.handlers import SocketServerHandler
15
+ from ..sockets.server.handlers import SocketWrappingSocketServerHandler
16
+ from ..sockets.server.handlers import StandardSocketServerHandler
17
+ from ..sockets.server.server import SocketServer
18
+ from ..sockets.server.threading import ThreadingSocketServerHandler
19
+ from .coro.server import CoroHttpServer
20
+ from .coro.server import CoroHttpServerSocketHandler
21
+ from .handlers import HttpHandler
22
+ from .parsing import HttpRequestParser
23
+ from .versions import HttpProtocolVersion
24
+ from .versions import HttpProtocolVersions
25
+
26
+
27
+ if ta.TYPE_CHECKING:
28
+ import ssl
29
+
30
+
31
+ @contextlib.contextmanager
32
+ def make_simple_http_server(
33
+ bind: CanSocketBinder,
34
+ handler: HttpHandler,
35
+ *,
36
+ server_version: HttpProtocolVersion = HttpProtocolVersions.HTTP_1_1,
37
+ ssl_context: ta.Optional['ssl.SSLContext'] = None,
38
+ executor: ta.Optional[cf.Executor] = None,
39
+ use_threads: bool = False,
40
+ ) -> ta.Iterator[SocketServer]:
41
+ check.arg(not (executor is not None and use_threads))
42
+
43
+ #
44
+
45
+ with contextlib.ExitStack() as es:
46
+ server_factory = functools.partial(
47
+ CoroHttpServer,
48
+ handler=handler,
49
+ parser=HttpRequestParser(
50
+ server_version=server_version,
51
+ ),
52
+ )
53
+
54
+ socket_handler = CoroHttpServerSocketHandler(
55
+ server_factory,
56
+ )
57
+
58
+ #
59
+
60
+ server_handler: SocketServerHandler = SocketHandlerSocketServerHandler(
61
+ socket_handler,
62
+ )
63
+
64
+ #
65
+
66
+ if ssl_context is not None:
67
+ server_handler = SocketWrappingSocketServerHandler(
68
+ server_handler,
69
+ SocketAndAddress.socket_wrapper(functools.partial(
70
+ ssl_context.wrap_socket,
71
+ server_side=True,
72
+ )),
73
+ )
74
+
75
+ #
76
+
77
+ server_handler = StandardSocketServerHandler(
78
+ server_handler,
79
+ )
80
+
81
+ #
82
+
83
+ if executor is not None:
84
+ server_handler = ExecutorSocketServerHandler(
85
+ server_handler,
86
+ executor,
87
+ )
88
+
89
+ elif use_threads:
90
+ server_handler = es.enter_context(ThreadingSocketServerHandler(
91
+ server_handler,
92
+ ))
93
+
94
+ #
95
+
96
+ server = es.enter_context(SocketServer(
97
+ SocketBinder.of(bind),
98
+ server_handler,
99
+ ))
100
+
101
+ yield server
@@ -1,24 +0,0 @@
1
- from .secrets import ( # noqa
2
- CachingSecrets,
3
- CompositeSecrets,
4
- EMPTY_SECRETS,
5
- EmptySecrets,
6
- EnvVarSecrets,
7
- FnSecrets,
8
- LoggingSecrets,
9
- MappingSecrets,
10
- Secret,
11
- SecretRef,
12
- SecretRefOrStr,
13
- Secrets,
14
- secret_field,
15
- secret_repr,
16
- )
17
-
18
-
19
- ##
20
-
21
-
22
- from ..lang.imports import _register_conditional_import # noqa
23
-
24
- _register_conditional_import('..marshal', '.marshal', __package__)
omlish/secrets/all.py ADDED
@@ -0,0 +1,16 @@
1
+ from .secrets import ( # noqa
2
+ CachingSecrets,
3
+ CompositeSecrets,
4
+ EMPTY_SECRETS,
5
+ EmptySecrets,
6
+ EnvVarSecrets,
7
+ FnSecrets,
8
+ LoggingSecrets,
9
+ MappingSecrets,
10
+ Secret,
11
+ SecretRef,
12
+ SecretRefOrStr,
13
+ Secrets,
14
+ secret_field,
15
+ secret_repr,
16
+ )
omlish/secrets/secrets.py CHANGED
@@ -335,3 +335,9 @@ class EnvVarSecrets(Secrets):
335
335
  return dct.pop(ekey)
336
336
  else:
337
337
  return dct[ekey]
338
+
339
+
340
+ ##
341
+
342
+
343
+ lang.imports._register_conditional_import('..marshal', '.marshal', __package__) # noqa
@@ -5,7 +5,7 @@ TODO:
5
5
  - codification of https://docs.python.org/3/library/socket.html#socket-families
6
6
  """
7
7
  import dataclasses as dc
8
- import socket
8
+ import socket as socket_
9
9
  import typing as ta
10
10
 
11
11
 
@@ -19,15 +19,15 @@ SocketAddress = ta.Any
19
19
  class SocketAddressInfoArgs:
20
20
  host: ta.Optional[str]
21
21
  port: ta.Union[str, int, None]
22
- family: socket.AddressFamily = socket.AddressFamily.AF_UNSPEC
22
+ family: socket_.AddressFamily = socket_.AddressFamily.AF_UNSPEC
23
23
  type: int = 0
24
24
  proto: int = 0
25
- flags: socket.AddressInfo = socket.AddressInfo(0)
25
+ flags: socket_.AddressInfo = socket_.AddressInfo(0)
26
26
 
27
27
 
28
28
  @dc.dataclass(frozen=True)
29
29
  class SocketAddressInfo:
30
- family: socket.AddressFamily
30
+ family: socket_.AddressFamily
31
31
  type: int
32
32
  proto: int
33
33
  canonname: ta.Optional[str]
@@ -35,28 +35,40 @@ class SocketAddressInfo:
35
35
 
36
36
 
37
37
  class SocketFamilyAndAddress(ta.NamedTuple):
38
- family: socket.AddressFamily
38
+ family: socket_.AddressFamily
39
39
  address: SocketAddress
40
40
 
41
41
 
42
42
  def get_best_socket_family(
43
43
  host: ta.Optional[str],
44
44
  port: ta.Union[str, int, None],
45
- family: ta.Union[int, socket.AddressFamily] = socket.AddressFamily.AF_UNSPEC,
45
+ family: ta.Union[int, socket_.AddressFamily] = socket_.AddressFamily.AF_UNSPEC,
46
46
  ) -> SocketFamilyAndAddress:
47
47
  """https://github.com/python/cpython/commit/f289084c83190cc72db4a70c58f007ec62e75247"""
48
48
 
49
- infos = socket.getaddrinfo(
49
+ infos = socket_.getaddrinfo(
50
50
  host,
51
51
  port,
52
52
  family,
53
- type=socket.SOCK_STREAM,
54
- flags=socket.AI_PASSIVE,
53
+ type=socket_.SOCK_STREAM,
54
+ flags=socket_.AI_PASSIVE,
55
55
  )
56
56
  ai = SocketAddressInfo(*next(iter(infos)))
57
57
  return SocketFamilyAndAddress(ai.family, ai.sockaddr)
58
58
 
59
59
 
60
60
  class SocketAndAddress(ta.NamedTuple):
61
- socket: socket.socket
61
+ socket: socket_.socket
62
62
  address: SocketAddress
63
+
64
+ def wrap_socket(self, fn: ta.Callable[[socket_.socket], socket_.socket]):
65
+ return self._replace(socket=fn(self.socket))
66
+
67
+ @classmethod
68
+ def socket_wrapper(
69
+ cls,
70
+ fn: ta.Callable[[socket_.socket], socket_.socket],
71
+ ) -> ta.Callable[['SocketAndAddress'], 'SocketAndAddress']:
72
+ def inner(conn):
73
+ return conn.wrap_socket(fn)
74
+ return inner
omlish/sockets/bind.py CHANGED
@@ -20,6 +20,8 @@ from omlish.sockets.addresses import SocketAndAddress
20
20
 
21
21
  SocketBinderT = ta.TypeVar('SocketBinderT', bound='SocketBinder')
22
22
  SocketBinderConfigT = ta.TypeVar('SocketBinderConfigT', bound='SocketBinder.Config')
23
+ CanSocketBinderConfig = ta.Union['SocketBinder.Config', int, ta.Tuple[str, int], str] # ta.TypeAlias
24
+ CanSocketBinder = ta.Union['SocketBinder', CanSocketBinderConfig] # ta.TypeAlias
23
25
 
24
26
 
25
27
  ##
@@ -38,33 +40,29 @@ class SocketBinder(abc.ABC, ta.Generic[SocketBinderConfigT]):
38
40
  #
39
41
 
40
42
  @classmethod
41
- def new(
42
- cls,
43
- target: ta.Union[
44
- int,
45
- ta.Tuple[str, int],
46
- str,
47
- ],
48
- ) -> 'SocketBinder.Config':
49
- if isinstance(target, int):
43
+ def of(cls, obj: CanSocketBinderConfig) -> 'SocketBinder.Config':
44
+ if isinstance(obj, SocketBinder.Config):
45
+ return obj
46
+
47
+ elif isinstance(obj, int):
50
48
  return TcpSocketBinder.Config(
51
- port=target,
49
+ port=obj,
52
50
  )
53
51
 
54
- elif isinstance(target, tuple):
55
- host, port = target
52
+ elif isinstance(obj, tuple):
53
+ host, port = obj
56
54
  return TcpSocketBinder.Config(
57
55
  host=host,
58
56
  port=port,
59
57
  )
60
58
 
61
- elif isinstance(target, str):
59
+ elif isinstance(obj, str):
62
60
  return UnixSocketBinder.Config(
63
- file=target,
61
+ file=obj,
64
62
  )
65
63
 
66
64
  else:
67
- raise TypeError(target)
65
+ raise TypeError(obj)
68
66
 
69
67
  #
70
68
 
@@ -76,13 +74,16 @@ class SocketBinder(abc.ABC, ta.Generic[SocketBinderConfigT]):
76
74
  #
77
75
 
78
76
  @classmethod
79
- def new(cls, target: ta.Any) -> 'SocketBinder':
77
+ def of(cls, obj: CanSocketBinder) -> 'SocketBinder':
78
+ if isinstance(obj, SocketBinder):
79
+ return obj
80
+
80
81
  config: SocketBinder.Config
81
- if isinstance(target, SocketBinder.Config):
82
- config = target
82
+ if isinstance(obj, SocketBinder.Config):
83
+ config = obj
83
84
 
84
85
  else:
85
- config = SocketBinder.Config.new(target)
86
+ config = SocketBinder.Config.of(obj)
86
87
 
87
88
  if isinstance(config, TcpSocketBinder.Config):
88
89
  return TcpSocketBinder(config)
@@ -1,5 +1,6 @@
1
1
  # ruff: noqa: UP006 UP007
2
2
  # @omlish-lite
3
+ import abc
3
4
  import typing as ta
4
5
 
5
6
  from .addresses import SocketAddress
@@ -10,3 +11,9 @@ SocketHandler = ta.Callable[[SocketAddress, 'SocketIoPair'], None] # ta.TypeAli
10
11
 
11
12
 
12
13
  ##
14
+
15
+
16
+ class SocketHandler_(abc.ABC): # noqa
17
+ @abc.abstractmethod
18
+ def __call__(self, addr: SocketAddress, f: SocketIoPair) -> None:
19
+ raise NotImplementedError
@@ -1,5 +1,7 @@
1
- # @omlish-lite
2
1
  # ruff: noqa: UP006 UP007
2
+ # @omlish-lite
3
+ import abc
4
+ import concurrent.futures as cf
3
5
  import dataclasses as dc
4
6
  import socket
5
7
  import typing as ta
@@ -16,8 +18,17 @@ SocketServerHandler = ta.Callable[[SocketAndAddress], None] # ta.TypeAlias
16
18
  ##
17
19
 
18
20
 
21
+ class SocketServerHandler_(abc.ABC): # noqa
22
+ @abc.abstractmethod
23
+ def __call__(self, conn: SocketAndAddress) -> None:
24
+ raise NotImplementedError
25
+
26
+
27
+ ##
28
+
29
+
19
30
  @dc.dataclass(frozen=True)
20
- class StandardSocketServerHandler:
31
+ class StandardSocketServerHandler(SocketServerHandler_):
21
32
  handler: SocketServerHandler
22
33
 
23
34
  timeout: ta.Optional[float] = None
@@ -46,7 +57,7 @@ class StandardSocketServerHandler:
46
57
 
47
58
 
48
59
  @dc.dataclass(frozen=True)
49
- class CallbackWrappedSocketServerHandler:
60
+ class CallbackWrappedSocketServerHandler(SocketServerHandler_):
50
61
  handler: SocketServerHandler
51
62
 
52
63
  before_handle: ta.Optional[SocketServerHandler] = None
@@ -83,7 +94,7 @@ class CallbackWrappedSocketServerHandler:
83
94
 
84
95
 
85
96
  @dc.dataclass(frozen=True)
86
- class SocketHandlerSocketServerHandler:
97
+ class SocketHandlerSocketServerHandler(SocketServerHandler_):
87
98
  handler: SocketHandler
88
99
 
89
100
  r_buf_size: int = -1
@@ -97,3 +108,27 @@ class SocketHandlerSocketServerHandler:
97
108
  )
98
109
 
99
110
  self.handler(conn.address, fp)
111
+
112
+
113
+ #
114
+
115
+
116
+ @dc.dataclass(frozen=True)
117
+ class SocketWrappingSocketServerHandler(SocketServerHandler_):
118
+ handler: SocketServerHandler
119
+ wrapper: ta.Callable[[SocketAndAddress], SocketAndAddress]
120
+
121
+ def __call__(self, conn: SocketAndAddress) -> None:
122
+ wrapped_conn = self.wrapper(conn)
123
+ self.handler(wrapped_conn)
124
+
125
+
126
+ #
127
+
128
+ @dc.dataclass(frozen=True)
129
+ class ExecutorSocketServerHandler(SocketServerHandler_):
130
+ handler: SocketServerHandler
131
+ executor: cf.Executor
132
+
133
+ def __call__(self, conn: SocketAndAddress) -> None:
134
+ self.executor.submit(self.handler, conn)
@@ -7,6 +7,7 @@ import threading
7
7
  import typing as ta
8
8
 
9
9
  from ..bind import SocketBinder
10
+ from ..io import close_socket_immediately
10
11
  from .handlers import SocketServerHandler
11
12
 
12
13
 
@@ -104,7 +105,14 @@ class SocketServer(abc.ABC):
104
105
 
105
106
  return
106
107
 
107
- self._handler(conn)
108
+ try:
109
+ self._handler(conn)
110
+
111
+ except Exception as exc: # noqa
112
+ if (on_error := self._on_error) is not None:
113
+ on_error(exc)
114
+
115
+ close_socket_immediately(conn.socket)
108
116
 
109
117
  yield bool(ready)
110
118
 
@@ -2,7 +2,7 @@
2
2
  TODO:
3
3
  - sync/async...
4
4
  """
5
- from ... import secrets as sec
5
+ from ..secrets import all as sec
6
6
 
7
7
 
8
8
  class SqlFunctionSecrets(sec.Secrets):
omlish/sql/dbs.py CHANGED
@@ -3,7 +3,7 @@ import urllib.parse
3
3
 
4
4
  from .. import dataclasses as dc
5
5
  from .. import lang
6
- from .. import secrets as sec
6
+ from ..secrets import all as sec
7
7
 
8
8
 
9
9
  ##
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: omlish
3
- Version: 0.0.0.dev218
3
+ Version: 0.0.0.dev219
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -18,7 +18,7 @@ Requires-Dist: sniffio~=1.3; extra == "all"
18
18
  Requires-Dist: greenlet~=3.1; extra == "all"
19
19
  Requires-Dist: trio~=0.27; extra == "all"
20
20
  Requires-Dist: trio-asyncio~=0.15; extra == "all"
21
- Requires-Dist: lz4~=4.3; extra == "all"
21
+ Requires-Dist: lz4~=4.4; extra == "all"
22
22
  Requires-Dist: python-snappy~=0.7; extra == "all"
23
23
  Requires-Dist: zstandard~=0.23; extra == "all"
24
24
  Requires-Dist: brotli~=1.1; extra == "all"
@@ -57,7 +57,7 @@ Requires-Dist: greenlet~=3.1; extra == "async"
57
57
  Requires-Dist: trio~=0.27; extra == "async"
58
58
  Requires-Dist: trio-asyncio~=0.15; extra == "async"
59
59
  Provides-Extra: compress
60
- Requires-Dist: lz4~=4.3; extra == "compress"
60
+ Requires-Dist: lz4~=4.4; extra == "compress"
61
61
  Requires-Dist: python-snappy~=0.7; extra == "compress"
62
62
  Requires-Dist: zstandard~=0.23; extra == "compress"
63
63
  Requires-Dist: brotli~=1.1; extra == "compress"
@@ -1,5 +1,5 @@
1
1
  omlish/.manifests.json,sha256=YGmAnUBszmosQQ_7Hh2wwtDiYdYZ4unNKYzOtALuels,7968
2
- omlish/__about__.py,sha256=0BtXUJi7KSCGQMkzet9GL1mr4dSvaRR9Jv-gAz1olhc,3380
2
+ omlish/__about__.py,sha256=XK2FqqJrrqiv22AiJ0Zjsv-tVj5fAtCQ0g6QGY3-xtU,3380
3
3
  omlish/__init__.py,sha256=SsyiITTuK0v74XpKV8dqNaCmjOlan1JZKrHQv5rWKPA,253
4
4
  omlish/c3.py,sha256=ubu7lHwss5V4UznbejAI0qXhXahrU01MysuHOZI9C4U,8116
5
5
  omlish/cached.py,sha256=UI-XTFBwA6YXWJJJeBn-WkwBkfzDjLBBaZf4nIJA9y0,510
@@ -301,19 +301,20 @@ omlish/http/consts.py,sha256=7BJ4D1MdIvqBcepkgCfBFHolgTwbOlqsOEiee_IjxOA,2289
301
301
  omlish/http/cookies.py,sha256=uuOYlHR6e2SC3GM41V0aozK10nef9tYg83Scqpn5-HM,6351
302
302
  omlish/http/dates.py,sha256=Otgp8wRxPgNGyzx8LFowu1vC4EKJYARCiAwLFncpfHM,2875
303
303
  omlish/http/encodings.py,sha256=w2WoKajpaZnQH8j-IBvk5ZFL2O2pAU_iBvZnkocaTlw,164
304
- omlish/http/handlers.py,sha256=twe1VYYlIX0e_unFNtt5moU-VbtG29IuTu4RWS1vrn4,1052
304
+ omlish/http/handlers.py,sha256=_MdO62GGKqzCabSSmA9uCMTB41b6sSC0AFJCpPJ9vOU,1232
305
305
  omlish/http/headers.py,sha256=ZMmjrEiYjzo0YTGyK0YsvjdwUazktGqzVVYorY4fd44,5081
306
306
  omlish/http/json.py,sha256=9XwAsl4966Mxrv-1ytyCqhcE6lbBJw-0_tFZzGszgHE,7440
307
307
  omlish/http/jwt.py,sha256=6Rigk1WrJ059DY4jDIKnxjnChWb7aFdermj2AI2DSvk,4346
308
308
  omlish/http/multipart.py,sha256=R9ycpHsXRcmh0uoc43aYb7BdWL-8kSQHe7J-M81aQZM,2240
309
309
  omlish/http/parsing.py,sha256=hxfd9nYaAAjYIivkTClFZXMRmiiCnxzeeEIGXw7-gt0,13992
310
- omlish/http/sessions.py,sha256=WVRTy2KjehwQiYTPn7r44gZ4Pqg8sDC_9-wiYON0344,4796
310
+ omlish/http/sessions.py,sha256=TfTJ_j-6c9PelG_RmijEwozfaVm3O7YzgtFvp8VzQqM,4799
311
+ omlish/http/simple.py,sha256=9WtpbQahiZE-UjRP3ZDni8DQTq_HkVSdwpui_y8mf1I,2867
311
312
  omlish/http/sse.py,sha256=MDs9RvxQXoQliImcc6qK1ERajEYM7Q1l8xmr-9ceNBc,2315
312
313
  omlish/http/versions.py,sha256=wSiOXPiClVjkVgSU_VmxkoD1SUYGaoPbP0U5Aw-Ufg8,409
313
314
  omlish/http/wsgi.py,sha256=czZsVUX-l2YTlMrUjKN49wRoP4rVpS0qpeBn4O5BoMY,948
314
315
  omlish/http/coro/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
315
316
  omlish/http/coro/fdio.py,sha256=ajj_lekRockGwQEw8m_mi6RO9-o6hnC9ITiwtZe3y-s,4017
316
- omlish/http/coro/server.py,sha256=IhdBv-Cx09FG6ADNXfysJV6v7i1gU7dCHLx9Bt_BieM,18799
317
+ omlish/http/coro/server.py,sha256=QujEUM2fhfy2GsoKhpHZvFv7SlGVwcU8kwUXEyUgwWk,18791
317
318
  omlish/inject/__init__.py,sha256=n0RC9UDGsBQQ39cST39-XJqJPq2M0tnnh9yJubW9azo,1891
318
319
  omlish/inject/binder.py,sha256=DAbc8TZi5w8Mna0TUtq0mT4jeDVA7i7SlBtOFrh2swc,4185
319
320
  omlish/inject/bindings.py,sha256=pLXn2U3kvmAS-68IOG-tr77DbiI-wp9hGyy4lhG6_H8,525
@@ -500,22 +501,23 @@ omlish/reflect/inspect.py,sha256=veJ424-9oZrqyvhVpvxOi7hcKW-PDBkdYL2yjrFlk4o,495
500
501
  omlish/reflect/ops.py,sha256=RJ6jzrM4ieFsXzWyNXWV43O_WgzEaUvlHSc5N2ezW2A,2044
501
502
  omlish/reflect/subst.py,sha256=g3q7NmNWsmc67mcchmCE3WFPCMDSBq-FXn4ah-DWL_U,3622
502
503
  omlish/reflect/types.py,sha256=lYxK_hlC4kVDMKeDYJp0mymSth21quwuFAMAEFBznyE,9151
503
- omlish/secrets/__init__.py,sha256=SGB1KrlNrxlNpazEHYy95NTzteLi8ndoEgMhU7luBl8,420
504
+ omlish/secrets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
505
+ omlish/secrets/all.py,sha256=zRp3bYkcVG4Aez4hBHKBxc07s6u74IrGQVUB8cfrGxY,281
504
506
  omlish/secrets/crypto.py,sha256=6CsLy0UEqCrBK8Xx_3-iFF6SKtu2GlEqUQ8-MliY3tk,3709
505
507
  omlish/secrets/marshal.py,sha256=U9uSRTWzZmumfNZeh_dROwVdGrARsp155TylRbjilP8,2048
506
508
  omlish/secrets/openssl.py,sha256=wxA_wIlxtuOUy71ABxAJgavh-UI_taOfm-A0dVlmSwM,6219
507
509
  omlish/secrets/pwgen.py,sha256=v-5ztnOTHTAWXLGR-3H6HkMj2nPIZBMbo5xWR3q0rDY,1707
508
510
  omlish/secrets/pwhash.py,sha256=Goktn-swmC6PXqfRBnDrH_Lr42vjckT712UyErPjzkw,4102
509
- omlish/secrets/secrets.py,sha256=cnDGBoPknVxsCN04_gqcJT_7Ebk3iO3VPkRZ2oMjkMw,7868
511
+ omlish/secrets/secrets.py,sha256=QNgOmRcIRK2fx49bIbBBM2rYbe6IhhLgk8fKvq8guoI,7963
510
512
  omlish/secrets/subprocesses.py,sha256=ffjfbgPbEE_Pwb_87vG4yYR2CGZy3I31mHNCo_0JtHw,1212
511
513
  omlish/sockets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
512
- omlish/sockets/addresses.py,sha256=QGK-5smlg5owx3PEw9qSfSHQ5mkAYumUpbaVR4qvcpM,1442
513
- omlish/sockets/bind.py,sha256=F5PATao0xUEoZ0unZbro2tPTECDtj1B6lS3ygEvIxUs,7750
514
- omlish/sockets/handlers.py,sha256=cVMKG3dn_tJlz6aM0WUL1uQ03F7VQmmKn9yJlOwKE6g,226
514
+ omlish/sockets/addresses.py,sha256=vbVeQBkzI513H4vRv-JS89QtRbr9U8v5zqkm3oODl_s,1869
515
+ omlish/sockets/bind.py,sha256=rNX-1VWYR0IlOLo4S0qqfm1PwqfjvSvHiFj7DE2_gIE,7914
516
+ omlish/sockets/handlers.py,sha256=ux2cPzAWV8b-mQ0K08-b7qjVeIT8Js5_-tyVZs0fbwg,406
515
517
  omlish/sockets/io.py,sha256=lfhTkB7NnAIx9kuQhAkwgsEUXY78Mp1_WtYrIQNS_k8,1408
516
518
  omlish/sockets/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
517
- omlish/sockets/server/handlers.py,sha256=aoWZtDKPboHj3YAR-qHblnEGpz_Nx8mEajV_LxXUBRw,2440
518
- omlish/sockets/server/server.py,sha256=ZLYjW_MmHfMGQ2qSMRFMKLwqPqGCCSf4ORiZjQd59MA,4144
519
+ omlish/sockets/server/handlers.py,sha256=-5lH2Xg7gnZiPB4t2Asa_Vgblj1ZkHzLvyiC_K4XlNc,3295
520
+ omlish/sockets/server/server.py,sha256=kIQ8hHpc9GVefX7sGUrs6bhpJybaagYVwKq5QRT5B4s,4463
519
521
  omlish/sockets/server/threading.py,sha256=YmW3Ym_p5j_F4SIH9BgRHIObywjq1HS39j9CGWIcMAY,2856
520
522
  omlish/specs/__init__.py,sha256=zZwF8yXTEkSstYtORkDhVLK-_hWU8WOJCuBpognb_NY,118
521
523
  omlish/specs/jmespath/LICENSE,sha256=IH-ZZlZkS8XMkf_ubNVD1aYHQ2l_wd0tmHtXrCcYpRU,1113
@@ -561,14 +563,14 @@ omlish/specs/openapi/openapi.py,sha256=y4h04jeB7ORJSVrcy7apaBdpwLjIyscv1Ub5SderH
561
563
  omlish/sql/__init__.py,sha256=TpZLsEJKJzvJ0eMzuV8hwOJJbkxBCV1RZPUMLAVB6io,173
562
564
  omlish/sql/abc.py,sha256=NfbcIlEvdEu6vn0TolhfYb2SO5uzUmY0kARCbg6uVAU,1879
563
565
  omlish/sql/dbapi.py,sha256=5ghJH-HexsmDlYdWlhf00nCGQX2IC98_gxIxMkucOas,3195
564
- omlish/sql/dbs.py,sha256=lpdFmm2vTwLoBiVYGj9yPsVcTEYYNCxlYZZpjfChzkY,1870
566
+ omlish/sql/dbs.py,sha256=65e388987upJpsFX8bNL7uhiYv2sCsmk9Y04V0MXdsI,1873
565
567
  omlish/sql/params.py,sha256=Z4VPet6GhNqD1T_MXSWSHkdy3cpUEhST-OplC4B_fYI,4433
566
568
  omlish/sql/qualifiedname.py,sha256=rlW3gVmyucJbqwcxj_7BfK4X2HoXrMroZT2H45zPgJQ,2264
567
569
  omlish/sql/alchemy/__init__.py,sha256=1ruDMiviH5fjevn2xVki-QspcE9O3VPy4hxOqpHjI2s,224
568
570
  omlish/sql/alchemy/asyncs.py,sha256=MwZwWIaZsUCQLcTA8mdHUPZmR-pXEVSAsvd15FCm3W4,3692
569
571
  omlish/sql/alchemy/duckdb.py,sha256=kr7pIhiBLNAuZrcigHDtFg9zHkVcrRW3LfryO9VJ4mk,3749
570
572
  omlish/sql/alchemy/exprs.py,sha256=gO4Fj4xEY-PuDgV-N8hBMy55glZz7O-4H7v1LWabfZY,323
571
- omlish/sql/alchemy/secrets.py,sha256=EMfy4EfTbEvrlv_41oOhn8qsoF-eTkY7HciPenIE6rI,178
573
+ omlish/sql/alchemy/secrets.py,sha256=WEeaec1ejQcE3Yaa7p5BSP9AMGEzy1lwr7QMSRL0VBw,180
572
574
  omlish/sql/alchemy/sqlean.py,sha256=RbkuOuFIfM4fowwKk8-sQ6Dxk-tTUwxS94nY5Kxt52s,403
573
575
  omlish/sql/queries/__init__.py,sha256=8wdq6PBf5YzqQWFu-CE8om6BN38sDAD9UEz9VzkojzM,1337
574
576
  omlish/sql/queries/base.py,sha256=_8O3MbH_OEjBnhp2oIJUZ3ClaQ8l4Sj9BdPdsP0Ie-g,224
@@ -637,9 +639,9 @@ omlish/text/indent.py,sha256=YjtJEBYWuk8--b9JU_T6q4yxV85_TR7VEVr5ViRCFwk,1336
637
639
  omlish/text/minja.py,sha256=jZC-fp3Xuhx48ppqsf2Sf1pHbC0t8XBB7UpUUoOk2Qw,5751
638
640
  omlish/text/parts.py,sha256=7vPF1aTZdvLVYJ4EwBZVzRSy8XB3YqPd7JwEnNGGAOo,6495
639
641
  omlish/text/random.py,sha256=jNWpqiaKjKyTdMXC-pWAsSC10AAP-cmRRPVhm59ZWLk,194
640
- omlish-0.0.0.dev218.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
641
- omlish-0.0.0.dev218.dist-info/METADATA,sha256=-vMqTXr2Q_gjsOk2hxSEXQXb9eWwZ4vVabWD7mQjgD8,4176
642
- omlish-0.0.0.dev218.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
643
- omlish-0.0.0.dev218.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
644
- omlish-0.0.0.dev218.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
645
- omlish-0.0.0.dev218.dist-info/RECORD,,
642
+ omlish-0.0.0.dev219.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
643
+ omlish-0.0.0.dev219.dist-info/METADATA,sha256=lh7Dpy8tG4NhG-VPo4QWw-EnYsyHj1OY8pnJOIEfQm8,4176
644
+ omlish-0.0.0.dev219.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
645
+ omlish-0.0.0.dev219.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
646
+ omlish-0.0.0.dev219.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
647
+ omlish-0.0.0.dev219.dist-info/RECORD,,