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

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,99 @@
1
+ # @omlish-lite
2
+ # ruff: noqa: UP006 UP007
3
+ import dataclasses as dc
4
+ import socket
5
+ import typing as ta
6
+
7
+ from ..addresses import SocketAndAddress
8
+ from ..handlers import SocketHandler
9
+ from ..io import SocketIoPair
10
+ from ..io import close_socket_immediately
11
+
12
+
13
+ SocketServerHandler = ta.Callable[[SocketAndAddress], None] # ta.TypeAlias
14
+
15
+
16
+ ##
17
+
18
+
19
+ @dc.dataclass(frozen=True)
20
+ class StandardSocketServerHandler:
21
+ handler: SocketServerHandler
22
+
23
+ timeout: ta.Optional[float] = None
24
+
25
+ # http://bugs.python.org/issue6192
26
+ # TODO: https://eklitzke.org/the-caveats-of-tcp-nodelay
27
+ disable_nagle_algorithm: bool = False
28
+
29
+ no_close: bool = False
30
+
31
+ def __call__(self, conn: SocketAndAddress) -> None:
32
+ try:
33
+ if self.timeout is not None:
34
+ conn.socket.settimeout(self.timeout)
35
+
36
+ if self.disable_nagle_algorithm:
37
+ conn.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, True)
38
+
39
+ self.handler(conn)
40
+
41
+ finally:
42
+ close_socket_immediately(conn.socket)
43
+
44
+
45
+ #
46
+
47
+
48
+ @dc.dataclass(frozen=True)
49
+ class CallbackWrappedSocketServerHandler:
50
+ handler: SocketServerHandler
51
+
52
+ before_handle: ta.Optional[SocketServerHandler] = None
53
+ after_handle: ta.Optional[SocketServerHandler] = None
54
+
55
+ # Return True if suppress like __exit__
56
+ on_error: ta.Optional[ta.Callable[[SocketAndAddress, Exception], bool]] = None
57
+
58
+ finally_: ta.Optional[SocketServerHandler] = None
59
+
60
+ def __call__(self, conn: SocketAndAddress) -> None:
61
+ try:
62
+ if (before_handle := self.before_handle) is not None:
63
+ before_handle(conn)
64
+
65
+ self.handler(conn)
66
+
67
+ except Exception as e:
68
+ if (on_error := self.on_error) is not None and on_error(conn, e):
69
+ pass
70
+ else:
71
+ raise
72
+
73
+ else:
74
+ if (after_handle := self.after_handle) is not None:
75
+ after_handle(conn)
76
+
77
+ finally:
78
+ if (finally_ := self.finally_) is not None:
79
+ finally_(conn)
80
+
81
+
82
+ #
83
+
84
+
85
+ @dc.dataclass(frozen=True)
86
+ class SocketHandlerSocketServerHandler:
87
+ handler: SocketHandler
88
+
89
+ r_buf_size: int = -1
90
+ w_buf_size: int = 0
91
+
92
+ def __call__(self, conn: SocketAndAddress) -> None:
93
+ fp = SocketIoPair.from_socket(
94
+ conn.socket,
95
+ r_buf_size=self.r_buf_size,
96
+ w_buf_size=self.w_buf_size,
97
+ )
98
+
99
+ self.handler(conn.address, fp)
@@ -0,0 +1,144 @@
1
+ # @omlish-lite
2
+ # ruff: noqa: UP006 UP007
3
+ import abc
4
+ import contextlib
5
+ import selectors
6
+ import threading
7
+ import typing as ta
8
+
9
+ from ..bind import SocketBinder
10
+ from .handlers import SocketServerHandler
11
+
12
+
13
+ ##
14
+
15
+
16
+ class SocketServer(abc.ABC):
17
+ def __init__(
18
+ self,
19
+ binder: SocketBinder,
20
+ handler: SocketServerHandler,
21
+ *,
22
+ on_error: ta.Optional[ta.Callable[[BaseException], None]] = None,
23
+ poll_interval: float = .5,
24
+ shutdown_timeout: ta.Optional[float] = None,
25
+ ) -> None:
26
+ super().__init__()
27
+
28
+ self._binder = binder
29
+ self._handler = handler
30
+ self._on_error = on_error
31
+ self._poll_interval = poll_interval
32
+ self._shutdown_timeout = shutdown_timeout
33
+
34
+ self._lock = threading.RLock()
35
+ self._is_shutdown = threading.Event()
36
+ self._should_shutdown = False
37
+
38
+ @property
39
+ def binder(self) -> SocketBinder:
40
+ return self._binder
41
+
42
+ @property
43
+ def handler(self) -> SocketServerHandler:
44
+ return self._handler
45
+
46
+ #
47
+
48
+ class SelectorProtocol(ta.Protocol):
49
+ def register(self, *args, **kwargs) -> None:
50
+ raise NotImplementedError
51
+
52
+ def select(self, *args, **kwargs) -> bool:
53
+ raise NotImplementedError
54
+
55
+ Selector: ta.ClassVar[ta.Any]
56
+ if hasattr(selectors, 'PollSelector'):
57
+ Selector = selectors.PollSelector
58
+ else:
59
+ Selector = selectors.SelectSelector
60
+
61
+ #
62
+
63
+ @contextlib.contextmanager
64
+ def _listen_context(self) -> ta.Iterator[SelectorProtocol]:
65
+ with contextlib.ExitStack() as es:
66
+ es.enter_context(self._lock)
67
+ es.enter_context(self._binder)
68
+
69
+ self._binder.listen()
70
+
71
+ self._is_shutdown.clear()
72
+ try:
73
+ # XXX: Consider using another file descriptor or connecting to the socket to wake this up instead of
74
+ # polling. Polling reduces our responsiveness to a shutdown request and wastes cpu at all other times.
75
+ with self.Selector() as selector:
76
+ selector.register(self._binder.fileno(), selectors.EVENT_READ)
77
+
78
+ yield selector
79
+
80
+ finally:
81
+ self._is_shutdown.set()
82
+
83
+ @contextlib.contextmanager
84
+ def loop_context(self, poll_interval: ta.Optional[float] = None) -> ta.Iterator[ta.Iterator[bool]]:
85
+ if poll_interval is None:
86
+ poll_interval = self._poll_interval
87
+
88
+ with self._listen_context() as selector:
89
+ def loop():
90
+ while not self._should_shutdown:
91
+ ready = selector.select(poll_interval)
92
+
93
+ # bpo-35017: shutdown() called during select(), exit immediately.
94
+ if self._should_shutdown:
95
+ break # type: ignore[unreachable]
96
+
97
+ if ready:
98
+ try:
99
+ conn = self._binder.accept()
100
+
101
+ except OSError as exc:
102
+ if (on_error := self._on_error) is not None:
103
+ on_error(exc)
104
+
105
+ return
106
+
107
+ self._handler(conn)
108
+
109
+ yield bool(ready)
110
+
111
+ yield loop()
112
+
113
+ def run(self, poll_interval: ta.Optional[float] = None) -> None:
114
+ with self.loop_context(poll_interval=poll_interval) as loop:
115
+ for _ in loop:
116
+ pass
117
+
118
+ #
119
+
120
+ class _NOT_SET: # noqa
121
+ def __new__(cls, *args, **kwargs): # noqa
122
+ raise TypeError
123
+
124
+ def shutdown(
125
+ self,
126
+ block: bool = False,
127
+ timeout: ta.Union[float, None, ta.Type[_NOT_SET]] = _NOT_SET,
128
+ ) -> None:
129
+ self._should_shutdown = True
130
+
131
+ if block:
132
+ if timeout is self._NOT_SET:
133
+ timeout = self._shutdown_timeout
134
+
135
+ if not self._is_shutdown.wait(timeout=timeout): # type: ignore
136
+ raise TimeoutError
137
+
138
+ #
139
+
140
+ def __enter__(self) -> 'SocketServer':
141
+ return self
142
+
143
+ def __exit__(self, exc_type, exc_val, exc_tb):
144
+ self.shutdown()
@@ -0,0 +1,123 @@
1
+ # @omlish-lite
2
+ # ruff: noqa: UP006 UP007
3
+ import threading
4
+ import time
5
+ import typing as ta
6
+
7
+ from ...lite.check import check
8
+ from ..addresses import SocketAndAddress
9
+ from .handlers import SocketServerHandler
10
+
11
+
12
+ ##
13
+
14
+
15
+ class ThreadingSocketServerHandler:
16
+ def __init__(
17
+ self,
18
+ handler: SocketServerHandler,
19
+ *,
20
+ shutdown_timeout: ta.Optional[float] = None,
21
+ ) -> None:
22
+ super().__init__()
23
+
24
+ self._handler = handler
25
+ self._shutdown_timeout = shutdown_timeout
26
+
27
+ self._lock = threading.RLock()
28
+ self._threads: ta.List[threading.Thread] = []
29
+ self._is_shutdown = False
30
+
31
+ @property
32
+ def handler(self) -> SocketServerHandler:
33
+ return self._handler
34
+
35
+ #
36
+
37
+ def __call__(self, conn: SocketAndAddress) -> None:
38
+ self.handle(conn)
39
+
40
+ def handle(self, conn: SocketAndAddress) -> None:
41
+ with self._lock:
42
+ check.state(not self._is_shutdown)
43
+
44
+ self._reap()
45
+
46
+ t = threading.Thread(
47
+ target=self._handler,
48
+ args=(conn,),
49
+ )
50
+
51
+ self._threads.append(t)
52
+
53
+ t.start()
54
+
55
+ #
56
+
57
+ def _reap(self) -> None:
58
+ with self._lock:
59
+ self._threads[:] = (thread for thread in self._threads if thread.is_alive())
60
+
61
+ def is_alive(self) -> bool:
62
+ with self._lock:
63
+ self._reap()
64
+
65
+ return bool(self._threads)
66
+
67
+ def join(self, timeout: ta.Optional[float] = None) -> None:
68
+ if timeout is not None:
69
+ deadline: ta.Optional[float] = time.time() + timeout
70
+ else:
71
+ deadline = None
72
+
73
+ def calc_timeout() -> ta.Optional[float]:
74
+ if deadline is None:
75
+ return None
76
+
77
+ tt = deadline - time.time()
78
+ if tt <= 0:
79
+ raise TimeoutError
80
+
81
+ return tt
82
+
83
+ if not (self._lock.acquire(timeout=calc_timeout() or -1)):
84
+ raise TimeoutError
85
+
86
+ try:
87
+ self._reap()
88
+
89
+ for t in self._threads:
90
+ t.join(timeout=calc_timeout())
91
+
92
+ if t.is_alive():
93
+ raise TimeoutError
94
+
95
+ finally:
96
+ self._lock.release()
97
+
98
+ #
99
+
100
+ class _NOT_SET: # noqa
101
+ def __new__(cls, *args, **kwargs): # noqa
102
+ raise TypeError
103
+
104
+ def shutdown(
105
+ self,
106
+ block: bool = False,
107
+ timeout: ta.Union[float, None, ta.Type[_NOT_SET]] = _NOT_SET,
108
+ ) -> None:
109
+ self._is_shutdown = True
110
+
111
+ if block:
112
+ if timeout is self._NOT_SET:
113
+ timeout = self._shutdown_timeout
114
+
115
+ self.join(timeout=timeout) # type: ignore
116
+
117
+ #
118
+
119
+ def __enter__(self) -> 'ThreadingSocketServerHandler':
120
+ return self
121
+
122
+ def __exit__(self, exc_type, exc_val, exc_tb):
123
+ self.shutdown()
omlish/subprocesses.py CHANGED
@@ -20,6 +20,12 @@ SubprocessChannelOption = ta.Literal['pipe', 'stdout', 'devnull'] # ta.TypeAlia
20
20
  ##
