omlish 0.0.0.dev216__py3-none-any.whl → 0.0.0.dev218__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,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,,