omlish 0.0.0.dev292__py3-none-any.whl → 0.0.0.dev294__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.
omlish/__about__.py CHANGED
@@ -1,5 +1,5 @@
1
- __version__ = '0.0.0.dev292'
2
- __revision__ = '049add36e73b2356410aa68bca39c19cff8047d2'
1
+ __version__ = '0.0.0.dev294'
2
+ __revision__ = 'a8c5ea178d6688aa3681c24ef971c6e24d1eb392'
3
3
 
4
4
 
5
5
  #
omlish/configs/all.py CHANGED
@@ -1,4 +1,8 @@
1
1
  # ruff: noqa: I001
2
+ from .classes import ( # noqa
3
+ Configurable,
4
+ )
5
+
2
6
  from .formats import ( # noqa
3
7
  ConfigData as Data,
4
8
 
omlish/configs/classes.py CHANGED
@@ -8,6 +8,9 @@ from .. import lang
8
8
  ConfigurableConfigT = ta.TypeVar('ConfigurableConfigT', bound='Configurable.Config')
9
9
 
10
10
 
11
+ ##
12
+
13
+
11
14
  class Configurable(ta.Generic[ConfigurableConfigT], lang.Abstract):
12
15
  @dc.dataclass(frozen=True, kw_only=True)
13
16
  class Config:
@@ -15,7 +15,9 @@ from ...utils import class_decorator
15
15
  from ..fields.building import build_cls_std_fields
16
16
  from ..fields.conversion import std_field_to_field_spec
17
17
  from .metadata import extract_cls_metadata
18
+ from .params import STD_PARAM_DEFAULTS
18
19
  from .params import build_spec_std_params
20
+ from .params import get_class_spec
19
21
 
20
22
 
21
23
  ##
@@ -47,11 +49,19 @@ def dataclass(
47
49
  cache_hash: bool | None = None,
48
50
  generic_init: bool | None = None,
49
51
  override: bool | None = None,
52
+
50
53
  repr_id: bool | None = None,
54
+ terse_repr: bool | None = None,
55
+
56
+ allow_redundant_decorator: bool | None = None,
51
57
 
52
58
  #
53
59
 
54
60
  _plan_only: bool = False,
61
+
62
+ #
63
+
64
+ _kwargs: ta.Mapping[str, ta.Any] | None = None,
55
65
  ):
56
66
  if isinstance(metadata, ta.Mapping):
57
67
  raise TypeError(metadata)
@@ -60,6 +70,27 @@ def dataclass(
60
70
 
61
71
  cls = check.not_none(cls)
62
72
 
73
+ if STD_PARAMS_ATTR in cls.__dict__:
74
+ if (xcs := get_class_spec(cls)) is not None and xcs.allow_redundant_decorator:
75
+ xpd = {
76
+ a: getattr(xcs, a)
77
+ for a in STD_PARAM_DEFAULTS
78
+ }
79
+
80
+ dpd = {
81
+ **STD_PARAM_DEFAULTS,
82
+ **{k: v for k, v in (_kwargs or {}).items() if k in STD_PARAM_DEFAULTS},
83
+ }
84
+
85
+ if xpd == dpd:
86
+ check.in_(STD_FIELDS_ATTR, cls.__dict__)
87
+ return cls
88
+
89
+ raise TypeError(cls)
90
+
91
+ check.not_in(STD_PARAMS_ATTR, cls.__dict__)
92
+ check.not_in(STD_FIELDS_ATTR, cls.__dict__)
93
+
63
94
  #
64
95
 
65
96
  fields = build_cls_std_fields(
@@ -122,7 +153,11 @@ def dataclass(
122
153
  cache_hash=cache_hash,
123
154
  generic_init=generic_init,
124
155
  override=override,
156
+
125
157
  repr_id=repr_id,
158
+ terse_repr=terse_repr,
159
+
160
+ allow_redundant_decorator=allow_redundant_decorator,
126
161
  ),
127
162
  },
128
163
 
@@ -133,7 +168,6 @@ def dataclass(
133
168
  #
134
169
 
135
170
  std_params = build_spec_std_params(cs)
136
- check.not_in(STD_PARAMS_ATTR, cls.__dict__)
137
171
  setattr(cls, STD_PARAMS_ATTR, std_params)
138
172
 
139
173
  #
@@ -39,7 +39,11 @@ def make_dataclass( # noqa
39
39
  cache_hash: bool | None = None,
40
40
  generic_init: bool | None = None,
41
41
  override: bool | None = None,
42
+
42
43
  repr_id: bool | None = None,
44
+ terse_repr: bool | None = None,
45
+
46
+ allow_redundant_decorator: bool | None = None,
43
47
  ):
44
48
  if namespace is None:
45
49
  namespace = {}
@@ -105,5 +109,9 @@ def make_dataclass( # noqa
105
109
  cache_hash=cache_hash,
106
110
  generic_init=generic_init,
107
111
  override=override,
112
+
108
113
  repr_id=repr_id,
114
+ terse_repr=terse_repr,
115
+
116
+ allow_redundant_decorator=allow_redundant_decorator,
109
117
  )
@@ -9,6 +9,26 @@ from ...specs import ClassSpec
9
9
  ##
10
10
 
11
11
 
12
+ STD_PARAM_DEFAULTS: ta.Mapping[str, ta.Any] = dict(
13
+ init=True,
14
+ repr=True, # noqa
15
+ eq=True,
16
+ order=False,
17
+ unsafe_hash=False,
18
+ frozen=False,
19
+
20
+ match_args=True,
21
+ kw_only=False,
22
+ slots=False,
23
+ weakref_slot=False,
24
+ )
25
+
26
+ STD_PARAM_ATTRS: tuple[str, ...] = tuple(STD_PARAM_DEFAULTS)
27
+
28
+
29
+ ##
30
+
31
+
12
32
  class SpecDataclassParams(StdParams):
13
33
  __slots__ = (*StdParams.__slots__, '_spec')
14
34
 
@@ -11,25 +11,27 @@ from ..generation.ops import OpRef
11
11
  from ..generation.ops import Ref
12
12
  from ..generation.registry import register_generator_type
13
13
  from ..processing.base import ProcessingContext
14
+ from ..specs import FieldSpec
14
15
  from ..specs import FieldType
15
16
  from ..specs import ReprFn
17
+ from .fields import InitFields
16
18
 
17
19
 
18
20
  ##
19
21
 
20
22
 
21
- @dc.dataclass(frozen=True)
23
+ @dc.dataclass(frozen=True, kw_only=True)
22
24
  class ReprPlan(Plan):
23
- fields: tuple[str, ...]
25
+ @dc.dataclass(frozen=True, kw_only=True)
26
+ class Field:
27
+ name: str
28
+ kw_only: bool = False
29
+ fn: OpRef[ReprFn] | None = None
24
30
 
25
- @dc.dataclass(frozen=True)
26
- class Fn:
27
- field: str
28
- fn: OpRef[ReprFn]
29
-
30
- fns: tuple[Fn, ...] = ()
31
+ fields: tuple[Field, ...]
31
32
 
32
33
  id: bool = False
34
+ terse: bool = False
33
35
 
34
36
 
35
37
  @register_generator_type(ReprPlan)
@@ -38,22 +40,37 @@ class ReprGenerator(Generator[ReprPlan]):
38
40
  if not ctx.cs.repr or '__repr__' in ctx.cls.__dict__:
39
41
  return None
40
42
 
41
- fs = sorted(ctx.cs.fields, key=lambda f: f.repr_priority or 0)
43
+ ifs = ctx[InitFields]
44
+ fs: ta.Sequence[FieldSpec]
45
+ if ctx.cs.terse_repr:
46
+ # If terse repr will match init param order
47
+ fs = ifs.all
48
+ else:
49
+ # Otherwise default to dc.fields() order
50
+ fs = sorted(ctx.cs.fields, key=lambda f: f.repr_priority or 0)
42
51
 
43
52
  orm = {}
44
- rfs: list[ReprPlan.Fn] = []
53
+ rfs: list[ReprPlan.Field] = []
45
54
  for i, f in enumerate(fs):
46
- if f.repr_fn is None:
55
+ if not (f.field_type is FieldType.INSTANCE and f.repr):
47
56
  continue
48
- r: OpRef = OpRef(f'repr.fns.{i}.fn')
49
- orm[r] = f.repr_fn
50
- rfs.append(ReprPlan.Fn(f.name, r))
57
+
58
+ fnr: OpRef | None = None
59
+ if f.repr_fn is not None:
60
+ fnr = OpRef(f'repr.fns.{i}.fn')
61
+ orm[fnr] = f.repr_fn
62
+
63
+ rfs.append(ReprPlan.Field(
64
+ name=f.name,
65
+ kw_only=f in ifs.kw_only,
66
+ fn=fnr,
67
+ ))
51
68
 
52
69
  return PlanResult(
53
70
  ReprPlan(
54
- fields=tuple(f.name for f in fs if f.field_type is FieldType.INSTANCE and f.repr),
55
- fns=tuple(rfs),
71
+ fields=tuple(rfs),
56
72
  id=ctx.cs.repr_id,
73
+ terse=ctx.cs.terse_repr,
57
74
  ),
58
75
  orm,
59
76
  )
@@ -63,17 +80,20 @@ class ReprGenerator(Generator[ReprPlan]):
63
80
 
64
81
  part_lines: list[str] = []
65
82
 
66
- rfd = {rf.field: rf.fn for rf in pl.fns}
67
83
  for f in pl.fields:
68
- if (rf := rfd.get(f)) is not None:
69
- ors.add(rf)
84
+ pfx = ''
85
+ if not (pl.terse and not f.kw_only):
86
+ pfx = f'{f.name}='
87
+
88
+ if f.fn is not None:
89
+ ors.add(f.fn)
70
90
  part_lines.extend([
71
- f' if (s := {rf.ident()}(self.{f})) is not None:',
72
- f' parts.append(f"{f}={{s}}")',
91
+ f' if (s := {f.fn.ident()}(self.{f.name})) is not None:',
92
+ f' parts.append(f"{pfx}{{s}}")',
73
93
  ])
74
94
  else:
75
95
  part_lines.append(
76
- f' parts.append(f"{f}={{self.{f}!r}}")',
96
+ f' parts.append(f"{pfx}{{self.{f.name}!r}}")',
77
97
  )
78
98
 
79
99
  return [
@@ -1,5 +1,6 @@
1
1
  import typing as ta
2
2
 
3
+ from ..api.classes.decorator import dataclass
3
4
  from ..concerns.frozen import unchecked_frozen_base
4
5
  from .meta import DataMeta
5
6
  from .specs import get_metaclass_spec
@@ -16,9 +17,11 @@ T = ta.TypeVar('T')
16
17
  class Data(
17
18
  eq=False,
18
19
  order=False,
20
+ allow_redundant_decorator=True,
19
21
  confer=frozenset([
20
22
  'confer',
21
23
  'final_subclasses',
24
+ 'allow_redundant_decorator',
22
25
  ]),
23
26
  metaclass=DataMeta,
24
27
  ):
@@ -31,6 +34,9 @@ class Data(
31
34
  super().__init_subclass__(**kwargs)
32
35
 
33
36
 
37
+ #
38
+
39
+
34
40
  class Frozen(
35
41
  Data,
36
42
  frozen=True,
@@ -47,6 +53,9 @@ class Frozen(
47
53
  pass
48
54
 
49
55
 
56
+ #
57
+
58
+
50
59
  class Case(
51
60
  Frozen,
52
61
  abstract=True,
@@ -57,13 +66,19 @@ class Case(
57
66
  pass
58
67
 
59
68
 
69
+ #
70
+
71
+
72
+ @dataclass(frozen=True)
60
73
  class Box(
61
74
  Frozen,
62
75
  ta.Generic[T],
63
76
  generic_init=True,
77
+ terse_repr=True,
64
78
  confer=frozenset([
65
79
  *get_metaclass_spec(Frozen).confer,
66
80
  'generic_init',
81
+ 'terse_repr',
67
82
  ]),
68
83
  ):
69
84
  v: T
@@ -17,6 +17,11 @@ CONFER_CLASS_PARAMS: tuple[str, ...] = (
17
17
  'cache_hash',
18
18
  'generic_init',
19
19
  'override',
20
+
21
+ 'repr_id',
22
+ 'terse_repr',
23
+
24
+ 'allow_redundant_decorator',
20
25
  )
21
26
 
22
27
  CONFER_METACLASS_PARAMS: tuple[str, ...] = (
@@ -183,7 +183,11 @@ class ClassSpec(lang.Final):
183
183
  cache_hash: bool = False
184
184
  generic_init: bool = False
185
185
  override: bool = False
186
+
186
187
  repr_id: bool = False
188
+ terse_repr: bool = False
189
+
190
+ allow_redundant_decorator: bool = False
187
191
 
188
192
  ##
189
193
  # callbacks
@@ -75,7 +75,7 @@ def class_decorator(fn):
75
75
  @functools.wraps(fn)
76
76
  def inner(cls=None, *args, **kwargs):
77
77
  if cls is None:
78
- return lambda cls: fn(cls, *args, **kwargs) # noqa
78
+ return lambda cls: fn(cls, *args, _kwargs=kwargs, **kwargs) # noqa
79
79
  return fn(cls, *args, **kwargs)
80
80
  return inner
81
81
 
@@ -1,8 +1,7 @@
1
1
  # ruff: noqa: N802 N803
2
2
  import typing as ta
3
3
 
4
- from omlish import antlr
5
-
4
+ from ... import antlr
6
5
  from ._antlr.Json5Lexer import Json5Lexer # type: ignore
7
6
  from ._antlr.Json5Parser import Json5Parser # type: ignore
8
7
  from ._antlr.Json5Visitor import Json5Visitor # type: ignore
omlish/secrets/all.py CHANGED
@@ -15,6 +15,8 @@ from .secrets import ( # noqa
15
15
  secret_repr,
16
16
  )
17
17
 
18
+ ref = SecretRef
19
+
18
20
 
19
21
  ##
20
22
 
omlish/secrets/secrets.py CHANGED
@@ -59,6 +59,7 @@ class Secret(lang.NotPicklable, lang.Sensitive, lang.Final):
59
59
 
60
60
 
61
61
  @dc.dataclass(frozen=True)
62
+ @dc.extra_class_params(terse_repr=True)
62
63
  class SecretRef:
63
64
  key: str
64
65
 
@@ -66,10 +67,10 @@ class SecretRef:
66
67
  SecretRefOrStr: ta.TypeAlias = SecretRef | str
67
68
 
68
69
 
69
- def secret_repr(o: SecretRefOrStr | None) -> str | None:
70
+ def secret_repr(o: Secret | SecretRef | str | None) -> str | None:
70
71
  if isinstance(o, str):
71
72
  return '...'
72
- elif isinstance(o, SecretRef):
73
+ elif isinstance(o, (Secret, SecretRef)):
73
74
  return repr(o)
74
75
  elif o is None:
75
76
  return None
omlish/text/filecache.py CHANGED
@@ -131,7 +131,7 @@ class TextFileCache:
131
131
 
132
132
  #
133
133
 
134
- def _normalize_path(self, path: str) -> str:
134
+ def normalize_path(self, path: str) -> str:
135
135
  return abs_real_path(path)
136
136
 
137
137
  #
@@ -217,7 +217,7 @@ class TextFileCache:
217
217
  check_stat: bool = False,
218
218
  or_raise: bool = False,
219
219
  ) -> Entry:
220
- path = self._normalize_path(path)
220
+ path = self.normalize_path(path)
221
221
 
222
222
  with self._lock:
223
223
  return self._get_entry(
@@ -229,7 +229,7 @@ class TextFileCache:
229
229
  #
230
230
 
231
231
  def invalidate(self, path: str) -> bool:
232
- path = self._normalize_path(path)
232
+ path = self.normalize_path(path)
233
233
 
234
234
  with self._lock:
235
235
  return self._dct.pop(path, None) is not None
@@ -8,6 +8,12 @@ from .collection import ( # noqa
8
8
  TypedValues,
9
9
  )
10
10
 
11
+ from .consumer import ( # noqa
12
+ UnconsumedTypedValuesError,
13
+
14
+ TypedValuesConsumer,
15
+ )
16
+
11
17
  from .generic import ( # noqa
12
18
  TypedValueGeneric,
13
19
  )
@@ -26,6 +32,8 @@ from .values import ( # noqa
26
32
  UniqueTypedValue,
27
33
 
28
34
  ScalarTypedValue,
35
+
36
+ UniqueScalarTypedValue,
29
37
  )
30
38
 
31
39
 
@@ -6,6 +6,7 @@ TODO:
6
6
  import abc
7
7
  import typing as ta
8
8
 
9
+ from .. import check
9
10
  from .. import lang
10
11
  from .values import TypedValue # noqa
11
12
  from .values import UniqueTypedValue # noqa
@@ -22,6 +23,10 @@ UniqueTypedValueU = ta.TypeVar('UniqueTypedValueU', bound='UniqueTypedValue')
22
23
  ##
23
24
 
24
25
 
26
+ class _NOT_SET(lang.Marker): # noqa
27
+ pass
28
+
29
+
25
30
  class TypedValuesAccessor(lang.Abstract, ta.Generic[TypedValueT]):
26
31
  def __iter__(self):
27
32
  raise TypeError(
@@ -32,7 +37,7 @@ class TypedValuesAccessor(lang.Abstract, ta.Generic[TypedValueT]):
32
37
 
33
38
  @ta.final
34
39
  def __contains__(self, cls: type[TypedValueU]) -> bool:
35
- raise NotImplementedError
40
+ return self._typed_value_contains(cls)
36
41
 
37
42
  @abc.abstractmethod
38
43
  def _typed_value_contains(self, cls):
@@ -97,17 +102,20 @@ class TypedValuesAccessor(lang.Abstract, ta.Generic[TypedValueT]):
97
102
  ...
98
103
 
99
104
  @ta.final
100
- def get(self, key, /, default=None):
105
+ def get(self, key, /, default=_NOT_SET):
101
106
  if not isinstance(key, type):
102
- if default is not None:
107
+ if default is not _NOT_SET:
103
108
  raise RuntimeError('Must not provide both an instance key and a default')
104
109
  default = key
105
110
  key = type(default)
106
- return self._typed_value_get(key, default)
107
-
108
- @abc.abstractmethod
109
- def _typed_value_get(self, key, /, default=None):
110
- raise NotImplementedError
111
+ elif default is _NOT_SET:
112
+ default = None
113
+
114
+ check.issubclass(key, TypedValue)
115
+ try:
116
+ return self._typed_value_getitem(key)
117
+ except KeyError:
118
+ return default
111
119
 
112
120
  #
113
121
 
@@ -4,6 +4,7 @@ from .. import check
4
4
  from .. import dataclasses as dc
5
5
  from .. import lang
6
6
  from .accessor import TypedValuesAccessor
7
+ from .consumer import TypedValuesConsumer
7
8
  from .values import TypedValue
8
9
  from .values import UniqueTypedValue
9
10
 
@@ -28,7 +29,12 @@ class TypedValues(
28
29
  lang.Final,
29
30
  ta.Generic[TypedValueT],
30
31
  ):
31
- def __init__(self, *tvs: TypedValueT, override: bool = False) -> None:
32
+ def __init__(
33
+ self,
34
+ *tvs: TypedValueT,
35
+ override: bool = False,
36
+ check_type: type | tuple[type, ...] | None = None,
37
+ ) -> None:
32
38
  if hasattr(self, '_tup'):
33
39
  # When __new__ returns the empty singleton __init__ will still be called.
34
40
  if self is not self._EMPTY:
@@ -40,6 +46,8 @@ class TypedValues(
40
46
  tmp: list = []
41
47
  udct: dict = {}
42
48
  for tv in tvs:
49
+ if check_type is not None:
50
+ check.isinstance(tv, check_type)
43
51
  if isinstance(tv, UniqueTypedValue):
44
52
  utvc = tv._unique_typed_value_cls # noqa
45
53
  if not override:
@@ -65,7 +73,6 @@ class TypedValues(
65
73
  if idx == len(ulst):
66
74
  lst.append(tv)
67
75
  dct[utvc] = tv
68
- dct[type(tv)] = tv
69
76
  else:
70
77
  tv = obj
71
78
  lst.append(tv)
@@ -76,6 +83,10 @@ class TypedValues(
76
83
  k: tuple(v) if isinstance(v, list) else v
77
84
  for k, v in dct.items()
78
85
  }
86
+ self._dct2: dict[type[TypedValueT], TypedValueT | tuple[TypedValueT, ...]] = {
87
+ **self._dct,
88
+ **{type(v): v for v in self._dct.values() if isinstance(v, UniqueTypedValue)}, # type: ignore[misc]
89
+ }
79
90
 
80
91
  #
81
92
 
@@ -161,29 +172,33 @@ class TypedValues(
161
172
 
162
173
  #
163
174
 
175
+ def keys(self) -> ta.KeysView[type[TypedValueT]]:
176
+ return self._dct.keys()
177
+
178
+ def values(self) -> ta.ValuesView[TypedValueT | tuple[TypedValueT, ...]]:
179
+ return self._dct.values()
180
+
181
+ def items(self) -> ta.ItemsView[type[TypedValueT], TypedValueT | tuple[TypedValueT, ...]]:
182
+ return self._dct.items()
183
+
184
+ #
185
+
186
+ def consume(self) -> TypedValuesConsumer[TypedValueT]:
187
+ return TypedValuesConsumer(self._dct.items())
188
+
189
+ #
190
+
164
191
  def _typed_value_contains(self, cls):
165
- return cls in self._dct
192
+ return cls in self._dct2
166
193
 
167
194
  def _typed_value_getitem(self, key):
168
195
  if isinstance(key, int):
169
196
  return self._tup[key]
170
197
  elif isinstance(key, type):
171
- return self._dct[check.issubclass(key, TypedValue)]
198
+ return self._dct2[check.issubclass(key, TypedValue)]
172
199
  else:
173
200
  raise TypeError(key)
174
201
 
175
- def _typed_value_get(self, key, /, default=None):
176
- check.issubclass(key, TypedValue)
177
- try:
178
- return self._dct[key]
179
- except KeyError:
180
- if issubclass(key, UniqueTypedValue):
181
- return default
182
- elif default is not None:
183
- return tuple(default)
184
- else:
185
- return ()
186
-
187
202
  _any_dct: dict[type, tuple[TypedValueT, ...]]
188
203
 
189
204
  def _typed_value_get_any(self, cls):
@@ -192,10 +207,12 @@ class TypedValues(
192
207
  except AttributeError:
193
208
  any_dct = {}
194
209
  self._any_dct = any_dct
210
+
195
211
  try:
196
212
  return any_dct[cls]
197
213
  except KeyError:
198
214
  pass
215
+
199
216
  ret = tuple(tv for tv in self if isinstance(tv, cls))
200
217
  any_dct[cls] = ret
201
218
  return ret
@@ -0,0 +1,175 @@
1
+ # ruff: noqa: UP007
2
+ import dataclasses as dc
3
+ import typing as ta
4
+
5
+ from .. import check
6
+ from .. import lang
7
+ from .values import ScalarTypedValue
8
+ from .values import TypedValue
9
+ from .values import UniqueTypedValue
10
+
11
+
12
+ if ta.TYPE_CHECKING:
13
+ from . import collection as tvc
14
+ else:
15
+ tvc = lang.proxy_import('.collection', __package__)
16
+
17
+
18
+ TypedValueT = ta.TypeVar('TypedValueT', bound=TypedValue)
19
+ TypedValueU = ta.TypeVar('TypedValueU', bound=TypedValue)
20
+
21
+ UniqueTypedValueU = ta.TypeVar('UniqueTypedValueU', bound=UniqueTypedValue)
22
+
23
+
24
+ ##
25
+
26
+
27
+ @dc.dataclass()
28
+ class UnconsumedTypedValuesError(Exception):
29
+ values: ta.Sequence[TypedValue]
30
+
31
+
32
+ class _NOT_SET(lang.Marker): # noqa
33
+ pass
34
+
35
+
36
+ class TypedValuesConsumer(ta.Generic[TypedValueT]):
37
+ def __init__(
38
+ self,
39
+ src: ta.Union[
40
+ 'tvc.TypedValues',
41
+ ta.Iterable[tuple[type[TypedValueT], TypedValueT | tuple[TypedValueT, ...]]],
42
+ ta.Mapping[type[TypedValueT], TypedValueT | tuple[TypedValueT, ...]],
43
+ ],
44
+ ) -> None:
45
+ super().__init__()
46
+
47
+ kvs: ta.Iterable[tuple[type[TypedValueT], TypedValueT | tuple[TypedValueT, ...]]]
48
+ if isinstance(src, tvc.TypedValues):
49
+ kvs = src.items()
50
+ elif isinstance(src, ta.Mapping):
51
+ kvs = src.items()
52
+ else:
53
+ kvs = src
54
+
55
+ dct: dict = {}
56
+ for k, v in kvs:
57
+ check.not_in(k, dct)
58
+ dct[k] = v
59
+
60
+ self._dct: dict[type[TypedValueT], TypedValueT | tuple[TypedValueT, ...]] = dct
61
+
62
+ #
63
+
64
+ def check_empty(self) -> None:
65
+ if bool(self._dct):
66
+ raise UnconsumedTypedValuesError(list(self))
67
+
68
+ def __enter__(self) -> 'TypedValuesConsumer[TypedValueT]':
69
+ return self
70
+
71
+ def __exit__(self, exc_type, exc_val, exc_tb):
72
+ self.check_empty()
73
+
74
+ #
75
+
76
+ def __iter__(self) -> ta.Iterator[TypedValueT]:
77
+ for v in self._dct.values():
78
+ if isinstance(v, tuple):
79
+ yield from v
80
+ else:
81
+ yield v
82
+
83
+ def __len__(self) -> int:
84
+ return len(self._dct)
85
+
86
+ def __bool__(self) -> bool:
87
+ return bool(self._dct)
88
+
89
+ #
90
+
91
+ def keys(self) -> ta.KeysView[type[TypedValueT]]:
92
+ return self._dct.keys()
93
+
94
+ def values(self) -> ta.ValuesView[TypedValueT | tuple[TypedValueT, ...]]:
95
+ return self._dct.values()
96
+
97
+ def items(self) -> ta.ItemsView[type[TypedValueT], TypedValueT | tuple[TypedValueT, ...]]:
98
+ return self._dct.items()
99
+
100
+ #
101
+
102
+ @ta.overload
103
+ def pop(
104
+ self,
105
+ tv: UniqueTypedValueU,
106
+ ) -> UniqueTypedValueU:
107
+ ...
108
+
109
+ @ta.overload
110
+ def pop(
111
+ self,
112
+ cls: type[UniqueTypedValueU],
113
+ /,
114
+ default: UniqueTypedValueU,
115
+ ) -> UniqueTypedValueU:
116
+ ...
117
+
118
+ @ta.overload
119
+ def pop(
120
+ self,
121
+ cls: type[UniqueTypedValueU],
122
+ /,
123
+ default: UniqueTypedValueU | None,
124
+ ) -> UniqueTypedValueU | None:
125
+ ...
126
+
127
+ @ta.overload
128
+ def pop(
129
+ self,
130
+ cls: type[TypedValueU],
131
+ ) -> ta.Sequence[TypedValueU]:
132
+ ...
133
+
134
+ @ta.overload
135
+ def pop(
136
+ self,
137
+ cls: type[TypedValueU],
138
+ /,
139
+ default: ta.Iterable[TypedValueU],
140
+ ) -> ta.Sequence[TypedValueU]:
141
+ ...
142
+
143
+ def pop(self, key, /, default=_NOT_SET):
144
+ if not isinstance(key, type):
145
+ if default is not _NOT_SET:
146
+ raise RuntimeError('Must not provide both an instance key and a default')
147
+ default = key
148
+ key = type(default)
149
+
150
+ if (
151
+ issubclass(key, UniqueTypedValue) and
152
+ (utvc := key._unique_typed_value_cls) is not key # noqa
153
+ ):
154
+ key = utvc
155
+
156
+ try:
157
+ return self._dct.pop(key)
158
+ except KeyError:
159
+ if default is not _NOT_SET:
160
+ return default
161
+ else:
162
+ raise
163
+
164
+ #
165
+
166
+ def pop_scalar_kwargs(self, **kwargs: type[TypedValueT]) -> dict[str, TypedValueT]:
167
+ dct: dict[str, TypedValueT] = {}
168
+ for k, vc in kwargs.items():
169
+ check.issubclass(vc, ScalarTypedValue)
170
+ try:
171
+ v = self.pop(vc)
172
+ except KeyError:
173
+ continue
174
+ dct[k] = v.v # type: ignore[attr-defined]
175
+ return dct
@@ -1,16 +1,14 @@
1
1
  import abc
2
2
  import typing as ta
3
3
 
4
- from .. import check
5
4
  from .. import lang
6
5
  from .accessor import TypedValuesAccessor
7
6
  from .collection import TypedValues
8
7
  from .generic import TypedValueGeneric
9
8
  from .values import TypedValue
10
- from .values import UniqueTypedValue
11
9
 
12
10
 
13
- TypedValueT = ta.TypeVar('TypedValueT', bound='TypedValue')
11
+ TypedValueT = ta.TypeVar('TypedValueT', bound=TypedValue)
14
12
 
15
13
 
16
14
  ##
@@ -43,17 +41,6 @@ class TypedValueHolder(
43
41
  else:
44
42
  raise TypeError(key)
45
43
 
46
- def _typed_value_get(self, key, /, default=None):
47
- if (tvs := self._typed_values) is not None:
48
- return tvs.get(key, default)
49
- check.issubclass(key, TypedValue)
50
- if issubclass(key, UniqueTypedValue):
51
- return default
52
- elif default is not None:
53
- return list(default)
54
- else:
55
- return []
56
-
57
44
  def _typed_value_get_any(self, cls):
58
45
  if (tvs := self._typed_values) is not None:
59
46
  return tvs.get_any(cls)
@@ -1,10 +1,9 @@
1
- from omlish import check
2
- from omlish import dataclasses as dc
3
- from omlish import lang
4
- from omlish import marshal as msh
5
- from omlish import reflect as rfl
6
- from omlish.funcs import match as mfs
7
-
1
+ from .. import check
2
+ from .. import dataclasses as dc
3
+ from .. import lang
4
+ from .. import marshal as msh
5
+ from .. import reflect as rfl
6
+ from ..funcs import match as mfs
8
7
  from .collection import TypedValues
9
8
  from .reflect import reflect_typed_values_impls
10
9
  from .values import ScalarTypedValue
@@ -1,8 +1,7 @@
1
1
  import typing as ta
2
2
 
3
- from omlish import check
4
- from omlish import reflect as rfl
5
-
3
+ from .. import check
4
+ from .. import reflect as rfl
6
5
  from .values import TypedValue
7
6
 
8
7
 
@@ -1,3 +1,7 @@
1
+ """
2
+ TODO:
3
+ - dc.Box, or some other kind of meta
4
+ """
1
5
  import typing as ta
2
6
 
3
7
  from .. import dataclasses as dc
@@ -17,13 +21,16 @@ class TypedValue(lang.Abstract):
17
21
  ##
18
22
 
19
23
 
24
+ _UNIQUE_BASES: set[type[TypedValue]] = set()
25
+
26
+
20
27
  class UniqueTypedValue(TypedValue, lang.Abstract):
21
28
  _unique_typed_value_cls: ta.ClassVar[type[TypedValue]]
22
29
 
23
30
  def __init_subclass__(cls, **kwargs: ta.Any) -> None:
24
31
  super().__init_subclass__(**kwargs)
25
32
 
26
- if UniqueTypedValue in cls.__bases__:
33
+ if any(ur in cls.__bases__ for ur in _UNIQUE_BASES):
27
34
  try:
28
35
  cls._unique_typed_value_cls # noqa
29
36
  except AttributeError:
@@ -35,16 +42,25 @@ class UniqueTypedValue(TypedValue, lang.Abstract):
35
42
  ##
36
43
 
37
44
 
38
- @dc.dataclass(frozen=True)
39
- @dc.extra_class_params(generic_init=True)
40
- class ScalarTypedValue(TypedValue, lang.Abstract, ta.Generic[T]):
41
- v: T
42
-
43
- def __repr__(self) -> str:
44
- return f'{self.__class__.__name__}({self.v!r})'
45
-
45
+ class ScalarTypedValue(TypedValue, dc.Box[T], abstract=True):
46
46
  def __init_subclass__(cls, **kwargs: ta.Any) -> None:
47
47
  super().__init_subclass__(**kwargs)
48
48
 
49
49
  if UniqueTypedValue in (mro := cls.__mro__) and mro.index(ScalarTypedValue) > mro.index(UniqueTypedValue):
50
- raise TypeError(f'Class {cls} must have UniqueTypedValue before ScalarTypedValue in mro')
50
+ raise TypeError(f'Class {cls} must not have UniqueTypedValue before ScalarTypedValue in mro')
51
+
52
+
53
+ ##
54
+
55
+
56
+ class UniqueScalarTypedValue(ScalarTypedValue[T], UniqueTypedValue, abstract=True):
57
+ pass
58
+
59
+
60
+ ##
61
+
62
+
63
+ _UNIQUE_BASES.update([
64
+ UniqueTypedValue,
65
+ UniqueScalarTypedValue,
66
+ ])
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: omlish
3
- Version: 0.0.0.dev292
3
+ Version: 0.0.0.dev294
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -1,5 +1,5 @@
1
1
  omlish/.manifests.json,sha256=pjGUyLHaoWpPqRP3jz2u1fC1qoRc2lvrEcpU_Ax2tdg,8253
2
- omlish/__about__.py,sha256=35DcIUR8xZ1fV59-t4ejDVrAHFLqGSDxuBoLBDriBvA,3444
2
+ omlish/__about__.py,sha256=h0CCG_UNc66bAsV21kg7z2dMtYQmx6M9HituQ3gMevU,3444
3
3
  omlish/__init__.py,sha256=SsyiITTuK0v74XpKV8dqNaCmjOlan1JZKrHQv5rWKPA,253
4
4
  omlish/c3.py,sha256=rer-TPOFDU6fYq_AWio_AmA-ckZ8JDY5shIzQ_yXfzA,8414
5
5
  omlish/cached.py,sha256=MLap_p0rdGoDIMVhXVHm1tsbcWobJF0OanoodV03Ju8,542
@@ -179,8 +179,8 @@ omlish/concurrent/executors.py,sha256=mF-rjJWzNFxwB1-_H7rHuwoImpl4FtNM6W3wcqM3NE
179
179
  omlish/concurrent/futures.py,sha256=870tx8ELI8THvMnTrQoYIlEFKO9hM4KUrlehckJqKBU,4238
180
180
  omlish/concurrent/threadlets.py,sha256=JfirbTDJgy9Ouokz_VmHeAAPS7cih8qMUJrN-owwXD4,2423
181
181
  omlish/configs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
182
- omlish/configs/all.py,sha256=kziwjzUBkf8AT0w7Pq7JX2jtkQVOQ5R1wJyn6hfTN5k,1055
183
- omlish/configs/classes.py,sha256=9uelgi9gS5Sf8ZbtydNXhMxjBs7xBxGZgfuK0Vbc2cg,1168
182
+ omlish/configs/all.py,sha256=xTfR7NySnlIeqhk0GlUOncPnWZ97cLhCtRDlN_Ny8og,1107
183
+ omlish/configs/classes.py,sha256=bRQ3NiYWpHNXspu7P52_9d-00P9YQz_cV8zWXTY2BZE,1173
184
184
  omlish/configs/formats.py,sha256=RJw4Rzp7vlTd5YyAvpAoruQnk45v8dGPtPWwqH7aYyE,5301
185
185
  omlish/configs/nginx.py,sha256=XuX9yyb0_MwkJ8esKiMS9gFkqHUPza_uCprhnWykNy8,2051
186
186
  omlish/configs/shadow.py,sha256=-R5nbevC4pFgqDPYOCCIqNcusgXsMWlRIUOEG0HBoJg,2228
@@ -208,15 +208,15 @@ omlish/dataclasses/errors.py,sha256=tyv3WR6az66uGGiq9FIuCHvy1Ef-G7zeMY7mMG6hy2Y,
208
208
  omlish/dataclasses/inspect.py,sha256=BlpPghVCU3w_YDnONEqqE99YHzJM2q3eoqe39YX25Ko,4596
209
209
  omlish/dataclasses/internals.py,sha256=vIGCZnStgD3ef4drYRtVOrxhxmAPa0vJpo4pXcDcQvM,3073
210
210
  omlish/dataclasses/reflection.py,sha256=5N4acL27xwSnQJvoks6ts2JseGfwL_P9D2gM9vqtAFM,2243
211
- omlish/dataclasses/specs.py,sha256=h9qD2xAijKAS95Iw3GUPx3mj1peoUOlgh7aXtqVfmDU,6073
212
- omlish/dataclasses/utils.py,sha256=_1B6tEkkcxHVoLBEo34ebR_0E-iZW7W0zFTo27EdSqY,1854
211
+ omlish/dataclasses/specs.py,sha256=r9hpIWy83ODiB1n7wTf7JL5fiCeeT8fWbMvxs7c4e3g,6148
212
+ omlish/dataclasses/utils.py,sha256=gv6za6oJYBr1VaeGd7oXqq9lhBs_sxkpC27XYzJggno,1870
213
213
  omlish/dataclasses/api/__init__.py,sha256=GFodt19CKrfuBpdv1EUqVUCPAFIlHPnabE2G8QJElBY,426
214
214
  omlish/dataclasses/api/classes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
215
215
  omlish/dataclasses/api/classes/conversion.py,sha256=x1Ayo5W3t8lVh10KGH_ZBJ_kK7HqcdI2LdJA6mR_WXQ,810
216
- omlish/dataclasses/api/classes/decorator.py,sha256=4IiMWsCeXD7lubTZC_becVsi8zsIIH8fN2PbP-fFZE0,2990
217
- omlish/dataclasses/api/classes/make.py,sha256=O3iWvCMHW4XJXmHHDvNsh5rhkPh9VQ-iCPMUGPWETAM,2629
216
+ omlish/dataclasses/api/classes/decorator.py,sha256=q-m05j6VhJ9_00TmrXBvwmv0_TFPTD8OURi1KbKo9-4,3933
217
+ omlish/dataclasses/api/classes/make.py,sha256=Q_8ZVjhhFEUstIZA3Ht_vlGptYjTcJqX48qT57W7SZw,2820
218
218
  omlish/dataclasses/api/classes/metadata.py,sha256=2YafXunxqbqnHIdp5gsiGLyH7cWg9FR5wCwcxlLFd20,2685
219
- omlish/dataclasses/api/classes/params.py,sha256=qmHuGC4vB8o-7cnRXllVz_WNprx2fsyrNzPY2mYC5FM,1680
219
+ omlish/dataclasses/api/classes/params.py,sha256=GmLJotHT4BuXcK9lAwP00boR0_mfM0xITWBFKrk0brY,1994
220
220
  omlish/dataclasses/api/fields/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
221
221
  omlish/dataclasses/api/fields/building.py,sha256=YVAJZ2c318vK0YWz9VU8_MdjA5qNjqsI3N85K-bD0TI,3314
222
222
  omlish/dataclasses/api/fields/constructor.py,sha256=T2GeczTz9uy2EOTDlU4VJoiXp-I6jvlxnYXChvQqHxk,1533
@@ -237,7 +237,7 @@ omlish/dataclasses/concerns/order.py,sha256=f1JVDkeTWllO9Tu79xKkjHul-_rpsYZXHMTn
237
237
  omlish/dataclasses/concerns/override.py,sha256=eegJ4KRs-p3Oj5ipY1eySwXJ3vFyVXG5gWRQZcsmvUQ,2810
238
238
  omlish/dataclasses/concerns/params.py,sha256=ZrNGBUp87YkrOMW7bYn0GdYk9PuDHzxdwKn477lqUyE,404
239
239
  omlish/dataclasses/concerns/replace.py,sha256=Q11NjVMMHVh9MjJ6osaXNFG5HuGWQM6qDgWK7IN0IIc,1501
240
- omlish/dataclasses/concerns/repr.py,sha256=Ft8V0aqxNHz29fOAQsRoFTlLybbgGeT2QbSxXJa7Gyc,2855
240
+ omlish/dataclasses/concerns/repr.py,sha256=HHwCqZPGTMhRPsVgbqrZEh30DBV8LcVSXF2oSrqcjvM,3458
241
241
  omlish/dataclasses/concerns/slots.py,sha256=xg6346UT_oUlb0kYaWFbeJUKzZcpQx4nJkT86CXfI5c,5922
242
242
  omlish/dataclasses/generation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
243
243
  omlish/dataclasses/generation/base.py,sha256=adi68lJogtjx1SoxGJ5hqC-f-CMX2gWi8iALmucIwKo,686
@@ -253,8 +253,8 @@ omlish/dataclasses/generation/processor.py,sha256=_rt_GHdx_pi5seRMzIu6DvLEx4MYGs
253
253
  omlish/dataclasses/generation/registry.py,sha256=_Cfvs9QY6f8Pvf9cKUi-OTI-qaDem3z5jcWkSDNk3kQ,1006
254
254
  omlish/dataclasses/generation/utils.py,sha256=u6DWRvzxgqrxqyfAGzNOyDvnOJYdMTYyZ7l1oOOiXrI,2089
255
255
  omlish/dataclasses/metaclass/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
256
- omlish/dataclasses/metaclass/bases.py,sha256=OSvFRx1PZ1HoBzT0YpsXy-AwAdWnNrcQ5p-teTIr7nY,1196
257
- omlish/dataclasses/metaclass/confer.py,sha256=yj31r3Vi1bdEvBRBjQML5IBzqEtDpzH3xC3LGkUAkKI,1327
256
+ omlish/dataclasses/metaclass/bases.py,sha256=aKxhjk_dx87ssTkEs35y4kPGIhuas4LmM5nlzYzvqhg,1394
257
+ omlish/dataclasses/metaclass/confer.py,sha256=dErYZbTXBKgvGAi2eu3FocxTvd9lNSqv03haKWsNjcg,1395
258
258
  omlish/dataclasses/metaclass/meta.py,sha256=0MQG7Sl1y8QccGRgLOC0VoLDTMBG6VoyT-wZdthO1zI,2639
259
259
  omlish/dataclasses/metaclass/specs.py,sha256=djzkHK95h06Cgrx8rr3SGkv2gOvL-fPOhWOBWbbN8h4,789
260
260
  omlish/dataclasses/processing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -344,7 +344,7 @@ omlish/formats/json5/__init__.py,sha256=BsjPz5zJDji3GjQ8x8hWvcl1GYPV_ZIHnE3c2Sr8
344
344
  omlish/formats/json5/codec.py,sha256=ldnxCRo0JP1fkGLt0mMxJlLvNxqIF_1KUCcSp1HtI-M,452
345
345
  omlish/formats/json5/errors.py,sha256=AHkR9ySjAoQdUrizpqgL8fg0M5oe5mHZkml3KZHEvC4,38
346
346
  omlish/formats/json5/literals.py,sha256=rj4-9KFXfgdq5oK_eUkp57cgoMQ8T0gRaG9ga430he4,2429
347
- omlish/formats/json5/parsing.py,sha256=FrH6CgAYoqHGgJMPfbhNNuvwxi20i5rus9pGHU-BcW0,2346
347
+ omlish/formats/json5/parsing.py,sha256=qYLcPgkMyjsWeolc6nMg-u5_2PMvBy7jtEUIJZoNZhs,2342
348
348
  omlish/formats/json5/_antlr/Json5Lexer.py,sha256=8TKxlENDsl6CPfoLR06uQSvhDnzGcY7fKsIhFJ_g6N4,23237
349
349
  omlish/formats/json5/_antlr/Json5Listener.py,sha256=fSiOzSS0CMjxaCev3sxZqJlW-buqIyDLwgnuRv-Uh80,2095
350
350
  omlish/formats/json5/_antlr/Json5Parser.py,sha256=nbbwoCPvEVRcEh5_t092XLmsXIHnbzONvH0W0g_BYkQ,19677
@@ -619,13 +619,13 @@ omlish/reflect/ops.py,sha256=RJ6jzrM4ieFsXzWyNXWV43O_WgzEaUvlHSc5N2ezW2A,2044
619
619
  omlish/reflect/subst.py,sha256=g3q7NmNWsmc67mcchmCE3WFPCMDSBq-FXn4ah-DWL_U,3622
620
620
  omlish/reflect/types.py,sha256=Cn9FYGoiCNt0FS0YLiTTAR12WKcesWMapCrVYcb8IDo,9225
621
621
  omlish/secrets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
622
- omlish/secrets/all.py,sha256=SGB1KrlNrxlNpazEHYy95NTzteLi8ndoEgMhU7luBl8,420
622
+ omlish/secrets/all.py,sha256=kUTuS4pZVskJe1kFN6m1F1br09BNSjX7MUC2RZRndwc,437
623
623
  omlish/secrets/crypto.py,sha256=9D21lnvPhStwu8arD4ssT0ih0bDG-nlqIRdVgYL40xA,3708
624
624
  omlish/secrets/marshal.py,sha256=u90n1OfRfdpH1T2F0xK_pAPH1ENYL6acFt6XdVd3KvI,1986
625
625
  omlish/secrets/openssl.py,sha256=UT_dXJ4zA1s9e-UHoW_NLGHQO7iouUNPnJNkkpuw3JI,6213
626
626
  omlish/secrets/pwgen.py,sha256=5k7QMSysUfv9F65TDMdDlrhTIKy6QbMG3KT2HNVmnVg,1712
627
627
  omlish/secrets/pwhash.py,sha256=Jctv3QzcMvVPXJsWA3w3LDUlzmyUDGEWG9sLiJz1xaw,4107
628
- omlish/secrets/secrets.py,sha256=mRajnNFbrHPLSz21OEinE_k-FjirXARIxFLOq2JbPAo,7969
628
+ omlish/secrets/secrets.py,sha256=-U3VeyIswWcYh1zSuvjE2I7QTXyoH7UMzqNJTclnDCs,8029
629
629
  omlish/secrets/ssl.py,sha256=_72xTNP6a1Xw0Pweuow9WK5yveqJ7hmjhala9iMnrAk,152
630
630
  omlish/secrets/subprocesses.py,sha256=ZdShw4jrGDdyQW8mRMgl106-9qpCEq2J6w_x7ruz1wk,1217
631
631
  omlish/secrets/tempssl.py,sha256=X_cAQbeaz-YcH8SzQ0luYTktIGJv4KMpfTD3t9l9Gqk,1879
@@ -813,7 +813,7 @@ omlish/text/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
813
813
  omlish/text/asdl.py,sha256=AS3irh-sag5pqyH3beJif78PjCbOaFso1NeKq-HXuTs,16867
814
814
  omlish/text/decoding.py,sha256=sQWGckWzRslRHYKpj1SBeoo6AVqXm5HFlWFRARN1QpM,1286
815
815
  omlish/text/delimit.py,sha256=z9uIuWJdbp7M3ku2KQRHo-lzJYZUJCqZTLse1sIUI4Q,4932
816
- omlish/text/filecache.py,sha256=ls08QSqBlhVXvjDwJpUXiP-U9HLyCstGAxtBOuWJmVY,5414
816
+ omlish/text/filecache.py,sha256=U3sHtHzUYtPeXr8WrSw3eJ1m7zipJf_yu1jExcTcXgY,5411
817
817
  omlish/text/glyphsplit.py,sha256=HI8TWDUaF_tJG5RnIdIjtUH_lYnjYZ7KZBANSxOXGZc,3808
818
818
  omlish/text/indent.py,sha256=LOQgHskHMLVrRC6HLL9uIWay517dpvPEYQK0Igm-wm8,1341
819
819
  omlish/text/linecache.py,sha256=hRYlEhD63ZfA6_ZOTkQIcnON-3W56QMAhcG3vEJqj9M,1858
@@ -824,17 +824,18 @@ omlish/text/random.py,sha256=8feS5JE_tSjYlMl-lp0j93kCfzBae9AM2cXlRLebXMA,199
824
824
  omlish/text/templating.py,sha256=azhKpvkDR2uby8k3AJ8Y6GpdKVQUb7Xt_cGbDz6dkTM,2454
825
825
  omlish/text/go/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
826
826
  omlish/text/go/quoting.py,sha256=N9EYdnFdEX_A8fOviH-1w4jwV3XOQ7VU2WsoUNubYVY,9137
827
- omlish/typedvalues/__init__.py,sha256=c3IQmRneMmH6JRcafprqmBILWD89b-IyIll6MgahGCI,562
828
- omlish/typedvalues/accessor.py,sha256=0k21N-CkjGaY6zCwugsRfOC_CDkqk7wNz4oxO1_6EEA,2919
829
- omlish/typedvalues/collection.py,sha256=jsXSggmMMvGATcJgQkUXt5Guwq8aquw73_OIC-e6U0I,5300
827
+ omlish/typedvalues/__init__.py,sha256=nzpnoRW_wScMPit5Xz37ky3nKBdzzkgtnQA4SfVHN8E,684
828
+ omlish/typedvalues/accessor.py,sha256=5q-JbIUjhzmW6Ui55YepHc1FDAlV13Whkz_TVNvtQ9Q,3064
829
+ omlish/typedvalues/collection.py,sha256=a6Je_kmz2FlAV2dI92S7c_paXge0QExMynV-fD9oPrs,5823
830
+ omlish/typedvalues/consumer.py,sha256=peDQAgriSyBx_Hc8QHAhEgYy0oSS52qQ_7Tqdssl2AE,4375
830
831
  omlish/typedvalues/generic.py,sha256=byWG_gMXhNelckUwdmOoJE9FKkL71Q4BSi4ZLyy0XZ0,788
831
- omlish/typedvalues/holder.py,sha256=4SwRezsmuDDEO5gENGx8kTm30pblF5UktoEAu02i-Gk,1554
832
- omlish/typedvalues/marshal.py,sha256=Rr-4DZ90BoD5Z9gT18QhZH2yMA3-gPJBK8GUrGkp8VA,4245
833
- omlish/typedvalues/reflect.py,sha256=y_7IY8_4cLVRvD3ug-_-cDaO5RtzC1rLVFzkeAPALf8,683
834
- omlish/typedvalues/values.py,sha256=Q_5IiQM3Vka4wGVd-scaslb4-oCMjFcIOksIrKE-JIM,1229
835
- omlish-0.0.0.dev292.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
836
- omlish-0.0.0.dev292.dist-info/METADATA,sha256=kDZfh7WmEgxzVyOJP7bSmYSh1RzTqJOv4VdFbKI55fk,4316
837
- omlish-0.0.0.dev292.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
838
- omlish-0.0.0.dev292.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
839
- omlish-0.0.0.dev292.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
840
- omlish-0.0.0.dev292.dist-info/RECORD,,
832
+ omlish/typedvalues/holder.py,sha256=ZTnHiw-K38ciOBLEdwgrltr7Xp8jjEs_0Lp69DH-G-o,1128
833
+ omlish/typedvalues/marshal.py,sha256=hWHRLcrGav7lvXJDtb9bNI0ickl4SKPQ6F4BbTpqw3A,4219
834
+ omlish/typedvalues/reflect.py,sha256=Ih1YgU-srUjsvBn_P7C66f73_VCvcwqE3ffeBnZBgt4,674
835
+ omlish/typedvalues/values.py,sha256=CEL8xeeneJBe8CrV3NXyZcC6sZ0FR6Cgz2YtaCBug6A,1359
836
+ omlish-0.0.0.dev294.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
837
+ omlish-0.0.0.dev294.dist-info/METADATA,sha256=LOvDXgRmMOuG2yUn4QvyNJBuAmrFqRtSTlmKv_rv1Vk,4316
838
+ omlish-0.0.0.dev294.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
839
+ omlish-0.0.0.dev294.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
840
+ omlish-0.0.0.dev294.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
841
+ omlish-0.0.0.dev294.dist-info/RECORD,,