omlish 0.0.0.dev271__py3-none-any.whl → 0.0.0.dev272__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.dev271'
2
- __revision__ = 'fc242f5a994ee5dd88268a5720ed88792d17c61f'
1
+ __version__ = '0.0.0.dev272'
2
+ __revision__ = '77ed49b2a8b3f746064a52c4b81e1c02dba03a40'
3
3
 
4
4
 
5
5
  #
@@ -0,0 +1,25 @@
1
+ from .accessor import ( # noqa
2
+ TypedValuesAccessor,
3
+ )
4
+
5
+ from .collection import ( # noqa
6
+ DuplicateUniqueTypedValueError,
7
+
8
+ TypedValues,
9
+ )
10
+
11
+ from .generic import ( # noqa
12
+ TypedValueGeneric,
13
+ )
14
+
15
+ from .holder import ( # noqa
16
+ TypedValueHolder,
17
+ )
18
+
19
+ from .values import ( # noqa
20
+ TypedValue,
21
+
22
+ UniqueTypedValue,
23
+
24
+ ScalarTypedValue,
25
+ )
@@ -0,0 +1,113 @@
1
+ """
2
+ TODO:
3
+ - Accessor inputs/outputs should *ideally* be subtype of class generic param
4
+ - but can't make a typevar with a bound of another typevar
5
+ """
6
+ import abc
7
+ import typing as ta
8
+
9
+ from .. import lang
10
+ from .values import TypedValue # noqa
11
+ from .values import UniqueTypedValue # noqa
12
+
13
+
14
+ T = ta.TypeVar('T')
15
+
16
+ TypedValueT = ta.TypeVar('TypedValueT', bound='TypedValue')
17
+ TypedValueU = ta.TypeVar('TypedValueU', bound='TypedValue')
18
+
19
+ UniqueTypedValueU = ta.TypeVar('UniqueTypedValueU', bound='UniqueTypedValue')
20
+
21
+
22
+ ##
23
+
24
+
25
+ class TypedValuesAccessor(lang.Abstract, ta.Generic[TypedValueT]):
26
+ @ta.final
27
+ def __contains__(self, cls: type[TypedValueU]) -> bool:
28
+ raise NotImplementedError
29
+
30
+ @abc.abstractmethod
31
+ def _typed_value_contains(self, cls):
32
+ raise NotImplementedError
33
+
34
+ #
35
+
36
+ @ta.overload
37
+ def __getitem__(self, idx: int) -> TypedValueT:
38
+ ...
39
+
40
+ @ta.overload
41
+ def __getitem__(self, cls: type[UniqueTypedValueU]) -> UniqueTypedValueU: # type: ignore[overload-overlap]
42
+ ...
43
+
44
+ @ta.overload
45
+ def __getitem__(self, cls: type[TypedValueU]) -> ta.Sequence[TypedValueU]:
46
+ ...
47
+
48
+ @ta.final
49
+ def __getitem__(self, key):
50
+ return self._typed_value_getitem(key)
51
+
52
+ @abc.abstractmethod
53
+ def _typed_value_getitem(self, key):
54
+ raise NotImplementedError
55
+
56
+ #
57
+
58
+ @ta.overload
59
+ def get(
60
+ self,
61
+ tv: UniqueTypedValueU,
62
+ ) -> UniqueTypedValueU:
63
+ ...
64
+
65
+ @ta.overload
66
+ def get(
67
+ self,
68
+ cls: type[UniqueTypedValueU],
69
+ /,
70
+ default: UniqueTypedValueU,
71
+ ) -> UniqueTypedValueU:
72
+ ...
73
+
74
+ @ta.overload
75
+ def get( # type: ignore[overload-overlap]
76
+ self,
77
+ cls: type[UniqueTypedValueU],
78
+ /,
79
+ default: None = None,
80
+ ) -> UniqueTypedValueU | None:
81
+ ...
82
+
83
+ @ta.overload
84
+ def get(
85
+ self,
86
+ cls: type[TypedValueU],
87
+ /,
88
+ default: ta.Iterable[TypedValueU] | None = None,
89
+ ) -> ta.Sequence[TypedValueU]:
90
+ ...
91
+
92
+ @ta.final
93
+ def get(self, key, /, default=None):
94
+ if not isinstance(key, type):
95
+ if default is not None:
96
+ raise RuntimeError('Must not provide both an instance key and a default')
97
+ default = key
98
+ key = type(default)
99
+ return self._typed_value_get(key, default)
100
+
101
+ @abc.abstractmethod
102
+ def _typed_value_get(self, key, /, default=None):
103
+ raise NotImplementedError
104
+
105
+ #
106
+
107
+ @ta.final
108
+ def get_any(self, cls: type[T]) -> ta.Sequence[T]:
109
+ return self._typed_value_get_any(cls)
110
+
111
+ @abc.abstractmethod
112
+ def _typed_value_get_any(self, cls):
113
+ raise NotImplementedError
@@ -0,0 +1,124 @@
1
+ import typing as ta
2
+
3
+ from .. import check
4
+ from .. import dataclasses as dc
5
+ from .. import lang
6
+ from .accessor import TypedValuesAccessor
7
+ from .values import TypedValue
8
+ from .values import UniqueTypedValue
9
+
10
+
11
+ TypedValueT = ta.TypeVar('TypedValueT', bound='TypedValue')
12
+
13
+ UniqueTypedValueT = ta.TypeVar('UniqueTypedValueT', bound='UniqueTypedValue')
14
+
15
+
16
+ ##
17
+
18
+
19
+ @dc.dataclass()
20
+ class DuplicateUniqueTypedValueError(Exception, ta.Generic[UniqueTypedValueT]):
21
+ cls: type[UniqueTypedValueT]
22
+ new: UniqueTypedValueT
23
+ old: UniqueTypedValueT
24
+
25
+
26
+ class TypedValues(
27
+ TypedValuesAccessor[TypedValueT],
28
+ lang.Final,
29
+ ta.Generic[TypedValueT],
30
+ ):
31
+ def __init__(self, *tvs: TypedValueT, override: bool = False) -> None:
32
+ super().__init__()
33
+
34
+ tmp: list = []
35
+ udct: dict = {}
36
+ for tv in tvs:
37
+ if isinstance(tv, UniqueTypedValue):
38
+ uoc = tv._unique_typed_value_cls # noqa
39
+ if not override:
40
+ try:
41
+ exu = udct[uoc]
42
+ except KeyError:
43
+ pass
44
+ else:
45
+ raise DuplicateUniqueTypedValueError(uoc, tv, check.single(exu))
46
+ ulst = udct.setdefault(uoc, [])
47
+ ulst.append(tv)
48
+ tmp.append((tv, len(ulst)))
49
+ elif isinstance(tv, TypedValue):
50
+ tmp.append(tv)
51
+ else:
52
+ raise TypeError(tv)
53
+
54
+ lst: list = []
55
+ dct: dict = {}
56
+ for tv in tmp:
57
+ if isinstance(tv, tuple):
58
+ uo, idx = tv # type: ignore
59
+ ulst = udct[uo._unique_typed_value_cls] # noqa
60
+ if idx == len(ulst):
61
+ lst.append(uo)
62
+ dct[uo._unique_typed_value_cls] = uo # noqa
63
+ dct[type(uo)] = uo
64
+ else:
65
+ lst.append(tv)
66
+ dct.setdefault(type(tv), []).append(tv)
67
+
68
+ self._lst = lst
69
+ self._dct = dct
70
+
71
+ self._any_dct: dict[type, ta.Sequence[ta.Any]] = {}
72
+
73
+ def without(self, *tys: type) -> ta.Iterator[TypedValueT]:
74
+ for o in self._lst:
75
+ if not isinstance(o, tys):
76
+ yield o
77
+
78
+ def __repr__(self) -> str:
79
+ return f'{self.__class__.__name__}({", ".join(map(repr, self._lst))})'
80
+
81
+ #
82
+
83
+ def __iter__(self) -> ta.Iterator[TypedValueT]:
84
+ return iter(self._lst)
85
+
86
+ def __len__(self) -> int:
87
+ return len(self._lst)
88
+
89
+ def __bool__(self) -> bool:
90
+ return bool(self._lst)
91
+
92
+ #
93
+
94
+ def _typed_value_contains(self, cls):
95
+ return cls in self._dct
96
+
97
+ def _typed_value_getitem(self, key):
98
+ if isinstance(key, int):
99
+ return self._lst[key]
100
+ elif isinstance(key, type):
101
+ return self._dct[check.issubclass(key, TypedValue)]
102
+ else:
103
+ raise TypeError(key)
104
+
105
+ def _typed_value_get(self, key, /, default=None):
106
+ check.issubclass(key, TypedValue)
107
+ try:
108
+ return self._dct[key]
109
+ except KeyError:
110
+ if issubclass(key, UniqueTypedValue):
111
+ return default
112
+ elif default is not None:
113
+ return list(default)
114
+ else:
115
+ return []
116
+
117
+ def _typed_value_get_any(self, cls):
118
+ try:
119
+ return self._any_dct[cls]
120
+ except KeyError:
121
+ pass
122
+ ret = [tv for tv in self if isinstance(tv, cls)]
123
+ self._any_dct[cls] = ret
124
+ return ret
@@ -0,0 +1,31 @@
1
+ import typing as ta
2
+
3
+ from .. import check
4
+ from .. import lang
5
+ from .. import reflect as rfl
6
+ from .values import TypedValue # noqa
7
+
8
+
9
+ TypedValueT = ta.TypeVar('TypedValueT', bound='TypedValue')
10
+
11
+
12
+ ##
13
+
14
+
15
+ class TypedValueGeneric(lang.Abstract, ta.Generic[TypedValueT]):
16
+ _typed_value_type: ta.ClassVar[rfl.Type]
17
+
18
+ def __init_subclass__(cls, **kwargs: ta.Any) -> None:
19
+ super().__init_subclass__(**kwargs)
20
+
21
+ if '_typed_value_type' in cls.__dict__:
22
+ return
23
+
24
+ g_mro = rfl.ALIAS_UPDATING_GENERIC_SUBSTITUTION.generic_mro(cls)
25
+ g_tvg = check.single(
26
+ gb
27
+ for gb in g_mro
28
+ if isinstance(gb, rfl.Generic) and gb.cls is TypedValueGeneric
29
+ )
30
+ tvt = check.single(g_tvg.args)
31
+ cls._typed_value_type = tvt
@@ -0,0 +1,60 @@
1
+ import abc
2
+ import typing as ta
3
+
4
+ from .. import check
5
+ from .. import lang
6
+ from .accessor import TypedValuesAccessor
7
+ from .collection import TypedValues
8
+ from .generic import TypedValueGeneric
9
+ from .values import TypedValue
10
+ from .values import UniqueTypedValue
11
+
12
+
13
+ TypedValueT = ta.TypeVar('TypedValueT', bound='TypedValue')
14
+
15
+
16
+ ##
17
+
18
+
19
+ class TypedValueHolder(
20
+ TypedValuesAccessor[TypedValueT],
21
+ TypedValueGeneric[TypedValueT],
22
+ lang.Abstract,
23
+ ):
24
+ @property
25
+ @abc.abstractmethod
26
+ def _typed_values(self) -> TypedValues[TypedValueT] | None:
27
+ raise NotImplementedError
28
+
29
+ #
30
+
31
+ def _typed_value_contains(self, cls):
32
+ if (tvs := self._typed_values) is not None:
33
+ return cls in tvs
34
+ return False
35
+
36
+ def _typed_value_getitem(self, key):
37
+ if (tvs := self._typed_values) is not None:
38
+ return tvs[key]
39
+ if isinstance(key, int):
40
+ raise IndexError(key)
41
+ elif isinstance(key, type):
42
+ raise KeyError(key)
43
+ else:
44
+ raise TypeError(key)
45
+
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
+ def _typed_value_get_any(self, cls):
58
+ if (tvs := self._typed_values) is not None:
59
+ return tvs.get_any(cls)
60
+ return []
@@ -0,0 +1,38 @@
1
+ import typing as ta
2
+
3
+ from .. import dataclasses as dc
4
+ from .. import lang
5
+
6
+
7
+ T = ta.TypeVar('T')
8
+
9
+
10
+ ##
11
+
12
+
13
+ class TypedValue(lang.Abstract):
14
+ pass
15
+
16
+
17
+ class UniqueTypedValue(TypedValue, lang.Abstract):
18
+ _unique_typed_value_cls: ta.ClassVar[type[TypedValue]]
19
+
20
+ def __init_subclass__(cls, **kwargs: ta.Any) -> None:
21
+ super().__init_subclass__(**kwargs)
22
+
23
+ if UniqueTypedValue in cls.__bases__:
24
+ try:
25
+ cls._unique_typed_value_cls # noqa
26
+ except AttributeError:
27
+ cls._unique_typed_value_cls = cls
28
+ else:
29
+ raise TypeError(f'Class already has _unique_typed_value_cls: {cls}')
30
+
31
+
32
+ @dc.dataclass(frozen=True)
33
+ @dc.extra_params(generic_init=True)
34
+ class ScalarTypedValue(TypedValue, lang.Abstract, ta.Generic[T]):
35
+ v: T
36
+
37
+ def __repr__(self) -> str:
38
+ return f'{self.__class__.__name__}({self.v!r})'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: omlish
3
- Version: 0.0.0.dev271
3
+ Version: 0.0.0.dev272
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -1,5 +1,5 @@
1
1
  omlish/.manifests.json,sha256=x26AIwDzScUvnX-p4xlq6Zc5QYrAo0Vmgf1qHc1KL_M,8253
