omlish 0.0.0.dev339__py3-none-any.whl → 0.0.0.dev341__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 +2 -2
- omlish/asyncs/bluelet/LICENSE +1 -1
- omlish/asyncs/bluelet/api.py +1 -1
- omlish/asyncs/bluelet/core.py +1 -1
- omlish/asyncs/bluelet/events.py +1 -1
- omlish/asyncs/bluelet/files.py +1 -1
- omlish/asyncs/bluelet/runner.py +1 -1
- omlish/asyncs/bluelet/sockets.py +1 -1
- omlish/check.py +197 -30
- omlish/collections/__init__.py +19 -0
- omlish/collections/multimaps.py +151 -0
- omlish/formats/json/__init__.py +13 -13
- omlish/formats/json/backends/__init__.py +2 -2
- omlish/formats/json/backends/default.py +56 -12
- omlish/formats/json/backends/orjson.py +6 -5
- omlish/formats/json/backends/std.py +4 -1
- omlish/formats/json/backends/ujson.py +6 -5
- omlish/formats/json/codecs.py +4 -4
- omlish/graphs/dags.py +112 -48
- omlish/graphs/domination.py +5 -1
- omlish/graphs/dot/items.py +3 -0
- omlish/graphs/dot/make.py +3 -0
- omlish/graphs/dot/rendering.py +3 -0
- omlish/graphs/dot/utils.py +3 -0
- omlish/graphs/trees.py +5 -4
- omlish/lang/classes/bindable.py +2 -0
- omlish/lite/check.py +6 -6
- omlish/math/__init__.py +15 -15
- omlish/math/fixed.py +25 -15
- omlish/os/forkhooks.py +4 -4
- omlish/typedvalues/__init__.py +4 -0
- omlish/typedvalues/collection.py +3 -0
- omlish/typedvalues/consumer.py +12 -0
- {omlish-0.0.0.dev339.dist-info → omlish-0.0.0.dev341.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev339.dist-info → omlish-0.0.0.dev341.dist-info}/RECORD +39 -39
- omlish/formats/json/json.py +0 -17
- {omlish-0.0.0.dev339.dist-info → omlish-0.0.0.dev341.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev339.dist-info → omlish-0.0.0.dev341.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev339.dist-info → omlish-0.0.0.dev341.dist-info}/licenses/LICENSE +0 -0
- {omlish-0.0.0.dev339.dist-info → omlish-0.0.0.dev341.dist-info}/top_level.txt +0 -0
omlish/formats/json/codecs.py
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
from ..codecs import make_object_lazy_loaded_codec
|
2
2
|
from ..codecs import make_str_object_codec
|
3
|
-
from .
|
4
|
-
from .
|
5
|
-
from .
|
6
|
-
from .
|
3
|
+
from .backends.default import dumps
|
4
|
+
from .backends.default import dumps_compact
|
5
|
+
from .backends.default import dumps_pretty
|
6
|
+
from .backends.default import loads
|
7
7
|
|
8
8
|
|
9
9
|
##
|
omlish/graphs/dags.py
CHANGED
@@ -12,100 +12,164 @@ from .. import check
|
|
12
12
|
from .. import lang
|
13
13
|
|
14
14
|
|
15
|
-
K = ta.TypeVar('K')
|
16
|
-
V = ta.TypeVar('V')
|
17
15
|
T = ta.TypeVar('T')
|
18
|
-
U = ta.TypeVar('U')
|
19
16
|
|
20
17
|
|
21
|
-
|
22
|
-
|
23
|
-
|
18
|
+
##
|
19
|
+
|
20
|
+
|
21
|
+
class LinkError(KeyError):
|
22
|
+
pass
|
23
|
+
|
24
|
+
|
25
|
+
def traverse_links(
|
26
|
+
links: ta.Mapping[T, ta.Iterable[T]],
|
27
|
+
roots: ta.Iterable[T],
|
28
|
+
*,
|
29
|
+
include_roots: bool = False,
|
30
|
+
strict: bool = False,
|
31
|
+
) -> set[T]:
|
32
|
+
"""Returns all keys deeply reachable from given roots. Handles cycles."""
|
33
|
+
|
34
|
+
roots = set(roots)
|
35
|
+
|
36
|
+
todo = set(roots)
|
24
37
|
seen: set[T] = set()
|
25
38
|
while todo:
|
26
39
|
key = todo.pop()
|
27
40
|
seen.add(key)
|
28
|
-
cur = data.get(key, [])
|
29
|
-
todo.update(set(cur) - seen)
|
30
|
-
return seen - keys
|
31
|
-
|
32
41
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
42
|
+
try:
|
43
|
+
cur = links[key]
|
44
|
+
except KeyError:
|
45
|
+
if strict:
|
46
|
+
raise LinkError(key) from None
|
47
|
+
else:
|
48
|
+
todo.update(set(cur) - seen)
|
49
|
+
|
50
|
+
if include_roots:
|
51
|
+
return seen
|
52
|
+
else:
|
53
|
+
return seen - roots
|
54
|
+
|
55
|
+
|
56
|
+
def invert_links(
|
57
|
+
links: ta.Mapping[T, ta.Iterable[T]],
|
58
|
+
*,
|
59
|
+
auto_add_roots: bool = False,
|
60
|
+
if_absent: ta.Literal['raise', 'ignore', 'add'] = 'add',
|
61
|
+
) -> dict[T, set[T]]:
|
62
|
+
check.in_(if_absent, ('raise', 'ignore', 'add'))
|
63
|
+
if if_absent != 'add':
|
64
|
+
check.arg(auto_add_roots, 'auto_add_roots must be True with given if_absent is not "add"')
|
65
|
+
|
66
|
+
ret: dict[T, set[T]]
|
67
|
+
if auto_add_roots:
|
68
|
+
ret = {src: set() for src in links}
|
69
|
+
else:
|
70
|
+
ret = {}
|
71
|
+
|
72
|
+
for src, dsts in links.items():
|
73
|
+
for dst in dsts:
|
37
74
|
try:
|
38
|
-
|
75
|
+
tgt = ret[dst]
|
39
76
|
except KeyError:
|
40
|
-
|
41
|
-
|
42
|
-
|
77
|
+
if if_absent == 'raise':
|
78
|
+
raise LinkError(dst) from None
|
79
|
+
elif if_absent == 'ignore':
|
80
|
+
continue
|
81
|
+
elif if_absent == 'add':
|
82
|
+
tgt = ret[dst] = set()
|
83
|
+
else:
|
84
|
+
raise RuntimeError from None
|
85
|
+
|
86
|
+
tgt.add(src)
|
43
87
|
|
88
|
+
return ret
|
44
89
|
|
45
|
-
|
46
|
-
|
47
|
-
for l, rs in src.items():
|
48
|
-
for r in rs:
|
49
|
-
dst[r].add(l)
|
50
|
-
return dst
|
90
|
+
|
91
|
+
##
|
51
92
|
|
52
93
|
|
53
94
|
class Dag(ta.Generic[T]):
|
54
|
-
|
95
|
+
"""Given 'input_its_by_outputs', or a map from nodes to that node's dependencies."""
|
96
|
+
|
97
|
+
def __init__(
|
98
|
+
self,
|
99
|
+
input_its_by_outputs: ta.Mapping[T, ta.Iterable[T]],
|
100
|
+
*,
|
101
|
+
auto_add_outputs: bool = True,
|
102
|
+
if_absent: ta.Literal['raise', 'ignore', 'add'] = 'add',
|
103
|
+
) -> None:
|
55
104
|
super().__init__()
|
56
105
|
|
57
106
|
self._input_sets_by_output = {u: set(d) for u, d in input_its_by_outputs.items()}
|
58
107
|
|
108
|
+
self._output_sets_by_input = invert_links(
|
109
|
+
self._input_sets_by_output,
|
110
|
+
auto_add_roots=auto_add_outputs,
|
111
|
+
if_absent=if_absent,
|
112
|
+
)
|
113
|
+
|
59
114
|
@property
|
60
115
|
def input_sets_by_output(self) -> ta.Mapping[T, ta.AbstractSet[T]]:
|
61
116
|
return self._input_sets_by_output
|
62
117
|
|
63
|
-
@
|
118
|
+
@property
|
64
119
|
def output_sets_by_input(self) -> ta.Mapping[T, ta.AbstractSet[T]]:
|
65
|
-
return
|
120
|
+
return self._output_sets_by_input
|
66
121
|
|
67
|
-
def subdag(
|
68
|
-
|
122
|
+
def subdag(
|
123
|
+
self,
|
124
|
+
roots: ta.Iterable[T],
|
125
|
+
*,
|
126
|
+
ignored: ta.Iterable[T] | None = None,
|
127
|
+
) -> 'Subdag[T]':
|
128
|
+
return Subdag(
|
129
|
+
self,
|
130
|
+
roots,
|
131
|
+
ignored=ignored,
|
132
|
+
)
|
69
133
|
|
70
134
|
|
71
|
-
class Subdag(ta.Generic[
|
135
|
+
class Subdag(ta.Generic[T]):
|
72
136
|
def __init__(
|
73
137
|
self,
|
74
|
-
dag:
|
75
|
-
|
138
|
+
dag: Dag[T],
|
139
|
+
roots: ta.Iterable[T],
|
76
140
|
*,
|
77
|
-
ignored: ta.Iterable[
|
141
|
+
ignored: ta.Iterable[T] | None = None,
|
78
142
|
) -> None:
|
79
143
|
super().__init__()
|
80
144
|
|
81
|
-
self._dag: Dag[
|
82
|
-
self.
|
83
|
-
self._ignored = set(ignored or []) - self.
|
145
|
+
self._dag: Dag[T] = check.isinstance(dag, Dag)
|
146
|
+
self._roots = set(roots)
|
147
|
+
self._ignored = set(ignored or []) - self._roots
|
84
148
|
|
85
149
|
@property
|
86
|
-
def dag(self) ->
|
150
|
+
def dag(self) -> Dag[T]:
|
87
151
|
return self._dag
|
88
152
|
|
89
153
|
@property
|
90
|
-
def
|
91
|
-
return self.
|
154
|
+
def roots(self) -> ta.AbstractSet[T]:
|
155
|
+
return self._roots
|
92
156
|
|
93
157
|
@property
|
94
|
-
def ignored(self) -> ta.AbstractSet[
|
158
|
+
def ignored(self) -> ta.AbstractSet[T]:
|
95
159
|
return self._ignored
|
96
160
|
|
97
161
|
@lang.cached_property
|
98
|
-
def inputs(self) -> ta.AbstractSet[
|
99
|
-
return traverse_links(self.
|
162
|
+
def inputs(self) -> ta.AbstractSet[T]:
|
163
|
+
return traverse_links(self._dag.input_sets_by_output, self._roots) - self._ignored
|
100
164
|
|
101
165
|
@lang.cached_property
|
102
|
-
def outputs(self) -> ta.AbstractSet[
|
103
|
-
return traverse_links(self.
|
166
|
+
def outputs(self) -> ta.AbstractSet[T]:
|
167
|
+
return traverse_links(self._dag.output_sets_by_input, self._roots) - self._ignored
|
104
168
|
|
105
169
|
@lang.cached_property
|
106
|
-
def output_inputs(self) -> ta.AbstractSet[
|
107
|
-
return traverse_links(self.
|
170
|
+
def output_inputs(self) -> ta.AbstractSet[T]:
|
171
|
+
return traverse_links(self._dag.input_sets_by_output, self.outputs) - self._ignored
|
108
172
|
|
109
173
|
@lang.cached_property
|
110
|
-
def all(self) -> ta.AbstractSet[
|
111
|
-
return self.
|
174
|
+
def all(self) -> ta.AbstractSet[T]:
|
175
|
+
return self.roots | self.inputs | self.outputs | self.output_inputs
|
omlish/graphs/domination.py
CHANGED
@@ -9,7 +9,11 @@ from .. import lang
|
|
9
9
|
V = ta.TypeVar('V')
|
10
10
|
MK = ta.TypeVar('MK')
|
11
11
|
MV = ta.TypeVar('MV')
|
12
|
-
|
12
|
+
|
13
|
+
SetMap: ta.TypeAlias = ta.Mapping[MK, ta.AbstractSet[MV]]
|
14
|
+
|
15
|
+
|
16
|
+
##
|
13
17
|
|
14
18
|
|
15
19
|
class DirectedGraph(ta.Generic[V], lang.Abstract):
|
omlish/graphs/dot/items.py
CHANGED
omlish/graphs/dot/make.py
CHANGED
omlish/graphs/dot/rendering.py
CHANGED
omlish/graphs/dot/utils.py
CHANGED
omlish/graphs/trees.py
CHANGED
@@ -10,13 +10,14 @@ from .. import cached
|
|
10
10
|
from .. import check
|
11
11
|
from .. import collections as col
|
12
12
|
from .. import lang
|
13
|
-
from ..algorithm import
|
13
|
+
from ..algorithm.toposort import mut_toposort
|
14
14
|
|
15
15
|
|
16
16
|
T = ta.TypeVar('T')
|
17
17
|
NodeT = ta.TypeVar('NodeT')
|
18
|
-
|
19
|
-
|
18
|
+
|
19
|
+
NodeWalker: ta.TypeAlias = ta.Callable[[NodeT], ta.Iterable[NodeT]]
|
20
|
+
NodeGenerator: ta.TypeAlias = ta.Generator[NodeT, None, None]
|
20
21
|
|
21
22
|
|
22
23
|
##
|
@@ -200,7 +201,7 @@ class BasicTreeAnalysis(ta.Generic[NodeT]):
|
|
200
201
|
else:
|
201
202
|
e, d = lang.identity, lang.identity
|
202
203
|
tsd = {e(n): {e(p)} for n, p in parents_by_node.items()}
|
203
|
-
ts = list(
|
204
|
+
ts = list(mut_toposort(tsd))
|
204
205
|
root = d(check.single(ts[0]))
|
205
206
|
|
206
207
|
return cls(
|
omlish/lang/classes/bindable.py
CHANGED
@@ -27,6 +27,8 @@ class BindableClass(ta.Generic[T]):
|
|
27
27
|
setattr(self, '_bound', _bound)
|
28
28
|
|
29
29
|
def __class_getitem__(cls, *args, **kwargs):
|
30
|
+
# FIXME: this could handle __mro_items__ to be subclassable, but it's not currently really intended to be
|
31
|
+
# subclassed
|
30
32
|
if cls is BindableClass:
|
31
33
|
return super().__class_getitem__(*args, **kwargs) # type: ignore[misc]
|
32
34
|
|
omlish/lite/check.py
CHANGED
@@ -177,7 +177,7 @@ class Checks:
|
|
177
177
|
|
178
178
|
return inner
|
179
179
|
|
180
|
-
def cast(self, v: ta.Any, cls: ta.Type[T], msg: CheckMessage = None) -> T:
|
180
|
+
def cast(self, v: ta.Any, cls: ta.Type[T], msg: CheckMessage = None) -> T:
|
181
181
|
if not isinstance(v, cls):
|
182
182
|
self._raise(
|
183
183
|
TypeError,
|
@@ -226,7 +226,7 @@ class Checks:
|
|
226
226
|
|
227
227
|
return v
|
228
228
|
|
229
|
-
def not_issubclass(self, v: ta.Type[T], spec: ta.Any, msg: CheckMessage = None) -> ta.Type[T]:
|
229
|
+
def not_issubclass(self, v: ta.Type[T], spec: ta.Any, msg: CheckMessage = None) -> ta.Type[T]:
|
230
230
|
if issubclass(v, spec):
|
231
231
|
self._raise(
|
232
232
|
TypeError,
|
@@ -317,21 +317,21 @@ class Checks:
|
|
317
317
|
|
318
318
|
return it
|
319
319
|
|
320
|
-
def single(self, obj: ta.Iterable[T],
|
320
|
+
def single(self, obj: ta.Iterable[T], msg: CheckMessage = None) -> T:
|
321
321
|
try:
|
322
322
|
[value] = obj
|
323
323
|
except ValueError:
|
324
324
|
self._raise(
|
325
325
|
ValueError,
|
326
326
|
'Must be single',
|
327
|
-
|
327
|
+
msg,
|
328
328
|
Checks._ArgsKwargs(obj),
|
329
329
|
render_fmt='%s',
|
330
330
|
)
|
331
331
|
|
332
332
|
return value
|
333
333
|
|
334
|
-
def opt_single(self, obj: ta.Iterable[T],
|
334
|
+
def opt_single(self, obj: ta.Iterable[T], msg: CheckMessage = None) -> ta.Optional[T]:
|
335
335
|
it = iter(obj)
|
336
336
|
try:
|
337
337
|
value = next(it)
|
@@ -346,7 +346,7 @@ class Checks:
|
|
346
346
|
self._raise(
|
347
347
|
ValueError,
|
348
348
|
'Must be empty or single',
|
349
|
-
|
349
|
+
msg,
|
350
350
|
Checks._ArgsKwargs(obj),
|
351
351
|
render_fmt='%s',
|
352
352
|
)
|
omlish/math/__init__.py
CHANGED
@@ -35,11 +35,11 @@ from .fixed import ( # noqa
|
|
35
35
|
CheckedInt64,
|
36
36
|
CheckedInt128,
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
38
|
+
CheckedUint8,
|
39
|
+
CheckedUint16,
|
40
|
+
CheckedUint32,
|
41
|
+
CheckedUint64,
|
42
|
+
CheckedUint128,
|
43
43
|
|
44
44
|
ClampedInt8,
|
45
45
|
ClampedInt16,
|
@@ -47,11 +47,11 @@ from .fixed import ( # noqa
|
|
47
47
|
ClampedInt64,
|
48
48
|
ClampedInt128,
|
49
49
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
50
|
+
ClampedUint8,
|
51
|
+
ClampedUint16,
|
52
|
+
ClampedUint32,
|
53
|
+
ClampedUint64,
|
54
|
+
ClampedUint128,
|
55
55
|
|
56
56
|
WrappedInt8,
|
57
57
|
WrappedInt16,
|
@@ -59,11 +59,11 @@ from .fixed import ( # noqa
|
|
59
59
|
WrappedInt64,
|
60
60
|
WrappedInt128,
|
61
61
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
62
|
+
WrappedUint8,
|
63
|
+
WrappedUint16,
|
64
|
+
WrappedUint32,
|
65
|
+
WrappedUint64,
|
66
|
+
WrappedUint128,
|
67
67
|
)
|
68
68
|
|
69
69
|
from .floats import ( # noqa
|
omlish/math/fixed.py
CHANGED
@@ -183,6 +183,16 @@ class FixedWidthInt(int, lang.Abstract):
|
|
183
183
|
locals()[_proxy_name] = _gen_tuple_proxy_method(_proxy_name)
|
184
184
|
del _proxy_name
|
185
185
|
|
186
|
+
#
|
187
|
+
|
188
|
+
def __invert__(self) -> ta.Self:
|
189
|
+
if not self.SIGNED:
|
190
|
+
return self.__class__(~int(self) & self.MASK)
|
191
|
+
else:
|
192
|
+
return self.__class__(super().__invert__())
|
193
|
+
|
194
|
+
#
|
195
|
+
|
186
196
|
def __repr__(self) -> str:
|
187
197
|
return f'{self.__class__.__name__}({int(self)})'
|
188
198
|
|
@@ -278,23 +288,23 @@ class CheckedInt128(CheckedInt, SignedInt, AnyInt128):
|
|
278
288
|
#
|
279
289
|
|
280
290
|
|
281
|
-
class
|
291
|
+
class CheckedUint8(CheckedInt, UnsignedInt, AnyInt8):
|
282
292
|
pass
|
283
293
|
|
284
294
|
|
285
|
-
class
|
295
|
+
class CheckedUint16(CheckedInt, UnsignedInt, AnyInt16):
|
286
296
|
pass
|
287
297
|
|
288
298
|
|
289
|
-
class
|
299
|
+
class CheckedUint32(CheckedInt, UnsignedInt, AnyInt32):
|
290
300
|
pass
|
291
301
|
|
292
302
|
|
293
|
-
class
|
303
|
+
class CheckedUint64(CheckedInt, UnsignedInt, AnyInt64):
|
294
304
|
pass
|
295
305
|
|
296
306
|
|
297
|
-
class
|
307
|
+
class CheckedUint128(CheckedInt, UnsignedInt, AnyInt128):
|
298
308
|
pass
|
299
309
|
|
300
310
|
|
@@ -324,23 +334,23 @@ class ClampedInt128(ClampedInt, SignedInt, AnyInt128):
|
|
324
334
|
#
|
325
335
|
|
326
336
|
|
327
|
-
class
|
337
|
+
class ClampedUint8(ClampedInt, UnsignedInt, AnyInt8):
|
328
338
|
pass
|
329
339
|
|
330
340
|
|
331
|
-
class
|
341
|
+
class ClampedUint16(ClampedInt, UnsignedInt, AnyInt16):
|
332
342
|
pass
|
333
343
|
|
334
344
|
|
335
|
-
class
|
345
|
+
class ClampedUint32(ClampedInt, UnsignedInt, AnyInt32):
|
336
346
|
pass
|
337
347
|
|
338
348
|
|
339
|
-
class
|
349
|
+
class ClampedUint64(ClampedInt, UnsignedInt, AnyInt64):
|
340
350
|
pass
|
341
351
|
|
342
352
|
|
343
|
-
class
|
353
|
+
class ClampedUint128(ClampedInt, UnsignedInt, AnyInt128):
|
344
354
|
pass
|
345
355
|
|
346
356
|
|
@@ -370,21 +380,21 @@ class WrappedInt128(WrappedInt, SignedInt, AnyInt128):
|
|
370
380
|
#
|
371
381
|
|
372
382
|
|
373
|
-
class
|
383
|
+
class WrappedUint8(WrappedInt, UnsignedInt, AnyInt8):
|
374
384
|
pass
|
375
385
|
|
376
386
|
|
377
|
-
class
|
387
|
+
class WrappedUint16(WrappedInt, UnsignedInt, AnyInt16):
|
378
388
|
pass
|
379
389
|
|
380
390
|
|
381
|
-
class
|
391
|
+
class WrappedUint32(WrappedInt, UnsignedInt, AnyInt32):
|
382
392
|
pass
|
383
393
|
|
384
394
|
|
385
|
-
class
|
395
|
+
class WrappedUint64(WrappedInt, UnsignedInt, AnyInt64):
|
386
396
|
pass
|
387
397
|
|
388
398
|
|
389
|
-
class
|
399
|
+
class WrappedUint128(WrappedInt, UnsignedInt, AnyInt128):
|
390
400
|
pass
|
omlish/os/forkhooks.py
CHANGED
@@ -36,9 +36,9 @@ class _ForkHookManager:
|
|
36
36
|
|
37
37
|
#
|
38
38
|
|
39
|
-
_hooks_by_key: ta.ClassVar[ta.Dict[
|
39
|
+
_hooks_by_key: ta.ClassVar[ta.Dict[ta.Any, Hook]] = {}
|
40
40
|
|
41
|
-
_hook_keys: ta.ClassVar[ta.FrozenSet[
|
41
|
+
_hook_keys: ta.ClassVar[ta.FrozenSet[ta.Any]] = frozenset()
|
42
42
|
_priority_ordered_hooks: ta.ClassVar[ta.List[Hook]] = []
|
43
43
|
|
44
44
|
@classmethod
|
@@ -191,7 +191,7 @@ class ForkHook(abc.ABC): # noqa
|
|
191
191
|
##
|
192
192
|
|
193
193
|
|
194
|
-
class
|
194
|
+
class ForkDepthTracker(ForkHook):
|
195
195
|
_hook_priority = -1000
|
196
196
|
|
197
197
|
_fork_depth: ta.ClassVar[int] = 0
|
@@ -208,7 +208,7 @@ class _ForkDepthTracker(ForkHook):
|
|
208
208
|
|
209
209
|
|
210
210
|
def get_fork_depth() -> int:
|
211
|
-
return
|
211
|
+
return ForkDepthTracker.get_fork_depth()
|
212
212
|
|
213
213
|
|
214
214
|
##
|
omlish/typedvalues/__init__.py
CHANGED
@@ -6,12 +6,16 @@ from .collection import ( # noqa
|
|
6
6
|
DuplicateUniqueTypedValueError,
|
7
7
|
|
8
8
|
TypedValues,
|
9
|
+
|
10
|
+
collect,
|
9
11
|
)
|
10
12
|
|
11
13
|
from .consumer import ( # noqa
|
12
14
|
UnconsumedTypedValuesError,
|
13
15
|
|
14
16
|
TypedValuesConsumer,
|
17
|
+
|
18
|
+
consume,
|
15
19
|
)
|
16
20
|
|
17
21
|
from .generic import ( # noqa
|
omlish/typedvalues/collection.py
CHANGED
omlish/typedvalues/consumer.py
CHANGED
@@ -173,3 +173,15 @@ class TypedValuesConsumer(ta.Generic[TypedValueT]):
|
|
173
173
|
continue
|
174
174
|
dct[k] = v.v # type: ignore[attr-defined]
|
175
175
|
return dct
|
176
|
+
|
177
|
+
|
178
|
+
def consume(
|
179
|
+
*tvs: TypedValueT,
|
180
|
+
override: bool = False,
|
181
|
+
check_type: type | tuple[type, ...] | None = None,
|
182
|
+
) -> TypedValuesConsumer[TypedValueT]:
|
183
|
+
return tvc.TypedValues(
|
184
|
+
*tvs,
|
185
|
+
override=override,
|
186
|
+
check_type=check_type,
|
187
|
+
).consume()
|