omlish 0.0.0.dev337__py3-none-any.whl → 0.0.0.dev339__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/lang/__init__.py +9 -0
- omlish/lang/classes/bindable.py +41 -0
- omlish/lang/classes/protocols.py +26 -0
- omlish/marshal/composite/special.py +33 -0
- omlish/marshal/standard.py +4 -0
- omlish/reflect/__init__.py +2 -0
- omlish/reflect/ops.py +14 -8
- omlish/reflect/types.py +80 -10
- omlish/testing/pytest/plugins/switches/__init__.py +1 -0
- omlish/testing/pytest/plugins/{switches.py → switches/plugin.py} +9 -79
- omlish/testing/pytest/plugins/switches/switches.py +89 -0
- omlish/testing/pytest/skip.py +7 -8
- omlish/typedvalues/__init__.py +4 -0
- omlish/typedvalues/accessor.py +5 -1
- omlish/typedvalues/collection.py +1 -0
- omlish/typedvalues/of_.py +51 -0
- {omlish-0.0.0.dev337.dist-info → omlish-0.0.0.dev339.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev337.dist-info → omlish-0.0.0.dev339.dist-info}/RECORD +23 -17
- {omlish-0.0.0.dev337.dist-info → omlish-0.0.0.dev339.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev337.dist-info → omlish-0.0.0.dev339.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev337.dist-info → omlish-0.0.0.dev339.dist-info}/licenses/LICENSE +0 -0
- {omlish-0.0.0.dev337.dist-info → omlish-0.0.0.dev339.dist-info}/top_level.txt +0 -0
omlish/__about__.py
CHANGED
omlish/lang/__init__.py
CHANGED
@@ -61,12 +61,21 @@ from .classes.abstract import ( # noqa
|
|
61
61
|
unabstract_class,
|
62
62
|
)
|
63
63
|
|
64
|
+
from .classes.bindable import ( # noqa
|
65
|
+
BindableClass,
|
66
|
+
)
|
67
|
+
|
64
68
|
from .classes.namespaces import ( # noqa
|
65
69
|
GenericNamespaceMeta,
|
66
70
|
Namespace,
|
67
71
|
NamespaceMeta,
|
68
72
|
)
|
69
73
|
|
74
|
+
from .classes.protocols import ( # noqa
|
75
|
+
ProtocolForbiddenAsBaseClass,
|
76
|
+
ProtocolForbiddenAsBaseClassTypeError,
|
77
|
+
)
|
78
|
+
|
70
79
|
from .classes.restrict import ( # noqa
|
71
80
|
AnySensitive,
|
72
81
|
Final,
|
@@ -0,0 +1,41 @@
|
|
1
|
+
import typing as ta
|
2
|
+
|
3
|
+
|
4
|
+
T = ta.TypeVar('T')
|
5
|
+
|
6
|
+
|
7
|
+
##
|
8
|
+
|
9
|
+
|
10
|
+
class _ClassOrInstanceMethod:
|
11
|
+
def __init__(self, func):
|
12
|
+
super().__init__()
|
13
|
+
|
14
|
+
self.__func__ = func
|
15
|
+
|
16
|
+
def __get__(self, instance, owner=None):
|
17
|
+
return self.__func__.__get__(instance if instance is not None else owner)
|
18
|
+
|
19
|
+
|
20
|
+
class BindableClass(ta.Generic[T]):
|
21
|
+
# FIXME: apparently can't have TypeVars in ClassVars, but could stick in a @classmethod (which gets transformed)...
|
22
|
+
_bound: ta.ClassVar[type[T] | None] = None # type: ignore[misc]
|
23
|
+
|
24
|
+
def __init__(self, *, _bound):
|
25
|
+
super().__init__()
|
26
|
+
|
27
|
+
setattr(self, '_bound', _bound)
|
28
|
+
|
29
|
+
def __class_getitem__(cls, *args, **kwargs):
|
30
|
+
if cls is BindableClass:
|
31
|
+
return super().__class_getitem__(*args, **kwargs) # type: ignore[misc]
|
32
|
+
|
33
|
+
[bind_cls] = args
|
34
|
+
return cls(_bound=bind_cls)
|
35
|
+
|
36
|
+
def __init_subclass__(cls, **kwargs):
|
37
|
+
super().__init_subclass__(**kwargs)
|
38
|
+
|
39
|
+
for k, v in cls.__dict__.items():
|
40
|
+
if isinstance(v, classmethod):
|
41
|
+
setattr(cls, k, _ClassOrInstanceMethod(v.__func__))
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import typing as ta
|
2
|
+
|
3
|
+
|
4
|
+
##
|
5
|
+
|
6
|
+
|
7
|
+
class ProtocolForbiddenAsBaseClass(ta.Protocol):
|
8
|
+
pass
|
9
|
+
|
10
|
+
|
11
|
+
class ProtocolForbiddenAsBaseClassTypeError(TypeError):
|
12
|
+
pass
|
13
|
+
|
14
|
+
|
15
|
+
def _ProtocolForbiddenAsBaseClass__init_subclass__(cls: ta.Any, **kwargs: ta.Any) -> None: # noqa
|
16
|
+
if ta.Protocol not in cls.__mro__:
|
17
|
+
raise TypeError(f'Class {cls} must be a Protocol')
|
18
|
+
|
19
|
+
super(ProtocolForbiddenAsBaseClass, cls).__init_subclass__(**kwargs) # noqa
|
20
|
+
|
21
|
+
# TODO: ta.Protocol not in cls.__bases__ ?
|
22
|
+
if not cls.__dict__['_is_protocol']:
|
23
|
+
raise ProtocolForbiddenAsBaseClassTypeError(cls)
|
24
|
+
|
25
|
+
|
26
|
+
setattr(ProtocolForbiddenAsBaseClass, '__init_subclass__', classmethod(_ProtocolForbiddenAsBaseClass__init_subclass__))
|
@@ -0,0 +1,33 @@
|
|
1
|
+
import collections.abc
|
2
|
+
|
3
|
+
from ... import check
|
4
|
+
from ... import lang
|
5
|
+
from ... import reflect as rfl
|
6
|
+
from ...funcs import match as mfs
|
7
|
+
from ..base import MarshalContext
|
8
|
+
from ..base import Marshaler
|
9
|
+
from ..base import MarshalerFactoryMatchClass
|
10
|
+
from ..base import UnmarshalContext
|
11
|
+
from ..base import Unmarshaler
|
12
|
+
from ..base import UnmarshalerFactoryMatchClass
|
13
|
+
from .iterables import DEFAULT_ITERABLE_CONCRETE_TYPES
|
14
|
+
from .iterables import IterableMarshaler
|
15
|
+
from .iterables import IterableUnmarshaler
|
16
|
+
|
17
|
+
|
18
|
+
##
|
19
|
+
|
20
|
+
|
21
|
+
class SequenceNotStrMarshalerFactory(MarshalerFactoryMatchClass):
|
22
|
+
@mfs.simple(lambda _, ctx, rty: isinstance(rty, rfl.Protocol) and rty.cls is lang.SequenceNotStr)
|
23
|
+
def _build_generic(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler:
|
24
|
+
gty = check.isinstance(rty, rfl.Protocol)
|
25
|
+
return IterableMarshaler(ctx.make(check.single(gty.args)))
|
26
|
+
|
27
|
+
|
28
|
+
class SequenceNotStrUnmarshalerFactory(UnmarshalerFactoryMatchClass):
|
29
|
+
@mfs.simple(lambda _, ctx, rty: isinstance(rty, rfl.Protocol) and rty.cls is lang.SequenceNotStr)
|
30
|
+
def _build_generic(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler:
|
31
|
+
gty = check.isinstance(rty, rfl.Protocol)
|
32
|
+
cty = DEFAULT_ITERABLE_CONCRETE_TYPES[collections.abc.Sequence] # type: ignore[type-abstract]
|
33
|
+
return IterableUnmarshaler(cty, ctx.make(check.single(gty.args)))
|
omlish/marshal/standard.py
CHANGED
@@ -18,6 +18,8 @@ from .composite.newtypes import NewtypeMarshalerFactory
|
|
18
18
|
from .composite.newtypes import NewtypeUnmarshalerFactory
|
19
19
|
from .composite.optionals import OptionalMarshalerFactory
|
20
20
|
from .composite.optionals import OptionalUnmarshalerFactory
|
21
|
+
from .composite.special import SequenceNotStrMarshalerFactory
|
22
|
+
from .composite.special import SequenceNotStrUnmarshalerFactory
|
21
23
|
from .objects.dataclasses import DataclassMarshalerFactory
|
22
24
|
from .objects.dataclasses import DataclassUnmarshalerFactory
|
23
25
|
from .objects.namedtuples import NamedtupleMarshalerFactory
|
@@ -58,6 +60,7 @@ STANDARD_MARSHALER_FACTORIES: list[MarshalerFactory] = [
|
|
58
60
|
DATETIME_MARSHALER_FACTORY,
|
59
61
|
MaybeMarshalerFactory(),
|
60
62
|
MappingMarshalerFactory(),
|
63
|
+
SequenceNotStrMarshalerFactory(),
|
61
64
|
IterableMarshalerFactory(),
|
62
65
|
ANY_MARSHALER_FACTORY,
|
63
66
|
]
|
@@ -91,6 +94,7 @@ STANDARD_UNMARSHALER_FACTORIES: list[UnmarshalerFactory] = [
|
|
91
94
|
DATETIME_UNMARSHALER_FACTORY,
|
92
95
|
MaybeUnmarshalerFactory(),
|
93
96
|
MappingUnmarshalerFactory(),
|
97
|
+
SequenceNotStrUnmarshalerFactory(),
|
94
98
|
IterableUnmarshalerFactory(),
|
95
99
|
ANY_UNMARSHALER_FACTORY,
|
96
100
|
]
|
omlish/reflect/__init__.py
CHANGED
omlish/reflect/ops.py
CHANGED
@@ -1,9 +1,12 @@
|
|
1
|
+
import dataclasses as dc
|
1
2
|
import typing as ta
|
2
3
|
|
3
4
|
from .types import Annotated
|
4
5
|
from .types import Any
|
5
6
|
from .types import Generic
|
7
|
+
from .types import GenericLike
|
6
8
|
from .types import NewType
|
9
|
+
from .types import Protocol
|
7
10
|
from .types import Type
|
8
11
|
from .types import Union
|
9
12
|
from .types import get_type_var_bound
|
@@ -15,13 +18,13 @@ def strip_objs(ty: Type) -> Type:
|
|
15
18
|
return ty
|
16
19
|
|
17
20
|
if isinstance(ty, Union):
|
18
|
-
return
|
21
|
+
return dc.replace(ty, args=frozenset(map(strip_objs, ty.args)))
|
19
22
|
|
20
|
-
if isinstance(ty,
|
21
|
-
return
|
23
|
+
if isinstance(ty, GenericLike):
|
24
|
+
return dc.replace(ty, args=tuple(map(strip_objs, ty.args)), obj=None)
|
22
25
|
|
23
26
|
if isinstance(ty, Annotated):
|
24
|
-
return
|
27
|
+
return dc.replace(ty, ty=strip_objs(ty.ty), obj=None)
|
25
28
|
|
26
29
|
raise TypeError(ty)
|
27
30
|
|
@@ -31,10 +34,10 @@ def strip_annotations(ty: Type) -> Type:
|
|
31
34
|
return ty
|
32
35
|
|
33
36
|
if isinstance(ty, Union):
|
34
|
-
return
|
37
|
+
return dc.replace(ty, args=frozenset(map(strip_annotations, ty.args)))
|
35
38
|
|
36
|
-
if isinstance(ty,
|
37
|
-
return
|
39
|
+
if isinstance(ty, GenericLike):
|
40
|
+
return dc.replace(ty, args=tuple(map(strip_annotations, ty.args)))
|
38
41
|
|
39
42
|
if isinstance(ty, Annotated):
|
40
43
|
return strip_annotations(ty.ty)
|
@@ -74,7 +77,7 @@ def get_concrete_type(
|
|
74
77
|
|
75
78
|
return None
|
76
79
|
|
77
|
-
if isinstance(cur, (Union, Any)):
|
80
|
+
if isinstance(cur, (Union, Any, Protocol)):
|
78
81
|
return None
|
79
82
|
|
80
83
|
raise TypeError(cur)
|
@@ -89,6 +92,9 @@ def to_annotation(ty: Type) -> ta.Any:
|
|
89
92
|
if isinstance(ty, Union):
|
90
93
|
return ta.Union[*tuple(to_annotation(e) for e in ty.args)]
|
91
94
|
|
95
|
+
if isinstance(ty, Protocol):
|
96
|
+
return ta.Protocol[*ty.params]
|
97
|
+
|
92
98
|
if isinstance(ty, (type, ta.TypeVar, NewType)):
|
93
99
|
return ty
|
94
100
|
|
omlish/reflect/types.py
CHANGED
@@ -3,6 +3,7 @@ TODO:
|
|
3
3
|
- visitor / transformer
|
4
4
|
- uniform collection isinstance - items() for mappings, iter() for other
|
5
5
|
- also check instance type in isinstance not just items lol
|
6
|
+
TODO:
|
6
7
|
- ta.Generic in mro causing trouble - omit? no longer 1:1
|
7
8
|
- cache this shit, esp generic_mro shit
|
8
9
|
- cache __hash__ in Generic/Union
|
@@ -22,6 +23,7 @@ _AnnotatedAlias = ta._AnnotatedAlias # type: ignore # noqa
|
|
22
23
|
_CallableGenericAlias = ta._CallableGenericAlias # type: ignore # noqa
|
23
24
|
_GenericAlias = ta._GenericAlias # type: ignore # noqa
|
24
25
|
_LiteralGenericAlias = ta._LiteralGenericAlias # type: ignore # noqa
|
26
|
+
_ProtocolMeta = ta._ProtocolMeta # noqa
|
25
27
|
_SpecialGenericAlias = ta._SpecialGenericAlias # type: ignore # noqa
|
26
28
|
_UnionGenericAlias = ta._UnionGenericAlias # type: ignore # noqa
|
27
29
|
|
@@ -29,6 +31,16 @@ _UnionGenericAlias = ta._UnionGenericAlias # type: ignore # noqa
|
|
29
31
|
##
|
30
32
|
|
31
33
|
|
34
|
+
_Protocol = getattr(ta, 'Protocol')
|
35
|
+
_Generic = getattr(ta, 'Generic')
|
36
|
+
|
37
|
+
if not isinstance(_Protocol, type) or not issubclass(_Protocol, _Generic):
|
38
|
+
raise TypeError(f'typing.Protocol is not a proper typing.Generic subtype')
|
39
|
+
|
40
|
+
|
41
|
+
##
|
42
|
+
|
43
|
+
|
32
44
|
@dc.dataclass(frozen=True)
|
33
45
|
class _Special:
|
34
46
|
name: str
|
@@ -95,6 +107,10 @@ def get_params(obj: ta.Any) -> tuple[ta.TypeVar, ...]:
|
|
95
107
|
raise TypeError(obj)
|
96
108
|
|
97
109
|
|
110
|
+
def _is_immediate_protocol(obj: ta.Any) -> bool:
|
111
|
+
return isinstance(obj, _ProtocolMeta) and obj.__dict__['_is_protocol']
|
112
|
+
|
113
|
+
|
98
114
|
def is_union_type(cls: ta.Any) -> bool:
|
99
115
|
if hasattr(ta, 'UnionType'):
|
100
116
|
return ta.get_origin(cls) in {ta.Union, getattr(ta, 'UnionType')}
|
@@ -163,22 +179,30 @@ class Union(TypeInfo):
|
|
163
179
|
#
|
164
180
|
|
165
181
|
|
182
|
+
GenericLikeCls = ta.TypeVar('GenericLikeCls')
|
183
|
+
|
184
|
+
|
166
185
|
@dc.dataclass(frozen=True)
|
167
|
-
class
|
168
|
-
cls:
|
169
|
-
args: tuple[Type, ...] # map[int, V] = (int, V) | map[T, T] = (T, T)
|
186
|
+
class GenericLike(TypeInfo, abc.ABC, ta.Generic[GenericLikeCls]):
|
187
|
+
cls: GenericLikeCls
|
170
188
|
|
171
|
-
|
172
|
-
#
|
189
|
+
# args and params are the same length - params maps to the generic origin's params:
|
190
|
+
# args : map[int, V] = (int, V) | map[T, T] = (T, T)
|
191
|
+
# params : map[int, V] = (_0, _1) | map[T, T] = (_0, _1)
|
192
|
+
args: tuple[Type, ...]
|
193
|
+
params: tuple[ta.TypeVar, ...] = dc.field(compare=False, repr=False)
|
173
194
|
|
174
195
|
obj: ta.Any = dc.field(compare=False, repr=False)
|
175
196
|
|
176
|
-
|
177
|
-
|
178
|
-
|
197
|
+
def __post_init__(self) -> None:
|
198
|
+
if not isinstance(self.cls, type):
|
199
|
+
raise ReflectTypeError(f'GenericLike {self.cls=} must be a type')
|
200
|
+
if len(self.args) != len(self.params):
|
201
|
+
raise ReflectTypeError(f'GenericLike {self.args=} must be same length as {self.params=}')
|
179
202
|
|
180
|
-
def full_eq(self, other: '
|
203
|
+
def full_eq(self, other: 'GenericLike') -> bool:
|
181
204
|
return (
|
205
|
+
type(self) is type(other) and
|
182
206
|
self.cls == other.cls and
|
183
207
|
self.args == other.args and
|
184
208
|
self.params == other.params and
|
@@ -186,6 +210,18 @@ class Generic(TypeInfo):
|
|
186
210
|
)
|
187
211
|
|
188
212
|
|
213
|
+
@dc.dataclass(frozen=True)
|
214
|
+
class Generic(GenericLike[type]):
|
215
|
+
pass
|
216
|
+
|
217
|
+
|
218
|
+
@dc.dataclass(frozen=True)
|
219
|
+
class Protocol(GenericLike[ta.Any]):
|
220
|
+
# cls will still be a type - it will be the topmost _is_protocol=True class.
|
221
|
+
# it may however be ta.Protocol, which *is* a type, but not according to mypy.
|
222
|
+
pass
|
223
|
+
|
224
|
+
|
189
225
|
#
|
190
226
|
|
191
227
|
|
@@ -311,9 +347,13 @@ class Reflector:
|
|
311
347
|
return None
|
312
348
|
|
313
349
|
origin = ta.get_origin(obj)
|
350
|
+
|
314
351
|
args = ta.get_args(obj)
|
315
352
|
|
316
|
-
if
|
353
|
+
if origin is ta.Protocol:
|
354
|
+
params = get_params(obj)
|
355
|
+
|
356
|
+
elif oty is _CallableGenericAlias:
|
317
357
|
p, r = args
|
318
358
|
if p is Ellipsis or isinstance(p, ta.ParamSpec):
|
319
359
|
raise ReflectTypeError(f'Callable argument not yet supported for {obj=}')
|
@@ -332,6 +372,27 @@ class Reflector:
|
|
332
372
|
if len(args) != len(params):
|
333
373
|
raise ReflectTypeError(f'Mismatched {args=} and {params=} for {obj=}')
|
334
374
|
|
375
|
+
if not isinstance(origin, type):
|
376
|
+
raise ReflectTypeError(f'Generic origin {origin!r} is not a type')
|
377
|
+
|
378
|
+
if origin is ta.Protocol:
|
379
|
+
if args != params:
|
380
|
+
raise ReflectTypeError(f'Protocol argument not yet supported for {args=}, {params=}')
|
381
|
+
return Protocol(
|
382
|
+
ta.Protocol,
|
383
|
+
args,
|
384
|
+
params,
|
385
|
+
obj,
|
386
|
+
)
|
387
|
+
|
388
|
+
if _is_immediate_protocol(origin):
|
389
|
+
return Protocol(
|
390
|
+
origin,
|
391
|
+
args,
|
392
|
+
params,
|
393
|
+
obj,
|
394
|
+
)
|
395
|
+
|
335
396
|
return Generic(
|
336
397
|
origin,
|
337
398
|
tuple(self.type(a) for a in args),
|
@@ -346,6 +407,15 @@ class Reflector:
|
|
346
407
|
if check_only:
|
347
408
|
return None
|
348
409
|
|
410
|
+
if _is_immediate_protocol(obj):
|
411
|
+
params = get_params(obj)
|
412
|
+
return Protocol(
|
413
|
+
obj,
|
414
|
+
params,
|
415
|
+
params,
|
416
|
+
obj,
|
417
|
+
)
|
418
|
+
|
349
419
|
if issubclass(obj, ta.Generic): # type: ignore
|
350
420
|
params = get_params(obj)
|
351
421
|
if params:
|
@@ -0,0 +1 @@
|
|
1
|
+
from .plugin import SwitchesPlugin # noqa
|
@@ -3,17 +3,20 @@ TODO:
|
|
3
3
|
- inheritance
|
4
4
|
- dynamic registration
|
5
5
|
- dynamic switching (skip docker if not running, skip online if not online, ...)
|
6
|
+
- probably make IF_SINGLE understand parametErization
|
6
7
|
"""
|
7
8
|
import dataclasses as dc
|
8
|
-
import enum
|
9
9
|
import typing as ta
|
10
10
|
|
11
11
|
import pytest
|
12
12
|
|
13
|
-
from
|
14
|
-
from
|
15
|
-
from
|
16
|
-
from .
|
13
|
+
from ..... import check
|
14
|
+
from ..... import collections as col
|
15
|
+
from .._registry import register
|
16
|
+
from .switches import SWITCHES
|
17
|
+
from .switches import SWITCHES_BY_NAME
|
18
|
+
from .switches import Switch
|
19
|
+
from .switches import SwitchState
|
17
20
|
|
18
21
|
|
19
22
|
Configable: ta.TypeAlias = pytest.FixtureRequest | pytest.Config
|
@@ -22,80 +25,6 @@ Configable: ta.TypeAlias = pytest.FixtureRequest | pytest.Config
|
|
22
25
|
##
|
23
26
|
|
24
27
|
|
25
|
-
class SwitchState(enum.Enum):
|
26
|
-
ENABLED = enum.auto()
|
27
|
-
DISABLED = enum.auto()
|
28
|
-
ONLY = enum.auto()
|
29
|
-
IF_SINGLE = enum.auto()
|
30
|
-
|
31
|
-
|
32
|
-
@dc.dataclass(frozen=True, eq=False)
|
33
|
-
class Switch:
|
34
|
-
name: str
|
35
|
-
_default_state: SwitchState | ta.Callable[[pytest.Session], SwitchState]
|
36
|
-
|
37
|
-
_: dc.KW_ONLY
|
38
|
-
|
39
|
-
add_marks: ta.Sequence[ta.Any] | None = None
|
40
|
-
|
41
|
-
def default_state(self, session: pytest.Session) -> SwitchState:
|
42
|
-
if isinstance(e := self._default_state, SwitchState):
|
43
|
-
return e
|
44
|
-
elif callable(e):
|
45
|
-
return check.isinstance(e(session), SwitchState)
|
46
|
-
else:
|
47
|
-
raise TypeError(e)
|
48
|
-
|
49
|
-
@property
|
50
|
-
def attr(self) -> str:
|
51
|
-
return self.name.replace('-', '_')
|
52
|
-
|
53
|
-
|
54
|
-
SWITCHES: ta.Sequence[Switch] = [
|
55
|
-
Switch(
|
56
|
-
'name',
|
57
|
-
lambda _: SwitchState.ENABLED if docker.has_cli() else SwitchState.DISABLED,
|
58
|
-
),
|
59
|
-
|
60
|
-
Switch(
|
61
|
-
'docker-guest',
|
62
|
-
lambda _: SwitchState.ENABLED if docker.is_likely_in_docker() else SwitchState.DISABLED,
|
63
|
-
),
|
64
|
-
|
65
|
-
Switch(
|
66
|
-
'online',
|
67
|
-
SwitchState.ENABLED,
|
68
|
-
),
|
69
|
-
|
70
|
-
Switch(
|
71
|
-
'integration',
|
72
|
-
SwitchState.ENABLED,
|
73
|
-
),
|
74
|
-
|
75
|
-
Switch(
|
76
|
-
'high-mem',
|
77
|
-
SwitchState.ENABLED,
|
78
|
-
add_marks=[
|
79
|
-
# https://pytest-xdist.readthedocs.io/en/latest/distribution.html
|
80
|
-
pytest.mark.xdist_group('high-mem'),
|
81
|
-
pytest.mark.gc_collect_after(),
|
82
|
-
],
|
83
|
-
),
|
84
|
-
|
85
|
-
Switch(
|
86
|
-
'slow',
|
87
|
-
SwitchState.IF_SINGLE,
|
88
|
-
),
|
89
|
-
]
|
90
|
-
|
91
|
-
|
92
|
-
SWITCHES_BY_NAME: ta.Mapping[str, Switch] = col.make_map_by(lambda sw: sw.name, SWITCHES, strict=True)
|
93
|
-
SWITCHES_BY_ATTR: ta.Mapping[str, Switch] = col.make_map_by(lambda sw: sw.attr, SWITCHES, strict=True)
|
94
|
-
|
95
|
-
|
96
|
-
##
|
97
|
-
|
98
|
-
|
99
28
|
SWITCH_STATE_OPT_PREFIXES: ta.Mapping[SwitchState, str] = {
|
100
29
|
SwitchState.ENABLED: '--',
|
101
30
|
SwitchState.DISABLED: '--no-',
|
@@ -193,6 +122,7 @@ class SwitchesPlugin:
|
|
193
122
|
def pytest_sessionstart(self, session):
|
194
123
|
session.stash[self._states_key] = self._States(session)
|
195
124
|
|
125
|
+
@pytest.hookimpl(tryfirst=True)
|
196
126
|
def pytest_collection_modifyitems(self, config, items):
|
197
127
|
def process_item(item):
|
198
128
|
state: SwitchesPlugin._States = item.session.stash[self._states_key]
|
@@ -0,0 +1,89 @@
|
|
1
|
+
import dataclasses as dc
|
2
|
+
import enum
|
3
|
+
import typing as ta
|
4
|
+
|
5
|
+
import pytest
|
6
|
+
|
7
|
+
from ..... import check
|
8
|
+
from ..... import collections as col
|
9
|
+
from .....docker import all as docker
|
10
|
+
|
11
|
+
|
12
|
+
##
|
13
|
+
|
14
|
+
|
15
|
+
class SwitchState(enum.Enum):
|
16
|
+
ENABLED = enum.auto()
|
17
|
+
DISABLED = enum.auto()
|
18
|
+
ONLY = enum.auto()
|
19
|
+
IF_SINGLE = enum.auto()
|
20
|
+
|
21
|
+
|
22
|
+
@dc.dataclass(frozen=True, eq=False)
|
23
|
+
class Switch:
|
24
|
+
name: str
|
25
|
+
_default_state: SwitchState | ta.Callable[[pytest.Session], SwitchState]
|
26
|
+
|
27
|
+
_: dc.KW_ONLY
|
28
|
+
|
29
|
+
add_marks: ta.Sequence[ta.Any] | None = None
|
30
|
+
|
31
|
+
def default_state(self, session: pytest.Session) -> SwitchState:
|
32
|
+
if isinstance(e := self._default_state, SwitchState):
|
33
|
+
return e
|
34
|
+
elif callable(e):
|
35
|
+
return check.isinstance(e(session), SwitchState)
|
36
|
+
else:
|
37
|
+
raise TypeError(e)
|
38
|
+
|
39
|
+
@property
|
40
|
+
def attr(self) -> str:
|
41
|
+
return self.name.replace('-', '_')
|
42
|
+
|
43
|
+
|
44
|
+
##
|
45
|
+
|
46
|
+
|
47
|
+
SWITCHES: ta.Sequence[Switch] = [
|
48
|
+
Switch(
|
49
|
+
'name',
|
50
|
+
lambda _: SwitchState.ENABLED if docker.has_cli() else SwitchState.DISABLED,
|
51
|
+
),
|
52
|
+
|
53
|
+
Switch(
|
54
|
+
'docker-guest',
|
55
|
+
lambda _: SwitchState.ENABLED if docker.is_likely_in_docker() else SwitchState.DISABLED,
|
56
|
+
),
|
57
|
+
|
58
|
+
Switch(
|
59
|
+
'online',
|
60
|
+
SwitchState.ENABLED,
|
61
|
+
),
|
62
|
+
|
63
|
+
Switch(
|
64
|
+
'integration',
|
65
|
+
SwitchState.ENABLED,
|
66
|
+
),
|
67
|
+
|
68
|
+
Switch(
|
69
|
+
'high-mem',
|
70
|
+
SwitchState.ENABLED,
|
71
|
+
add_marks=[
|
72
|
+
# https://pytest-xdist.readthedocs.io/en/latest/distribution.html
|
73
|
+
pytest.mark.xdist_group('high-mem'),
|
74
|
+
pytest.mark.gc_collect_after(),
|
75
|
+
],
|
76
|
+
),
|
77
|
+
|
78
|
+
Switch(
|
79
|
+
'slow',
|
80
|
+
SwitchState.IF_SINGLE,
|
81
|
+
),
|
82
|
+
]
|
83
|
+
|
84
|
+
|
85
|
+
##
|
86
|
+
|
87
|
+
|
88
|
+
SWITCHES_BY_NAME: ta.Mapping[str, Switch] = col.make_map_by(lambda sw: sw.name, SWITCHES, strict=True)
|
89
|
+
SWITCHES_BY_ATTR: ta.Mapping[str, Switch] = col.make_map_by(lambda sw: sw.attr, SWITCHES, strict=True)
|
omlish/testing/pytest/skip.py
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
"""
|
2
|
+
TODO:
|
3
|
+
- if_not_single? switches does this
|
4
|
+
"""
|
1
5
|
import shutil
|
2
6
|
import sys
|
3
7
|
import sysconfig
|
@@ -11,8 +15,9 @@ from ... import lang
|
|
11
15
|
##
|
12
16
|
|
13
17
|
|
14
|
-
def if_cant_import(
|
15
|
-
|
18
|
+
def if_cant_import(*modules: str, **kwargs):
|
19
|
+
missing = [m for m in modules if not lang.can_import(m, **kwargs)]
|
20
|
+
return pytest.mark.skipif(bool(missing), reason=f'requires import {", ".join(missing)}')
|
16
21
|
|
17
22
|
|
18
23
|
def if_not_on_path(exe: str):
|
@@ -27,11 +32,5 @@ def if_not_platform(*platforms: str):
|
|
27
32
|
return pytest.mark.skipif(sys.platform not in platforms, reason=f'requires platform in {platforms}')
|
28
33
|
|
29
34
|
|
30
|
-
def if_not_single():
|
31
|
-
# FIXME
|
32
|
-
# [resolve_collection_argument(a) for a in session.config.args]
|
33
|
-
raise NotImplementedError
|
34
|
-
|
35
|
-
|
36
35
|
def if_nogil():
|
37
36
|
return pytest.mark.skipif(sysconfig.get_config_var('Py_GIL_DISABLED'), reason='requires gil build')
|
omlish/typedvalues/__init__.py
CHANGED
omlish/typedvalues/accessor.py
CHANGED
@@ -27,7 +27,11 @@ class _NOT_SET(lang.Marker): # noqa
|
|
27
27
|
pass
|
28
28
|
|
29
29
|
|
30
|
-
class TypedValuesAccessor(
|
30
|
+
class TypedValuesAccessor(
|
31
|
+
lang.Abstract,
|
32
|
+
ta.Sequence[TypedValueT0],
|
33
|
+
ta.Generic[TypedValueT0],
|
34
|
+
):
|
31
35
|
def __iter__(self):
|
32
36
|
raise TypeError(
|
33
37
|
'TypedValuesAccessor does not implement __iter__ - it is reserved for implementation by subclasses.',
|
omlish/typedvalues/collection.py
CHANGED
@@ -0,0 +1,51 @@
|
|
1
|
+
import typing as ta
|
2
|
+
|
3
|
+
from .. import lang
|
4
|
+
from .collection import TypedValues
|
5
|
+
from .consumer import TypedValuesConsumer
|
6
|
+
from .values import TypedValue
|
7
|
+
|
8
|
+
|
9
|
+
TypedValueT = ta.TypeVar('TypedValueT', bound=TypedValue)
|
10
|
+
|
11
|
+
|
12
|
+
##
|
13
|
+
|
14
|
+
|
15
|
+
class _TypedValuesOf(lang.BindableClass[TypedValueT]): # noqa
|
16
|
+
@classmethod
|
17
|
+
def collect(
|
18
|
+
cls,
|
19
|
+
*tvs: TypedValueT,
|
20
|
+
override: bool = False,
|
21
|
+
check_type: bool | type | tuple[type, ...] | None = None,
|
22
|
+
) -> TypedValues[TypedValueT]: # noqa
|
23
|
+
if isinstance(check_type, bool):
|
24
|
+
if check_type:
|
25
|
+
if cls._bound is None:
|
26
|
+
raise TypeError('TypedValues.of unbound, cannot use check_type=True')
|
27
|
+
check_type = cls._bound
|
28
|
+
else:
|
29
|
+
check_type = None
|
30
|
+
|
31
|
+
return TypedValues(
|
32
|
+
*tvs,
|
33
|
+
override=override,
|
34
|
+
check_type=check_type,
|
35
|
+
)
|
36
|
+
|
37
|
+
@classmethod
|
38
|
+
def consume(
|
39
|
+
cls,
|
40
|
+
*tvs: TypedValueT,
|
41
|
+
override: bool = False,
|
42
|
+
check_type: bool | type | tuple[type, ...] | None = None,
|
43
|
+
) -> TypedValuesConsumer[TypedValueT]:
|
44
|
+
return cls.collect(
|
45
|
+
*tvs,
|
46
|
+
override=override,
|
47
|
+
check_type=check_type,
|
48
|
+
).consume()
|
49
|
+
|
50
|
+
|
51
|
+
of = _TypedValuesOf
|
@@ -1,5 +1,5 @@
|
|
1
1
|
omlish/.manifests.json,sha256=orgsRvtpHu8tdhaCvlP9v3P495OJopYYiHKjK68WtWg,8587
|
2
|
-
omlish/__about__.py,sha256=
|
2
|
+
omlish/__about__.py,sha256=9rj0m3n7RBQVQZMvY6T23ySBhV_U7yrnp5EbbcfsW48,3478
|
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
|
@@ -404,7 +404,7 @@ omlish/iterators/iterators.py,sha256=RxW35yQ5ed8vBQ22IqpDXFx-i5JiLQdp7-pkMZXhJJ8
|
|
404
404
|
omlish/iterators/recipes.py,sha256=wOwOZg-zWG9Zc3wcAxJFSe2rtavVBYwZOfG09qYEx_4,472
|
405
405
|
omlish/iterators/tools.py,sha256=tdtWhwkPQq3sg7Brakrcbf8e1cOBg6e0TtwnSMnvEpg,2582
|
406
406
|
omlish/iterators/unique.py,sha256=Nw0pSaNEcHAkve0ugfLPvJcirDOn9ECyC5wIL8JlJKI,1395
|
407
|
-
omlish/lang/__init__.py,sha256=
|
407
|
+
omlish/lang/__init__.py,sha256=nFH_r4AnosVDh6gyQ-2-y5OBgWiRik_Mx5hcN0TItdg,6434
|
408
408
|
omlish/lang/attrs.py,sha256=i7euRF81uNF8QDmUVXSK_BtqLGshaMi4VVdUnMjiMwg,5050
|
409
409
|
omlish/lang/casing.py,sha256=cFUlbDdXLhwnWwcYx4qnM5c4zGX7hIRUfcjiZbxUD28,4636
|
410
410
|
omlish/lang/clsdct.py,sha256=HAGIvBSbCefzRjXriwYSBLO7QHKRv2UsE78jixOb-fA,1828
|
@@ -433,7 +433,9 @@ omlish/lang/cached/function.py,sha256=su9QxYECK9NK-UfMFKbgx4lqH2WoGBiYshnEfaGvfh
|
|
433
433
|
omlish/lang/cached/property.py,sha256=WHYyg4-6EA86TcNMfbXTjVhjEZPc0kngt9hfY3WN5w8,2768
|
434
434
|
omlish/lang/classes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
435
435
|
omlish/lang/classes/abstract.py,sha256=A-Jg5X8o_WvFryN0Cm2TpVkrZoTT1SYKQnv_pXjZk7o,3808
|
436
|
+
omlish/lang/classes/bindable.py,sha256=ekVyOxrM9kQ9AtI9Zzc89zP_JBfJizIThKFNw4YZtS8,1096
|
436
437
|
omlish/lang/classes/namespaces.py,sha256=_FBLekx2gNLql1C1ZRlpBtxuLWbcdFEzBm8CrD5XeOA,3589
|
438
|
+
omlish/lang/classes/protocols.py,sha256=T98ZsHLgzw8hPvvNluxoreevoF8fD4zs8SwcnTXkLuY,701
|
437
439
|
omlish/lang/classes/restrict.py,sha256=Ki-UOc2yUVteqC7i_EgIVpeEcnvRHVczjts5Fyiz7Mk,4125
|
438
440
|
omlish/lang/classes/simple.py,sha256=2C7u8k0K75xzcr6DT8zYd8U-1Yr_Xq1pfF3a0J6wo3g,2538
|
439
441
|
omlish/lang/classes/virtual.py,sha256=z0MYQD9Q5MkX8DzF325wDB4J9XoYbsB09jZ1omC62To,3366
|
@@ -496,7 +498,7 @@ omlish/marshal/global_.py,sha256=nTJmC17O8SJNURScIdYqEY72h-dRy6D-SaDSUQCp-cY,152
|
|
496
498
|
omlish/marshal/naming.py,sha256=7jQ204u_Kpc3-OGr-ctUHSv997DdWYRLh643qLHJhks,852
|
497
499
|
omlish/marshal/proxy.py,sha256=puKJpwPpuDlMOIrKMcLTRLJyMiL6n_Xs-p59AuDEymA,543
|
498
500
|
omlish/marshal/registries.py,sha256=FvC6qXHCizNB2QmU_N3orxW7iqfGYkiUXYYdTRWS6HA,2353
|
499
|
-
omlish/marshal/standard.py,sha256=
|
501
|
+
omlish/marshal/standard.py,sha256=C1AawI1IrSb_mH6xBhZWHnqdjviVpk5-Cm9g-9aY02A,4487
|
500
502
|
omlish/marshal/values.py,sha256=ssHiWdg_L6M17kAn8GiGdPW7UeQOm3RDikWkvwblf5I,263
|
501
503
|
omlish/marshal/composite/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
502
504
|
omlish/marshal/composite/iterables.py,sha256=YdkdWNUe_AzdUqiAsr7z3kaDcPeg7Znj3AuQepY_qaA,2647
|
@@ -505,6 +507,7 @@ omlish/marshal/composite/mappings.py,sha256=HoqUKe4kyCYRdMpQMWW0DLPi0-DEsxt-nk4p
|
|
505
507
|
omlish/marshal/composite/maybes.py,sha256=NfQ2cIHHIvohTl4iYPYbEvhNVq3L3JCu2GEbt4DM5DA,2216
|
506
508
|
omlish/marshal/composite/newtypes.py,sha256=5-te247TiPYf84oFhf59tqIOOByXj8i9KaHT8gn72fU,878
|
507
509
|
omlish/marshal/composite/optionals.py,sha256=MnecrmrJYjQvYJipIHNCDq78oH09dOjnw5pvaMKqoeU,1537
|
510
|
+
omlish/marshal/composite/special.py,sha256=s0PcOmDiQyCjoxcdaGSORTqNoXNp6uuBz_NJs2kHzRM,1350
|
508
511
|
omlish/marshal/composite/wrapped.py,sha256=jOsn3h1vLIqcoSTB-0KObnsdbV8jSVWJYbf7Kg9AUwg,750
|
509
512
|
omlish/marshal/objects/__init__.py,sha256=F4wej8L_tedC8ETYxAnmKfdPR9TjsqIus9Z3nZofYuc,182
|
510
513
|
omlish/marshal/objects/dataclasses.py,sha256=klXXY1zOKh_FYlw6L5ZNPjpXSk0ntUGxSOrm309WoiY,8953
|
@@ -563,11 +566,11 @@ omlish/os/pidfiles/cli.py,sha256=2SSsP4O3VdpsDIMAkWgWSjh_YNIPzCD9l5LNN2qrIjo,207
|
|
563
566
|
omlish/os/pidfiles/manager.py,sha256=QphQxIENVVwvBWynLCNU31NwOfLkV43VoTVeYFn2Hac,2351
|
564
567
|
omlish/os/pidfiles/pidfile.py,sha256=9tI5IMVwfPfnni0XMn4x5ptNQgm36n8tLeUNPf50UqU,4394
|
565
568
|
omlish/os/pidfiles/pinning.py,sha256=aQgCmvcAqN0lvI70GcSB2TKVX1G4vwbyN_AOHF3-eKE,6630
|
566
|
-
omlish/reflect/__init__.py,sha256=
|
569
|
+
omlish/reflect/__init__.py,sha256=9pzXLXXNMHkLhhI79iUr-o0SMOtR6HMUmAEUplZkIdE,853
|
567
570
|
omlish/reflect/inspect.py,sha256=WCo2YpBYauKw6k758FLlZ_H4Q05rgVPs96fEv9w6zHQ,1538
|
568
|
-
omlish/reflect/ops.py,sha256=
|
571
|
+
omlish/reflect/ops.py,sha256=RxUc9sFZxYP_f5y-jU2DujFLkzhzx8DsyITShPSpW3U,2614
|
569
572
|
omlish/reflect/subst.py,sha256=jpBgYR1_JyH9fz5b-gmOg7OhFKk7jIxEh7hwtKYKC9Q,3691
|
570
|
-
omlish/reflect/types.py,sha256=
|
573
|
+
omlish/reflect/types.py,sha256=C3NsAQFam_9mXhvSUa0H0RnJxhVAzIbY1Z_WHXHcNcs,11213
|
571
574
|
omlish/secrets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
572
575
|
omlish/secrets/all.py,sha256=gv_d9SfyMxso30HsrSz9XmIrSZOdl3rLA5MSH0ZXfgM,486
|
573
576
|
omlish/secrets/crypto.py,sha256=9D21lnvPhStwu8arD4ssT0ih0bDG-nlqIRdVgYL40xA,3708
|
@@ -742,7 +745,7 @@ omlish/testing/testing.py,sha256=zmBHw5gw1ZUUcDYC0uonSThjhRn0HNuorjpo0jLvju8,288
|
|
742
745
|
omlish/testing/pytest/__init__.py,sha256=i4ti6Q2rVYJ-XBk9UYDfUUagCrEDTC5jOeSykBjYYZQ,234
|
743
746
|
omlish/testing/pytest/helpers.py,sha256=HxiKvpJQ4b6WCiQXOqQTqKbmr7CMAgCF6hViT6pfIuw,202
|
744
747
|
omlish/testing/pytest/marks.py,sha256=qhVnq-3LlQ5uRLS1LXYkh8Xk-8aQGOgs2Nr49T8YqOA,280
|
745
|
-
omlish/testing/pytest/skip.py,sha256=
|
748
|
+
omlish/testing/pytest/skip.py,sha256=tra8FM5CZTh4M7ZWVf9YPmKUX4yhesf61XRoIkO4s9c,954
|
746
749
|
omlish/testing/pytest/inject/__init__.py,sha256=pdRKv1HcDmJ_yArKJbYITPXXZthRSGgBJWqITr0Er38,117
|
747
750
|
omlish/testing/pytest/inject/harness.py,sha256=_Qf7lLcYc_dpauYOE68u_a65jPCFWmQUYv9m_OOdNqs,5724
|
748
751
|
omlish/testing/pytest/plugins/__init__.py,sha256=ys1zXrYrNm7Uo6YOIVJ6Bd3dQo6kv387k7MbTYlqZSI,467
|
@@ -754,7 +757,6 @@ omlish/testing/pytest/plugins/pydevd.py,sha256=5moE64LrNRV6gKRaeCuONDiwuh-4UFxJP
|
|
754
757
|
omlish/testing/pytest/plugins/repeat.py,sha256=jiZCI-17042jBvUEbZCxNwqWtr7s3EhTBSeSHh_Uz4E,497
|
755
758
|
omlish/testing/pytest/plugins/skips.py,sha256=eMir_n777Kk2BvOwjQzRROKL4iAMYKSHFwWCHJ-bdPI,1040
|
756
759
|
omlish/testing/pytest/plugins/spacing.py,sha256=tzq-L-exegHe2BImumkYIsVcUwpUUhLJJOuSrsKDuCU,706
|
757
|
-
omlish/testing/pytest/plugins/switches.py,sha256=z3TKe2NHBOaa_cmarWTRJo519iCNDff4e0XSfHkajHU,7365
|
758
760
|
omlish/testing/pytest/plugins/utils.py,sha256=L5C622UXcA_AUKDcvyh5IMiRfqSGGz0McdhwZWvfMlU,261
|
759
761
|
omlish/testing/pytest/plugins/asyncs/__init__.py,sha256=TTNhFmP_krug1973sq_bpWBTIvg68-1nbuVLSs92Z6k,41
|
760
762
|
omlish/testing/pytest/plugins/asyncs/consts.py,sha256=0NOCkzV43dOu3u97BqYMQ4mPG8JuFncpWibkOZpCqX4,55
|
@@ -766,6 +768,9 @@ omlish/testing/pytest/plugins/asyncs/backends/asyncio.py,sha256=0b8pmbXNW2qI8qo1
|
|
766
768
|
omlish/testing/pytest/plugins/asyncs/backends/base.py,sha256=fTZ6R_iKpAp-8DVw8js8rxC_VNqj6onFD4KKBWnmtXk,587
|
767
769
|
omlish/testing/pytest/plugins/asyncs/backends/trio.py,sha256=xty9TR7-Kk6n0cdOqErLilPLLCchJe6zmEyhpypTmKM,3330
|
768
770
|
omlish/testing/pytest/plugins/asyncs/backends/trio_asyncio.py,sha256=VcGVwf4V-1ZFK_70FrFS9b11EU1dOy1ozhhIDXGNSEo,3169
|
771
|
+
omlish/testing/pytest/plugins/switches/__init__.py,sha256=KTdm9xe8AYQvNT-IKSGr9O8q_hgRGEqhK3zcto0EbWk,43
|
772
|
+
omlish/testing/pytest/plugins/switches/plugin.py,sha256=RBxjefl9RDJuSmT_W0lTSd9DlAT-nkyy_U2fBYzdWNs,5835
|
773
|
+
omlish/testing/pytest/plugins/switches/switches.py,sha256=lj8S9RMwUAW7a93ZqqTjoD4dRVkeGts2sl8Cn-H17hc,1890
|
769
774
|
omlish/text/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
770
775
|
omlish/text/asdl.py,sha256=AS3irh-sag5pqyH3beJif78PjCbOaFso1NeKq-HXuTs,16867
|
771
776
|
omlish/text/decoding.py,sha256=sQWGckWzRslRHYKpj1SBeoo6AVqXm5HFlWFRARN1QpM,1286
|
@@ -849,18 +854,19 @@ omlish/text/antlr/_runtime/xpath/XPathLexer.py,sha256=WvGKQjQnu7pX5C4CFKtsCzba2B
|
|
849
854
|
omlish/text/antlr/_runtime/xpath/__init__.py,sha256=lMd_BbXYdlDhZQN_q0TKN978XW5G0pq618F0NaLkpFE,71
|
850
855
|
omlish/text/go/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
851
856
|
omlish/text/go/quoting.py,sha256=N9EYdnFdEX_A8fOviH-1w4jwV3XOQ7VU2WsoUNubYVY,9137
|
852
|
-
omlish/typedvalues/__init__.py,sha256=
|
853
|
-
omlish/typedvalues/accessor.py,sha256=
|
854
|
-
omlish/typedvalues/collection.py,sha256=
|
857
|
+
omlish/typedvalues/__init__.py,sha256=Br1vFbV-dEjAfBbZ9Zg2xCGO87U6kduxxq69lrMRODw,722
|
858
|
+
omlish/typedvalues/accessor.py,sha256=959QsdK1zildcBTvFKSA6uAgi7SSo2RPKqcKWsuEZrM,3162
|
859
|
+
omlish/typedvalues/collection.py,sha256=QxQwaSmJGF2oAWAv2CZkgpOljbnxor104XOrCD0v1a8,5571
|
855
860
|
omlish/typedvalues/consumer.py,sha256=peDQAgriSyBx_Hc8QHAhEgYy0oSS52qQ_7Tqdssl2AE,4375
|
856
861
|
omlish/typedvalues/generic.py,sha256=ft-x4X3k1oFirtYnDfsvrI3ZQikWM8lGLrvrOEbcGq0,742
|
857
862
|
omlish/typedvalues/holder.py,sha256=vu-umn-h1nvUqmtV5T9ZfQ_OoOYsERu8PhI2N48Ryns,1133
|
858
863
|
omlish/typedvalues/marshal.py,sha256=AtBz7Jq-BfW8vwM7HSxSpR85JAXmxK2T0xDblmm1HI0,4956
|
864
|
+
omlish/typedvalues/of_.py,sha256=UXkxSj504WI2UrFlqdZJbu2hyDwBhL7XVrc2qdR02GQ,1309
|
859
865
|
omlish/typedvalues/reflect.py,sha256=PAvKW6T4cW7u--iX80w3HWwZUS3SmIZ2_lQjT65uAyk,1026
|
860
866
|
omlish/typedvalues/values.py,sha256=ym46I-q2QJ_6l4UlERqv3yj87R-kp8nCKMRph0xQ3UA,1307
|
861
|
-
omlish-0.0.0.
|
862
|
-
omlish-0.0.0.
|
863
|
-
omlish-0.0.0.
|
864
|
-
omlish-0.0.0.
|
865
|
-
omlish-0.0.0.
|
866
|
-
omlish-0.0.0.
|
867
|
+
omlish-0.0.0.dev339.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
868
|
+
omlish-0.0.0.dev339.dist-info/METADATA,sha256=Bx0Qfyj8FjWFBV_s8fjqv2aA13OgX8R1SCRM5RKTMSU,4416
|
869
|
+
omlish-0.0.0.dev339.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
870
|
+
omlish-0.0.0.dev339.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
|
871
|
+
omlish-0.0.0.dev339.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
|
872
|
+
omlish-0.0.0.dev339.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|