2
- omlish/__about__.py,sha256=a-BsHYkG1XmGNuahLQVSE6wR7i-00PDzWGTjEenZsC0,3380
2
+ omlish/__about__.py,sha256=sBVk_BgCjXDv-7KkFlDdOfXgB8qnaGdomycyZCp2gHA,3380
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
@@ -776,9 +776,15 @@ omlish/text/parts.py,sha256=Q9NvoyEGQKIWgiPD4D_Qc66cWAuyEKE033dT9m7c3Wk,6662
776
776
  omlish/text/random.py,sha256=8feS5JE_tSjYlMl-lp0j93kCfzBae9AM2cXlRLebXMA,199
777
777
  omlish/text/go/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
778
778
  omlish/text/go/quoting.py,sha256=N9EYdnFdEX_A8fOviH-1w4jwV3XOQ7VU2WsoUNubYVY,9137
779
- omlish-0.0.0.dev271.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
780
- omlish-0.0.0.dev271.dist-info/METADATA,sha256=SXISrSK-Lmc1Z9EwMNS_ex2iPPZeBFhAoayeCdlukGw,4198
781
- omlish-0.0.0.dev271.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
782
- omlish-0.0.0.dev271.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
783
- omlish-0.0.0.dev271.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
784
- omlish-0.0.0.dev271.dist-info/RECORD,,
779
+ omlish/typedvalues/__init__.py,sha256=9ROZq46KN2scNUckjMaSiUiXxP3a_-8_lnOh_eBF5RM,357
780
+ omlish/typedvalues/accessor.py,sha256=gZ48yDFRYS_0TgbRBY6Pxa50ncWCqwaGes_T_RWLTvo,2738
781
+ omlish/typedvalues/collection.py,sha256=XTAmxo_QlhaIUM-oFif-kDxxi3esQ5E1p99NSHsqRn0,3496
782
+ omlish/typedvalues/generic.py,sha256=byWG_gMXhNelckUwdmOoJE9FKkL71Q4BSi4ZLyy0XZ0,788
783
+ omlish/typedvalues/holder.py,sha256=4SwRezsmuDDEO5gENGx8kTm30pblF5UktoEAu02i-Gk,1554
784
+ omlish/typedvalues/values.py,sha256=DPq490iKm_Ny_pUa2tmSzMuITAZDGhIt969OaphFROg,892
785
+ omlish-0.0.0.dev272.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
786
+ omlish-0.0.0.dev272.dist-info/METADATA,sha256=XTYfFdON0tX-aBDW2Bo_n7ifW_sx1zE9oCg_2MWqmuo,4198
787
+ omlish-0.0.0.dev272.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
788
+ omlish-0.0.0.dev272.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
789
+ omlish-0.0.0.dev272.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
790
+ omlish-0.0.0.dev272.dist-info/RECORD,,