21
21
 
22
22
 
23
+ # Valid channel type kwarg values:
24
+ # - A special flag negative int
25
+ # - A positive fd int
26
+ # - A file-like object
27
+ # - None
28
+
23
29
  SUBPROCESS_CHANNEL_OPTION_VALUES: ta.Mapping[SubprocessChannelOption, int] = {
24
30
  'pipe': subprocess.PIPE,
25
31
  'stdout': subprocess.STDOUT,
@@ -65,6 +71,25 @@ def subprocess_close(
65
71
  ##
66
72
 
67
73
 
74
+ class VerboseCalledProcessError(subprocess.CalledProcessError):
75
+ @classmethod
76
+ def from_std(cls, e: subprocess.CalledProcessError) -> 'VerboseCalledProcessError':
77
+ return cls(
78
+ e.returncode,
79
+ e.cmd,
80
+ output=e.output,
81
+ stderr=e.stderr,
82
+ )
83
+
84
+ def __str__(self) -> str:
85
+ msg = super().__str__()
86
+ if self.output is not None:
87
+ msg += f' Output: {self.output!r}'
88
+ if self.stderr is not None:
89
+ msg += f' Stderr: {self.stderr!r}'
90
+ return msg
91
+
92
+
68
93
  class BaseSubprocesses(abc.ABC): # noqa
69
94
  DEFAULT_LOGGER: ta.ClassVar[ta.Optional[logging.Logger]] = None
70
95
 
@@ -98,16 +123,31 @@ class BaseSubprocesses(abc.ABC): # noqa
98
123
  if extra_env:
99
124
  self._log.debug('Subprocesses.prepare_args: extra_env=%r', extra_env)
100
125
 
126
+ #
127
+
101
128
  if extra_env:
102
129
  env = {**(env if env is not None else os.environ), **extra_env}
103
130
 
131
+ #
132
+
104
133
  if quiet and 'stderr' not in kwargs:
105
134
  if self._log and not self._log.isEnabledFor(logging.DEBUG):
106
135
  kwargs['stderr'] = subprocess.DEVNULL
107
136
 
137
+ for chk in ('stdout', 'stderr'):
138
+ try:
139
+ chv = kwargs[chk]
140
+ except KeyError:
141
+ continue
142
+ kwargs[chk] = SUBPROCESS_CHANNEL_OPTION_VALUES.get(chv, chv)
143
+
144
+ #
145
+
108
146
  if not shell:
109
147
  cmd = subprocess_maybe_shell_wrap_exec(*cmd)
110
148
 
149
+ #
150
+
111
151
  return cmd, dict(
112
152
  env=env,
113
153
  shell=shell,
@@ -115,35 +155,57 @@ class BaseSubprocesses(abc.ABC): # noqa
115
155
  )
116
156
 
117
157
  @contextlib.contextmanager
118
- def wrap_call(self, *cmd: ta.Any, **kwargs: ta.Any) -> ta.Iterator[None]:
158
+ def wrap_call(
159
+ self,
160
+ *cmd: ta.Any,
161
+ raise_verbose: bool = False,
162
+ **kwargs: ta.Any,
163
+ ) -> ta.Iterator[None]:
119
164
  start_time = time.time()
120
165
  try:
121
166
  if self._log:
122
167
  self._log.debug('Subprocesses.wrap_call.try: cmd=%r', cmd)
168
+
123
169
  yield
124
170
 
125
171
  except Exception as exc: # noqa
126
172
  if self._log:
127
173
  self._log.debug('Subprocesses.wrap_call.except: exc=%r', exc)
174
+
175
+ if (
176
+ raise_verbose and
177
+ isinstance(exc, subprocess.CalledProcessError) and
178
+ not isinstance(exc, VerboseCalledProcessError) and
179
+ (exc.output is not None or exc.stderr is not None)
180
+ ):
181
+ raise VerboseCalledProcessError.from_std(exc) from exc
182
+
128
183
  raise
129
184
 
130
185
  finally:
131
186
  end_time = time.time()
132
187
  elapsed_s = end_time - start_time
188
+
133
189
  if self._log:
134
- self._log.debug('sSubprocesses.wrap_call.finally: elapsed_s=%f cmd=%r', elapsed_s, cmd)
190
+ self._log.debug('Subprocesses.wrap_call.finally: elapsed_s=%f cmd=%r', elapsed_s, cmd)
135
191
 
136
192
  @contextlib.contextmanager
137
193
  def prepare_and_wrap(
138
194
  self,
139
195
  *cmd: ta.Any,
196
+ raise_verbose: bool = False,
140
197
  **kwargs: ta.Any,
141
198
  ) -> ta.Iterator[ta.Tuple[
142
199
  ta.Tuple[ta.Any, ...],
143
200
  ta.Dict[str, ta.Any],
144
201
  ]]:
145
202
  cmd, kwargs = self.prepare_args(*cmd, **kwargs)
146
- with self.wrap_call(*cmd, **kwargs):
203
+
204
+ with self.wrap_call(
205
+ *cmd,
206
+ raise_verbose=raise_verbose,
207
+ **kwargs,
208
+ ):
147
209
  yield cmd, kwargs
148
210
 
149
211
  #
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: omlish
3
- Version: 0.0.0.dev216
3
+ Version: 0.0.0.dev218
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -1,5 +1,5 @@
1
1
  omlish/.manifests.json,sha256=YGmAnUBszmosQQ_7Hh2wwtDiYdYZ4unNKYzOtALuels,7968
2
- omlish/__about__.py,sha256=PjS1s-BEA6BW1AWodoo9aQyr9k3shf8Uan7UcjNCYrU,3380
2
+ omlish/__about__.py,sha256=0BtXUJi7KSCGQMkzet9GL1mr4dSvaRR9Jv-gAz1olhc,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
@@ -11,7 +11,7 @@ omlish/libc.py,sha256=8r7Ejyhttk9ruCfBkxNTrlzir5WPbDE2vmY7VPlceMA,15362
11
11
  omlish/outcome.py,sha256=ABIE0zjjTyTNtn-ZqQ_9_mUzLiBQ3sDAyqc9JVD8N2k,7852
12
12
  omlish/runmodule.py,sha256=PWvuAaJ9wQQn6bx9ftEL3_d04DyotNn8dR_twm2pgw0,700
13
13
  omlish/shlex.py,sha256=bsW2XUD8GiMTUTDefJejZ5AyqT1pTgWMPD0BMoF02jE,248
14
- omlish/subprocesses.py,sha256=KOvt5gvpq2uisjYKyU_XUPZyM6yq8ywgbfWjz-lx9CQ,8686
14
+ omlish/subprocesses.py,sha256=c7arxsQ7JiaNCmK3GKqwRO6BwrvxeK7eez8A4SrvGBo,10199
15
15
  omlish/sync.py,sha256=QJ79kxmIqDP9SeHDoZAf--DpFIhDQe1jACy8H4N0yZI,2928
16
16
  omlish/antlr/__init__.py,sha256=88bMl_28cfSKslgOkMGYXqALgsHz3KC4LFvAVtzj7k8,89
17
17
  omlish/antlr/delimit.py,sha256=3Byvh9_Ip8ftM_SeSEmMbnNo1jrxk-xm8HnHDp_nDaI,3466
@@ -93,7 +93,7 @@ omlish/asyncs/flavors.py,sha256=1mNxGNRVmjUHzA13K5ht8vdJv4CLEmzYTQ6BZXr1520,4866
93
93
  omlish/asyncs/trio.py,sha256=fmZ5b_lKdVV8NQ3euCUutWgnkqTFzSnOjvJSA_jvmrE,367
94
94
  omlish/asyncs/trio_asyncio.py,sha256=oqdOHy0slj9PjVxaDf3gJkq9AAgg7wYZbB469jOftVw,1327
95
95
  omlish/asyncs/asyncio/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
96
- omlish/asyncs/asyncio/all.py,sha256=GR6BJOSS5W82hc7ZJF7Er_2NZ-94nTXZh71aVLJNa54,123
96
+ omlish/asyncs/asyncio/all.py,sha256=KpTanEtpTlc3rqv5SyiJaJGb_DXBzp_WKLhlRq6lrhY,212
97
97
  omlish/asyncs/asyncio/asyncio.py,sha256=3BMhVIF-QTjsFRGDtNYlRbBqKPCA3_AwJsjJoIWdM8k,1783
98
98
  omlish/asyncs/asyncio/channels.py,sha256=ZbmsEmdK1fV96liHdcVpRqA2dAMkXJt4Q3rFAg3YOIw,1074
99
99
  omlish/asyncs/asyncio/streams.py,sha256=Uc9PCWSfBqrK2kdVtfjjQU1eaYTWYmZm8QISDj2xiuw,1004
@@ -169,8 +169,8 @@ omlish/configs/processing/matching.py,sha256=R64RxpPB1uX5Ztvvk2dQ2xi_xwlaxkxQgZw
169
169
  omlish/configs/processing/names.py,sha256=weHmaTclzgM9lUn3aBtw-kwZ3mc2N-CZlFg3Kd_UsKo,1093
170
170
  omlish/configs/processing/rewriting.py,sha256=v7PfHtuTn5v_5Y6Au7oMN2Z0nxAMy1iYyO5CXnTvZhs,4226
171
171
  omlish/configs/processing/strings.py,sha256=qFS2oh6z02IaM_q4lTKLdufzkJqAJ6J-Qjrz5S-QJoM,826
172
- omlish/dataclasses/__init__.py,sha256=lw-ItSe_zE_iKGGEnkbT92Kv4Zu3KqS1vh-CFOFUGd8,1467
173
- omlish/dataclasses/utils.py,sha256=hbQfbdCjQ9oA3h9kmGcM5bWZM1GbboXsq02ns5ycJwQ,3958
172
+ omlish/dataclasses/__init__.py,sha256=4LYQCg0kqBNwexcXvK6drjxdi79sMvqa4augNhCBHLU,1543
173
+ omlish/dataclasses/utils.py,sha256=N2seT8cJtfOv-41D7F3E-q4us-FCTQmnxxPv3dt1OcI,3796
174
174
  omlish/dataclasses/impl/LICENSE,sha256=Oy-B_iHRgcSZxZolbI4ZaEVdZonSaaqFNzv7avQdo78,13936
175
175
  omlish/dataclasses/impl/__init__.py,sha256=zqGBC5gSbjJxaqG_zS1LL1PX-zAfhIua8UqOE4IwO2k,789
176
176
  omlish/dataclasses/impl/api.py,sha256=p7W519_EnDAWlkOVS-4BpP4SxadWIiUzC3RldSoB28o,6431
@@ -224,7 +224,11 @@ omlish/docker/consts.py,sha256=wvwfUtEFrEWZKfREWqSMrx8xjjl8P5MNUSF6qzzgJHY,70
224
224
  omlish/docker/detect.py,sha256=Qrdbosm2wJkxKDuy8gaGmbQoxk4Wnp1HJjAEz58NA8Y,614
225
225
  omlish/docker/hub.py,sha256=7LIuJGdA-N1Y1dmo50ynKM1KUTcnQM_5XbtPbdT_QLU,3940
226
226
  omlish/docker/manifests.py,sha256=LR4FpOGNUT3bZQ-gTjB6r_-1C3YiG30QvevZjrsVUQM,7068
227
+ omlish/docker/portrelay.py,sha256=QlRoTnQXs5INguR7XOj1xH0gNdL9SUeZm5z45DUctXo,1222
227
228
  omlish/docker/timebomb.py,sha256=A_pgIDaXKsQwPiikrCTgIJl91gwYqkPGFY6j-Naq07Q,342
229
+ omlish/docker/oci/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
230
+ omlish/docker/oci/data.py,sha256=4KtSxziT70BhF30ozQ1SCfX4y0LT_5x0CuOKC4zrEV4,2616
231
+ omlish/docker/oci/media.py,sha256=fJ8VcU-edDpg-FyJQamw-sUlhTghkC-WQ1TC4MiRpFU,4499
228
232
  omlish/formats/__init__.py,sha256=T0AG1gFnqQ5JiHN0UPQjQ-7g5tnxMIG-mgOvMYExYAM,21
229
233
  omlish/formats/cbor.py,sha256=o_Hbe4kthO9CeXK-FySrw0dHVlrdyTo2Y8PpGRDfZ3c,514
230
234
  omlish/formats/cloudpickle.py,sha256=16si4yUp_pAdDWGECAWf6HLA2PwSANGGgDoMLGZUem8,579
@@ -260,7 +264,7 @@ omlish/formats/json/stream/errors.py,sha256=c8M8UAYmIZ-vWZLeKD2jMj4EDCJbr9QR8Jq_
260
264
  omlish/formats/json/stream/lex.py,sha256=ItsWvtl5SZH-HwQtPy8Cpf4nszqDzvUTdIOEmSRiZ-E,6807
261
265
  omlish/formats/json/stream/parse.py,sha256=JuYmXwtTHmQJTFKoJNoEHUpCPxXdl_gvKPykVXgED34,6208
262
266
  omlish/formats/json/stream/render.py,sha256=NtmDsN92xZi5dkgSSuMeMXMAiJblmjz1arB4Ft7vBhc,3715
263
- omlish/formats/json5/Json5.g4,sha256=fSUikG4-eK3j0Ugab9FzQZgpN3w0dN2gjSPWXmPcybI,2661
267
+ omlish/formats/json5/Json5.g4,sha256=ZUmgJPvj8lSMUD_v3wijp10ZQExYB5mu5Q089dYEJSU,2389
264
268
  omlish/formats/json5/__init__.py,sha256=BsjPz5zJDji3GjQ8x8hWvcl1GYPV_ZIHnE3c2Sr8aTU,102
265
269
  omlish/formats/json5/codec.py,sha256=ldnxCRo0JP1fkGLt0mMxJlLvNxqIF_1KUCcSp1HtI-M,452
266
270
  omlish/formats/json5/errors.py,sha256=AHkR9ySjAoQdUrizpqgL8fg0M5oe5mHZkml3KZHEvC4,38
@@ -297,7 +301,7 @@ omlish/http/consts.py,sha256=7BJ4D1MdIvqBcepkgCfBFHolgTwbOlqsOEiee_IjxOA,2289
297
301
  omlish/http/cookies.py,sha256=uuOYlHR6e2SC3GM41V0aozK10nef9tYg83Scqpn5-HM,6351
298
302
  omlish/http/dates.py,sha256=Otgp8wRxPgNGyzx8LFowu1vC4EKJYARCiAwLFncpfHM,2875
299
303
  omlish/http/encodings.py,sha256=w2WoKajpaZnQH8j-IBvk5ZFL2O2pAU_iBvZnkocaTlw,164
300
- omlish/http/handlers.py,sha256=2bKw7XRM11C0VSx-DStKa6exFKNINKK4jZ3uVUVh5d8,795
304
+ omlish/http/handlers.py,sha256=twe1VYYlIX0e_unFNtt5moU-VbtG29IuTu4RWS1vrn4,1052
301
305
  omlish/http/headers.py,sha256=ZMmjrEiYjzo0YTGyK0YsvjdwUazktGqzVVYorY4fd44,5081
302
306
  omlish/http/json.py,sha256=9XwAsl4966Mxrv-1ytyCqhcE6lbBJw-0_tFZzGszgHE,7440
303
307
  omlish/http/jwt.py,sha256=6Rigk1WrJ059DY4jDIKnxjnChWb7aFdermj2AI2DSvk,4346
@@ -309,7 +313,7 @@ omlish/http/versions.py,sha256=wSiOXPiClVjkVgSU_VmxkoD1SUYGaoPbP0U5Aw-Ufg8,409
309
313
  omlish/http/wsgi.py,sha256=czZsVUX-l2YTlMrUjKN49wRoP4rVpS0qpeBn4O5BoMY,948
310
314
  omlish/http/coro/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
311
315
  omlish/http/coro/fdio.py,sha256=ajj_lekRockGwQEw8m_mi6RO9-o6hnC9ITiwtZe3y-s,4017
312
- omlish/http/coro/server.py,sha256=-e-J5pPqPDGrvQkwcukwltOjTbTNatiCx9Rl7FvooTI,18071
316
+ omlish/http/coro/server.py,sha256=IhdBv-Cx09FG6ADNXfysJV6v7i1gU7dCHLx9Bt_BieM,18799
313
317
  omlish/inject/__init__.py,sha256=n0RC9UDGsBQQ39cST39-XJqJPq2M0tnnh9yJubW9azo,1891
314
318
  omlish/inject/binder.py,sha256=DAbc8TZi5w8Mna0TUtq0mT4jeDVA7i7SlBtOFrh2swc,4185
315
319
  omlish/inject/bindings.py,sha256=pLXn2U3kvmAS-68IOG-tr77DbiI-wp9hGyy4lhG6_H8,525
@@ -371,7 +375,7 @@ omlish/io/fdio/pollers.py,sha256=yNadAt3W5wd90PFmd3vD77bq5QwoVb2A6SM2JjZpKRs,550
371
375
  omlish/iterators/__init__.py,sha256=yMavf5FofiS1EU4UFuWPXiFZ03W0H-y7MuMxW8FUaEE,358
372
376
  omlish/iterators/iterators.py,sha256=ghI4dO6WPyyFOLTIIMaHQ_IOy2xXaFpGPqveZ5YGIBU,3158
373
377
  omlish/iterators/recipes.py,sha256=53mkexitMhkwXQZbL6DrhpT0WePQ_56uXd5Jaw3DfzI,467
374
- omlish/iterators/tools.py,sha256=SvXyyQJh7aceLYhRl6pQB-rfSaXw5IMIWukeEeOZt-0,2492
378
+ omlish/iterators/tools.py,sha256=Pi4ybXytUXVZ3xwK89xpPImQfYYId9p1vIFQvVqVLqA,2551
375
379
  omlish/iterators/unique.py,sha256=0jAX3kwzVfRNhe0Tmh7kVP_Q2WBIn8POo_O-rgFV0rQ,1390
376
380
  omlish/lang/__init__.py,sha256=sY7YSgN772n48qWlR-mwuOOCOwRF5Fh421gZqZWxYlw,4042
377
381
  omlish/lang/cached.py,sha256=92TvRZQ6sWlm7dNn4hgl7aWKbX0J1XUEo3DRjBpgVQk,7834
@@ -383,7 +387,7 @@ omlish/lang/descriptors.py,sha256=RRBbkMgTzg82fFFE4D0muqobpM-ZZaOta6yB1lpX3s8,66
383
387
  omlish/lang/exceptions.py,sha256=qJBo3NU1mOWWm-NhQUHCY5feYXR3arZVyEHinLsmRH4,47
384
388
  omlish/lang/functions.py,sha256=t9nsnWwhsibG0w908VMx-_pRM5tZfruE3faPxrCWTbI,4160
385
389
  omlish/lang/generators.py,sha256=5LX17j-Ej3QXhwBgZvRTm_dq3n9veC4IOUcVmvSu2vU,5243
386
- omlish/lang/imports.py,sha256=3C04Z0Hsj-BQIfHDWd-MQFGyZqTWuyJc2di6GfE-eUM,9327
390
+ omlish/lang/imports.py,sha256=oGigWiLkLog29mWWYdu7untyX--K1SueFmKzCpXdtug,9612
387
391
  omlish/lang/iterables.py,sha256=HOjcxOwyI5bBApDLsxRAGGhTTmw7fdZl2kEckxRVl-0,1994
388
392
  omlish/lang/maybes.py,sha256=1RN7chX_x2XvgUwryZRz0W7hAX-be3eEFcFub5vvf6M,3417
389
393
  omlish/lang/objects.py,sha256=LOC3JvX1g5hPxJ7Sv2TK9kNkAo9c8J-Jw2NmClR_rkA,4576
@@ -411,7 +415,7 @@ omlish/lite/cached.py,sha256=O7ozcoDNFm1Hg2wtpHEqYSp_i_nCLNOP6Ueq_Uk-7mU,1300
411
415
  omlish/lite/check.py,sha256=OLwtE2x6nlbGx4vS3Rda7zMHpgqzDSLJminTAX2lqLA,13529
412
416
  omlish/lite/configs.py,sha256=Ev_19sbII67pTWzInYjYqa9VyTiZBvyjhZqyG8TtufE,908
413
417
  omlish/lite/contextmanagers.py,sha256=ciaMl0D3QDHToM7M28-kwZ-Q48LtwgCxiud3nekgutA,2863
414
- omlish/lite/dataclasses.py,sha256=M6UD4VwGo0Ky7RNzKWbO0IOy7iBZVCIbTiC6EYbFnX8,1035
418
+ omlish/lite/dataclasses.py,sha256=k1588egoF3h_Kb21tuQb8WyJ9wxhT06EztFvaKOHzNU,1115
415
419
  omlish/lite/inject.py,sha256=qBUftFeXMiRgANYbNS2e7TePMYyFAcuLgsJiLyMTW5o,28769
416
420
  omlish/lite/json.py,sha256=7-02Ny4fq-6YAu5ynvqoijhuYXWpLmfCI19GUeZnb1c,740
417
421
  omlish/lite/logs.py,sha256=CWFG0NKGhqNeEgryF5atN2gkPYbUdTINEw_s1phbINM,51
@@ -427,13 +431,15 @@ omlish/lite/types.py,sha256=fP5EMyBdEp2LmDxcHjUDtwAMdR06ISr9lKOL7smWfHM,140
427
431
  omlish/lite/typing.py,sha256=U3-JaEnkDSYxK4tsu_MzUn3RP6qALBe5FXQXpD-licE,1090
428
432
  omlish/logs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
429
433
  omlish/logs/abc.py,sha256=ho4ABKYMKX-V7g4sp1BByuOLzslYzLlQ0MESmjEpT-o,8005
430
- omlish/logs/all.py,sha256=4Z6cNB0E1xbX0IOQWZEWLA0Jw-yyjhXa3PD_Nvfewu8,556
434
+ omlish/logs/all.py,sha256=Er2NIcDvlMpuAcRr9b_uMHeoERU7I6lu5oLrDGRdV0U,728
435
+ omlish/logs/callers.py,sha256=W0BdEtuGkQ0JM-FCsXQIBQCsNUbIsbDrtCaJy9DStk4,1143
431
436
  omlish/logs/color.py,sha256=CM-ceoPXs0j5_klnZDJkFCFRgHOToFzJyLjC6LsnPEk,665
432
437
  omlish/logs/configs.py,sha256=XOc8rWxfPpPMxJESVD2mLCUoLtbQnGnZwvYhhqe7DD8,772
433
438
  omlish/logs/filters.py,sha256=2noFRyBez3y519fpfsDSt1vo8wX-85b8sMXZi5o_xyE,208
434
439
  omlish/logs/handlers.py,sha256=zgSnKQA5q9Fu7T0Nkd7twog9H1Wg9-bDCzz4_F1TOBo,319
435
440
  omlish/logs/json.py,sha256=zyqMWpZY3lk4WRk4wgmataBomGX9S3iDsydiM1sS-lI,1366
436
441
  omlish/logs/noisy.py,sha256=Ubc-eTH6ZbGYsLfUUi69JAotwuUwzb-SJBeGo_0dIZI,348
442
+ omlish/logs/protocol.py,sha256=NzyCeNBN-fyKpJinhECfjUQSd5MxZLiYbuLCTtW6QUU,4500
437
443
  omlish/logs/proxy.py,sha256=A-ROPUUAlF397qTbEqhel6YhQMstNuXL3Xmts7w9dAo,2347
438
444
  omlish/logs/standard.py,sha256=FbKdF2Z4Na5i2TNwKn0avLJXyICe2JKsPufjvKCHGn0,3162
439
445
  omlish/logs/utils.py,sha256=mzHrZ9ji75p5A8qR29eUr05CBAHMb8J753MSkID_VaQ,393
@@ -444,7 +450,7 @@ omlish/marshal/__init__.py,sha256=iVA7n31L08Bdub6HKPvYOXVvDhk2CMA6rPeKDL_u1to,22
444
450
  omlish/marshal/any.py,sha256=e82OyYK3Emm1P1ClnsnxP7fIWC2iNVyW0H5nK4mLmWM,779
445
451
  omlish/marshal/base.py,sha256=HEzfby-PgGzIhiRpBkFrkw5-hKacRSC5W_jwLjT8aYw,6740
446
452
  omlish/marshal/base64.py,sha256=F-3ogJdcFCtWINRgJgWT0rErqgx6f4qahhcg8OrkqhE,1089
447
- omlish/marshal/dataclasses.py,sha256=G6Uh8t4vvNBAx2BhzH8ksj8Hq_bo6npFphQhyF298VU,6892
453
+ omlish/marshal/dataclasses.py,sha256=ZpfNaIdhKwWouWkoQGuequKwrEeehbz9QSQoW3acyPo,7756
448
454
  omlish/marshal/datetimes.py,sha256=0ffg8cEvx9SMKIXZGD9b7MqpLfmgw0uKKdn6YTfoqok,3714
449
455
  omlish/marshal/enums.py,sha256=CMAbx6RI2EcQoo7SoD-5q2l-3DFKreWMiOxs6mFpl_4,1472
450
456
  omlish/marshal/exceptions.py,sha256=jwQWn4LcPnadT2KRI_1JJCOSkwWh0yHnYK9BmSkNN4U,302
@@ -503,9 +509,14 @@ omlish/secrets/pwhash.py,sha256=Goktn-swmC6PXqfRBnDrH_Lr42vjckT712UyErPjzkw,4102
503
509
  omlish/secrets/secrets.py,sha256=cnDGBoPknVxsCN04_gqcJT_7Ebk3iO3VPkRZ2oMjkMw,7868
504
510
  omlish/secrets/subprocesses.py,sha256=ffjfbgPbEE_Pwb_87vG4yYR2CGZy3I31mHNCo_0JtHw,1212
505
511
  omlish/sockets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
506
- omlish/sockets/addresses.py,sha256=ZQFacDsXo6cKSgEjzN525IcUJPyfubXETzbY-_BBAro,1285
507
- omlish/sockets/handlers.py,sha256=9kkNMj1DTJa4xo_3hcBvSkjKc-dy_Ho5he2ubJieJ2A,621
508
- omlish/sockets/server.py,sha256=96vCNBvHSf8lWI3kd3RBbY0M2qXGaD_TksMhnBQ0_q0,1600
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
515
+ omlish/sockets/io.py,sha256=lfhTkB7NnAIx9kuQhAkwgsEUXY78Mp1_WtYrIQNS_k8,1408
516
+ 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/threading.py,sha256=YmW3Ym_p5j_F4SIH9BgRHIObywjq1HS39j9CGWIcMAY,2856
509
520
  omlish/specs/__init__.py,sha256=zZwF8yXTEkSstYtORkDhVLK-_hWU8WOJCuBpognb_NY,118
510
521
  omlish/specs/jmespath/LICENSE,sha256=IH-ZZlZkS8XMkf_ubNVD1aYHQ2l_wd0tmHtXrCcYpRU,1113
511
522
  omlish/specs/jmespath/__init__.py,sha256=9tsrquw1kXe1KAhTP3WeL0GlGBiTguQVxsC-lUYTWP4,2087
@@ -626,9 +637,9 @@ omlish/text/indent.py,sha256=YjtJEBYWuk8--b9JU_T6q4yxV85_TR7VEVr5ViRCFwk,1336
626
637
  omlish/text/minja.py,sha256=jZC-fp3Xuhx48ppqsf2Sf1pHbC0t8XBB7UpUUoOk2Qw,5751
627
638
  omlish/text/parts.py,sha256=7vPF1aTZdvLVYJ4EwBZVzRSy8XB3YqPd7JwEnNGGAOo,6495
628
639
  omlish/text/random.py,sha256=jNWpqiaKjKyTdMXC-pWAsSC10AAP-cmRRPVhm59ZWLk,194
629
- omlish-0.0.0.dev216.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
630
- omlish-0.0.0.dev216.dist-info/METADATA,sha256=6BbpSJ9xCRfRy70TaSmBaJwjRO0Zip85jN984Y1F2qo,4176
631
- omlish-0.0.0.dev216.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
632
- omlish-0.0.0.dev216.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
633
- omlish-0.0.0.dev216.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
634
- omlish-0.0.0.dev216.dist-info/RECORD,,
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,,