omlish 0.0.0.dev216__py3-none-any.whl → 0.0.0.dev217__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.dev216'
2
- __revision__ = '4805bde6bf1ddb3b6c2099d185808394e0634392'
1
+ __version__ = '0.0.0.dev217'
2
+ __revision__ = 'd43ca6092cff650a9fc533e97d87ce9112f6f71a'
3
3
 
4
4
 
5
5
  #
@@ -1,6 +1,7 @@
1
1
  # ruff: noqa: I001
2
2
  from .asyncio import ( # noqa
3
- asyncio_once,
4
- drain_asyncio_tasks,
5
- draining_asyncio_tasks,
3
+ asyncio_once as once,
4
+ asyncio_wait_concurrent as wait_concurrent,
5
+ drain_asyncio_tasks as drain_tasks,
6
+ draining_asyncio_tasks as draining_tasks,
6
7
  )
@@ -93,8 +93,6 @@ from .impl.reflect import ( # noqa
93
93
  from .utils import ( # noqa
94
94
  is_immediate_dataclass,
95
95
 
96
- maybe_post_init,
97
-
98
96
  opt_repr,
99
97
  truthy_repr,
100
98
 
@@ -113,3 +111,9 @@ from .utils import ( # noqa
113
111
  iter_keys,
114
112
  iter_values,
115
113
  )
114
+
115
+ ##
116
+
117
+ from ..lite.dataclasses import ( # noqa
118
+ dataclass_maybe_post_init as maybe_post_init,
119
+ )
@@ -26,18 +26,6 @@ def is_immediate_dataclass(cls: type) -> bool:
26
26
  ##
27
27
 
28
28
 
29
- def maybe_post_init(sup: ta.Any) -> bool:
30
- try:
31
- fn = sup.__post_init__
32
- except AttributeError:
33
- return False
34
- fn()
35
- return True
36
-
37
-
38
- ##
39
-
40
-
41
29
  def opt_repr(o: ta.Any) -> str | None:
42
30
  return repr(o) if o is not None else None
43
31
 
omlish/docker/oci.py ADDED
@@ -0,0 +1,81 @@
1
+ # ruff: noqa: UP006 UP007
2
+ # @omlish-lite
3
+ import dataclasses as dc
4
+ import typing as ta
5
+
6
+ from omlish.lite import marshal as msh
7
+
8
+
9
+ @dc.dataclass(frozen=True)
10
+ class OciImageIndex:
11
+ """https://github.com/opencontainers/image-spec/blob/92353b0bee778725c617e7d57317b568a7796bd0/image-index.md"""
12
+
13
+ @dc.dataclass(frozen=True)
14
+ class Manifest:
15
+ digest: str
16
+ size: int
17
+
18
+ #
19
+
20
+ platform: ta.Optional[ta.Mapping[str, ta.Any]] = dc.field(default=None, metadata={msh.OBJ_MARSHALER_OMIT_IF_NONE: True}) # noqa
21
+ annotations: ta.Optional[ta.Mapping[str, str]] = dc.field(default=None, metadata={msh.OBJ_MARSHALER_OMIT_IF_NONE: True}) # noqa
22
+
23
+ #
24
+
25
+ MEDIA_TYPE: ta.ClassVar[str] = 'application/vnd.oci.image.manifest.v1+json'
26
+ media_type: str = dc.field(default=MEDIA_TYPE, metadata={msh.OBJ_MARSHALER_FIELD_KEY: 'mediaType'})
27
+
28
+ manifests: ta.Sequence[Manifest]
29
+
30
+ #
31
+
32
+ annotations: ta.Optional[ta.Mapping[str, str]] = dc.field(default=None, metadata={msh.OBJ_MARSHALER_OMIT_IF_NONE: True}) # noqa
33
+
34
+ #
35
+
36
+ SCHEMA_VERSION: ta.ClassVar[int] = 2
37
+ schema_version: int = dc.field(default=SCHEMA_VERSION, metadata={msh.OBJ_MARSHALER_FIELD_KEY: 'schemaVersion'})
38
+
39
+ MEDIA_TYPE: ta.ClassVar[str] = 'application/vnd.oci.image.index.v1+json'
40
+ media_type: str = dc.field(default=MEDIA_TYPE, metadata={msh.OBJ_MARSHALER_FIELD_KEY: 'mediaType'})
41
+
42
+
43
+ @dc.dataclass(frozen=True)
44
+ class OciImageManifest:
45
+ """https://github.com/opencontainers/image-spec/blob/92353b0bee778725c617e7d57317b568a7796bd0/manifest.md"""
46
+
47
+ @dc.dataclass(frozen=True)
48
+ class Config:
49
+ digest: str
50
+ size: int
51
+
52
+ #
53
+
54
+ MEDIA_TYPE: ta.ClassVar[str] = 'application/vnd.oci.image.config.v1+json'
55
+ media_type: str = dc.field(default=MEDIA_TYPE, metadata={msh.OBJ_MARSHALER_FIELD_KEY: 'mediaType'})
56
+
57
+ config: Config
58
+
59
+ @dc.dataclass(frozen=True)
60
+ class Layer:
61
+ digest: str
62
+ size: int
63
+
64
+ #
65
+
66
+ MEDIA_TYPES: ta.ClassVar[ta.Mapping[str, str]] = {
67
+ 'TAR': 'application/vnd.oci.image.layer.v1.tar',
68
+ 'TAR_GZIP': 'application/vnd.oci.image.layer.v1.tar+gzip',
69
+ 'TAR_ZSTD': 'application/vnd.oci.image.layer.v1.tar+zstd',
70
+ }
71
+ media_type: str = dc.field(default=MEDIA_TYPES['TAR'], metadata={msh.OBJ_MARSHALER_FIELD_KEY: 'mediaType'})
72
+
73
+ layers: ta.Sequence[Layer]
74
+
75
+ #
76
+
77
+ SCHEMA_VERSION: ta.ClassVar[int] = 2
78
+ schema_version: int = dc.field(default=SCHEMA_VERSION, metadata={msh.OBJ_MARSHALER_FIELD_KEY: 'schemaVersion'})
79
+
80
+ MEDIA_TYPE: ta.ClassVar[str] = 'application/vnd.oci.image.manifest.v1+json'
81
+ media_type: str = dc.field(default=MEDIA_TYPE, metadata={msh.OBJ_MARSHALER_FIELD_KEY: 'mediaType'})
@@ -0,0 +1,49 @@
1
+ # ruff: noqa: UP006 UP007
2
+ # @omlish-lite
3
+ import dataclasses as dc
4
+ import os
5
+ import typing as ta
6
+
7
+
8
+ @dc.dataclass(frozen=True)
9
+ class DockerPortRelay:
10
+ docker_port: int
11
+ host_port: int
12
+
13
+ name: ta.Optional[str] = None
14
+
15
+ DEFAULT_HOST_NAME: ta.ClassVar[str] = 'host.docker.internal'
16
+ host_name: str = DEFAULT_HOST_NAME
17
+
18
+ DEFAULT_INTERMEDIATE_PORT: ta.ClassVar[int] = 5000
19
+ intermediate_port: int = DEFAULT_INTERMEDIATE_PORT
20
+
21
+ DEFAULT_IMAGE: ta.ClassVar[str] = 'alpine/socat'
22
+ image: str = DEFAULT_IMAGE
23
+
24
+ def socat_args(self) -> ta.List[str]:
25
+ return [
26
+ '-d',
27
+ f'TCP-LISTEN:{self.intermediate_port},fork,reuseaddr',
28
+ f'TCP:{self.host_name}:{self.host_port}',
29
+ ]
30
+
31
+ def run_args(self) -> ta.List[str]:
32
+ if (name := self.name) is None:
33
+ name = f'docker_port_relay-{os.getpid()}'
34
+
35
+ return [
36
+ '--name', name,
37
+ '--rm',
38
+ '-p', f'{self.docker_port}:{self.intermediate_port}',
39
+ self.image,
40
+ *self.socat_args(),
41
+ ]
42
+
43
+ def run_cmd(self) -> ta.List[str]:
44
+ return [
45
+ 'docker',
46
+ 'run',
47
+ '-i',
48
+ *self.run_args(),
49
+ ]
omlish/lang/imports.py CHANGED
@@ -281,6 +281,10 @@ class NamePackage(ta.NamedTuple):
281
281
 
282
282
 
283
283
  class _ProxyInit:
284
+ class _Import(ta.NamedTuple):
285
+ pkg: str
286
+ attr: str
287
+
284
288
  def __init__(
285
289
  self,
286
290
  name_package: NamePackage,
@@ -294,31 +298,35 @@ class _ProxyInit:
294
298
  self._globals = globals
295
299
  self._update_globals = update_globals
296
300
 
297
- self._pkgs_by_attr: dict[str, str] = {}
301
+ self._imps_by_attr: dict[str, _ProxyInit._Import] = {}
298
302
  self._mods_by_pkgs: dict[str, ta.Any] = {}
299
303
 
300
304
  @property
301
305
  def name_package(self) -> NamePackage:
302
306
  return self._name_package
303
307
 
304
- def add(self, package: str, attrs: ta.Iterable[str]) -> None:
308
+ def add(self, package: str, attrs: ta.Iterable[str | tuple[str, str]]) -> None:
305
309
  if isinstance(attrs, str):
306
310
  raise TypeError(attrs)
307
311
  for attr in attrs:
308
- self._pkgs_by_attr[attr] = package
312
+ if isinstance(attr, tuple):
313
+ imp_attr, attr = attr
314
+ else:
315
+ imp_attr = attr
316
+ self._imps_by_attr[attr] = self._Import(package, imp_attr)
309
317
 
310
318
  def get(self, attr: str) -> ta.Any:
311
319
  try:
312
- pkg = self._pkgs_by_attr[attr]
320
+ imp = self._imps_by_attr[attr]
313
321
  except KeyError:
314
322
  raise AttributeError(attr) # noqa
315
323
 
316
324
  try:
317
- mod = self._mods_by_pkgs[pkg]
325
+ mod = self._mods_by_pkgs[imp.pkg]
318
326
  except KeyError:
319
- mod = importlib.import_module(pkg, package=self._name_package.package)
327
+ mod = importlib.import_module(imp.pkg, package=self._name_package.package)
320
328
 
321
- val = getattr(mod, attr)
329
+ val = getattr(mod, imp.attr)
322
330
 
323
331
  if self._update_globals and self._globals is not None:
324
332
  self._globals[attr] = val
@@ -329,7 +337,7 @@ class _ProxyInit:
329
337
  def proxy_init(
330
338
  globals: ta.MutableMapping[str, ta.Any], # noqa
331
339
  package: str,
332
- attrs: ta.Iterable[str],
340
+ attrs: ta.Iterable[str | tuple[str, str]],
333
341
  ) -> None:
334
342
  if isinstance(attrs, str):
335
343
  raise TypeError(attrs)
@@ -34,8 +34,10 @@ def dataclass_cache_hash(
34
34
 
35
35
 
36
36
  def dataclass_maybe_post_init(sup: ta.Any) -> bool:
37
+ if not isinstance(sup, super):
38
+ raise TypeError(sup)
37
39
  try:
38
- fn = sup.__post_init__
40
+ fn = sup.__post_init__ # type: ignore
39
41
  except AttributeError:
40
42
  return False
41
43
  fn()
@@ -9,6 +9,7 @@ from .. import collections as col
9
9
  from .. import dataclasses as dc
10
10
  from .. import lang
11
11
  from .. import reflect as rfl
12
+ from ..lite import marshal as lm
12
13
  from .base import MarshalContext
13
14
  from .base import Marshaler
14
15
  from .base import MarshalerFactory
@@ -96,6 +97,31 @@ def get_field_infos(
96
97
  unmarshal_names=col.unique([fmd.name, *(fmd.alts or ())]),
97
98
  )
98
99
 
100
+ else:
101
+ try:
102
+ lfk = field.metadata[lm.OBJ_MARSHALER_FIELD_KEY]
103
+ except KeyError:
104
+ pass
105
+ else:
106
+ if lfk is not None:
107
+ check.non_empty_str(lfk)
108
+ has_set_name = True
109
+ fi_kw.update(
110
+ marshal_name=lfk,
111
+ unmarshal_names=[lfk],
112
+ )
113
+ else:
114
+ fo_kw.update(
115
+ no_marshal=True,
116
+ no_unmarshal=True,
117
+ )
118
+
119
+ if (lon := field.metadata.get(lm.OBJ_MARSHALER_OMIT_IF_NONE)) is not None:
120
+ if check.isinstance(lon, bool):
121
+ fo_kw.update(
122
+ omit_if=lang.is_none,
123
+ )
124
+
99
125
  if fo_kw.get('embed') and not has_set_name:
100
126
  fi_kw.update(
101
127
  marshal_name=fi_kw['marshal_name'] + '_',
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.dev217
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=kDIujbwF1DOvbfOg4BotM1Kd9bV-L3rLG99gQZvd-EU,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,6 +224,8 @@ 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/oci.py,sha256=wbiOpZQWZtiCtyoDpZhYyHvwkZv5przil9DRLAvHrfs,2743
228
+ omlish/docker/portrelay.py,sha256=QlRoTnQXs5INguR7XOj1xH0gNdL9SUeZm5z45DUctXo,1222
227
229
  omlish/docker/timebomb.py,sha256=A_pgIDaXKsQwPiikrCTgIJl91gwYqkPGFY6j-Naq07Q,342
228
230
  omlish/formats/__init__.py,sha256=T0AG1gFnqQ5JiHN0UPQjQ-7g5tnxMIG-mgOvMYExYAM,21
229
231
  omlish/formats/cbor.py,sha256=o_Hbe4kthO9CeXK-FySrw0dHVlrdyTo2Y8PpGRDfZ3c,514
@@ -383,7 +385,7 @@ omlish/lang/descriptors.py,sha256=RRBbkMgTzg82fFFE4D0muqobpM-ZZaOta6yB1lpX3s8,66
383
385
  omlish/lang/exceptions.py,sha256=qJBo3NU1mOWWm-NhQUHCY5feYXR3arZVyEHinLsmRH4,47
384
386
  omlish/lang/functions.py,sha256=t9nsnWwhsibG0w908VMx-_pRM5tZfruE3faPxrCWTbI,4160
385
387
  omlish/lang/generators.py,sha256=5LX17j-Ej3QXhwBgZvRTm_dq3n9veC4IOUcVmvSu2vU,5243
386
- omlish/lang/imports.py,sha256=3C04Z0Hsj-BQIfHDWd-MQFGyZqTWuyJc2di6GfE-eUM,9327
388
+ omlish/lang/imports.py,sha256=oGigWiLkLog29mWWYdu7untyX--K1SueFmKzCpXdtug,9612
387
389
  omlish/lang/iterables.py,sha256=HOjcxOwyI5bBApDLsxRAGGhTTmw7fdZl2kEckxRVl-0,1994
388
390
  omlish/lang/maybes.py,sha256=1RN7chX_x2XvgUwryZRz0W7hAX-be3eEFcFub5vvf6M,3417
389
391
  omlish/lang/objects.py,sha256=LOC3JvX1g5hPxJ7Sv2TK9kNkAo9c8J-Jw2NmClR_rkA,4576
@@ -411,7 +413,7 @@ omlish/lite/cached.py,sha256=O7ozcoDNFm1Hg2wtpHEqYSp_i_nCLNOP6Ueq_Uk-7mU,1300
411
413
  omlish/lite/check.py,sha256=OLwtE2x6nlbGx4vS3Rda7zMHpgqzDSLJminTAX2lqLA,13529
412
414
  omlish/lite/configs.py,sha256=Ev_19sbII67pTWzInYjYqa9VyTiZBvyjhZqyG8TtufE,908
413
415
  omlish/lite/contextmanagers.py,sha256=ciaMl0D3QDHToM7M28-kwZ-Q48LtwgCxiud3nekgutA,2863
414
- omlish/lite/dataclasses.py,sha256=M6UD4VwGo0Ky7RNzKWbO0IOy7iBZVCIbTiC6EYbFnX8,1035
416
+ omlish/lite/dataclasses.py,sha256=k1588egoF3h_Kb21tuQb8WyJ9wxhT06EztFvaKOHzNU,1115
415
417
  omlish/lite/inject.py,sha256=qBUftFeXMiRgANYbNS2e7TePMYyFAcuLgsJiLyMTW5o,28769
416
418
  omlish/lite/json.py,sha256=7-02Ny4fq-6YAu5ynvqoijhuYXWpLmfCI19GUeZnb1c,740
417
419
  omlish/lite/logs.py,sha256=CWFG0NKGhqNeEgryF5atN2gkPYbUdTINEw_s1phbINM,51
@@ -444,7 +446,7 @@ omlish/marshal/__init__.py,sha256=iVA7n31L08Bdub6HKPvYOXVvDhk2CMA6rPeKDL_u1to,22
444
446
  omlish/marshal/any.py,sha256=e82OyYK3Emm1P1ClnsnxP7fIWC2iNVyW0H5nK4mLmWM,779
445
447
  omlish/marshal/base.py,sha256=HEzfby-PgGzIhiRpBkFrkw5-hKacRSC5W_jwLjT8aYw,6740
446
448
  omlish/marshal/base64.py,sha256=F-3ogJdcFCtWINRgJgWT0rErqgx6f4qahhcg8OrkqhE,1089
447
- omlish/marshal/dataclasses.py,sha256=G6Uh8t4vvNBAx2BhzH8ksj8Hq_bo6npFphQhyF298VU,6892
449
+ omlish/marshal/dataclasses.py,sha256=ZpfNaIdhKwWouWkoQGuequKwrEeehbz9QSQoW3acyPo,7756
448
450
  omlish/marshal/datetimes.py,sha256=0ffg8cEvx9SMKIXZGD9b7MqpLfmgw0uKKdn6YTfoqok,3714
449
451
  omlish/marshal/enums.py,sha256=CMAbx6RI2EcQoo7SoD-5q2l-3DFKreWMiOxs6mFpl_4,1472
450
452
  omlish/marshal/exceptions.py,sha256=jwQWn4LcPnadT2KRI_1JJCOSkwWh0yHnYK9BmSkNN4U,302
@@ -626,9 +628,9 @@ omlish/text/indent.py,sha256=YjtJEBYWuk8--b9JU_T6q4yxV85_TR7VEVr5ViRCFwk,1336
626
628
  omlish/text/minja.py,sha256=jZC-fp3Xuhx48ppqsf2Sf1pHbC0t8XBB7UpUUoOk2Qw,5751
627
629
  omlish/text/parts.py,sha256=7vPF1aTZdvLVYJ4EwBZVzRSy8XB3YqPd7JwEnNGGAOo,6495
628
630
  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,,
631
+ omlish-0.0.0.dev217.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
632
+ omlish-0.0.0.dev217.dist-info/METADATA,sha256=ej8P7o2EGJWFumDVus7JjRA14H1OZPQWWqQ_mB7vRhE,4176
633
+ omlish-0.0.0.dev217.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
634
+ omlish-0.0.0.dev217.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
635
+ omlish-0.0.0.dev217.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
636
+ omlish-0.0.0.dev217.dist-info/RECORD,,