omlish 0.0.0.dev319__py3-none-any.whl → 0.0.0.dev321__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.dev319'
2
- __revision__ = 'db501bf0b4fbb5f1af2b467b004ffec22f3e769c'
1
+ __version__ = '0.0.0.dev321'
2
+ __revision__ = 'e452050adbb646a190bed1f28cfcacf45c007fab'
3
3
 
4
4
 
5
5
  #
@@ -4,6 +4,12 @@ import typing as _ta
4
4
  from .. import lang as _lang
5
5
 
6
6
 
7
+ from .bimap import ( # noqa
8
+ BiMap,
9
+
10
+ make_bi_map,
11
+ )
12
+
7
13
  from .coerce import ( # noqa
8
14
  abs_set,
9
15
  abs_set_of,
@@ -0,0 +1,89 @@
1
+ import abc
2
+ import typing as ta
3
+
4
+ from .. import check
5
+ from .. import lang
6
+
7
+
8
+ K = ta.TypeVar('K')
9
+ V = ta.TypeVar('V')
10
+
11
+ K2 = ta.TypeVar('K2')
12
+ V2 = ta.TypeVar('V2')
13
+
14
+
15
+ ##
16
+
17
+
18
+ class BiMap(ta.Mapping[K, V], lang.Abstract):
19
+ @abc.abstractmethod
20
+ def inverse(self) -> 'BiMap[V, K]':
21
+ raise NotImplementedError
22
+
23
+
24
+ ##
25
+
26
+
27
+ class _BaseBiMapImpl(BiMap[K, V], lang.Abstract):
28
+ def __init__(
29
+ self,
30
+ dct: ta.Mapping[K, V],
31
+ inverse: BiMap[V, K],
32
+ ) -> None:
33
+ super().__init__()
34
+
35
+ self._dct = dct
36
+ self._inverse = inverse
37
+
38
+ def inverse(self) -> 'BiMap[V, K]':
39
+ return self._inverse
40
+
41
+ def __getitem__(self, key, /):
42
+ return self._dct[key]
43
+
44
+ def __len__(self) -> int:
45
+ return len(self._dct)
46
+
47
+ def __iter__(self):
48
+ return iter(self._dct)
49
+
50
+ def __repr__(self) -> str:
51
+ return f'BiMap({self._dct!r})'
52
+
53
+
54
+ class _BiMapImpl(_BaseBiMapImpl[K, V]):
55
+ def __init__(self, *args, **kwargs) -> None:
56
+ dct: dict[K, V] = {}
57
+ inv_dct: dict[V, K] = {}
58
+ for k, v in lang.yield_dict_init(*args, **kwargs):
59
+ check.not_in(k, dct)
60
+ check.not_in(v, inv_dct)
61
+ dct[k] = v
62
+ inv_dct[v] = k
63
+
64
+ super().__init__(dct, _BiMapImpl._Inverse(inv_dct, self))
65
+
66
+ class _Inverse(_BaseBiMapImpl):
67
+ pass
68
+
69
+
70
+ ##
71
+
72
+
73
+ @ta.overload
74
+ def make_bi_map(**kwargs: V) -> BiMap[V, str]:
75
+ ...
76
+
77
+
78
+ @ta.overload
79
+ def make_bi_map(dct: ta.Mapping[K, V]) -> BiMap[K, V]:
80
+ ...
81
+
82
+
83
+ @ta.overload
84
+ def make_bi_map(items: ta.Iterable[tuple[K, V]]) -> BiMap[K, V]:
85
+ ...
86
+
87
+
88
+ def make_bi_map(*args, **kwargs):
89
+ return _BiMapImpl(*args, **kwargs)
@@ -217,6 +217,13 @@ class Method(ta.Generic[P, R]):
217
217
  def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R:
218
218
  instance, *rest = args
219
219
  instance_cls = type(instance)
220
+
221
+ # if instance_cls is super:
222
+ # owner = instance.__self_class__.__mro__[instance.__self_class__.__mro__.index(instance.__thisclass__) + 1]
223
+ # att_disp = self.build_attr_dispatcher(instance.__self_class__, owner)
224
+ # func = self.build_dispatch_func(att_disp)
225
+ # return func.__get__(instance, instance.__thisclass__)(*rest, **kwargs)
226
+
220
227
  try:
221
228
  func = self._dispatch_func_cache[weakref.ref(instance_cls)]
222
229
  except KeyError:
omlish/lang/__init__.py CHANGED
@@ -61,6 +61,12 @@ from .classes.abstract import ( # noqa
61
61
  unabstract_class,
62
62
  )
63
63
 
64
+ from .classes.namespaces import ( # noqa
65
+ GenericNamespaceMeta,
66
+ Namespace,
67
+ NamespaceMeta,
68
+ )
69
+
64
70
  from .classes.restrict import ( # noqa
65
71
  AnySensitive,
66
72
  Final,
@@ -79,7 +85,6 @@ from .classes.restrict import ( # noqa
79
85
  from .classes.simple import ( # noqa
80
86
  LazySingleton,
81
87
  Marker,
82
- Namespace,
83
88
  SimpleMetaDict,
84
89
  Singleton,
85
90
  )
@@ -52,7 +52,11 @@ class Abstract(abc.ABC): # noqa
52
52
 
53
53
  super().__init_subclass__(**kwargs)
54
54
 
55
- if not _DISABLE_CHECKS and Abstract not in cls.__bases__:
55
+ if (
56
+ not _DISABLE_CHECKS and
57
+ Abstract not in cls.__bases__ and
58
+ abc.ABC not in cls.__bases__
59
+ ):
56
60
  ams = {a for a, o in cls.__dict__.items() if is_abstract_method(o)}
57
61
  seen = set(cls.__dict__)
58
62
  for b in cls.__bases__:
@@ -0,0 +1,126 @@
1
+ import abc
2
+ import typing as ta
3
+
4
+ from .restrict import NotInstantiable
5
+
6
+
7
+ V = ta.TypeVar('V')
8
+
9
+
10
+ ##
11
+
12
+
13
+ class _NOT_SET: # noqa
14
+ def __new__(cls, *args, **kwargs): # noqa
15
+ raise TypeError
16
+
17
+
18
+ NamespaceCheckValue: ta.TypeAlias = type | tuple[type, ...] | ta.Callable[[ta.Any], bool]
19
+
20
+
21
+ class GenericNamespaceMeta(abc.ABCMeta, ta.Generic[V]):
22
+ __namespace_check_values__: NamespaceCheckValue | None = None
23
+ __namespace_case_insensitive__: bool = False
24
+
25
+ def __init_subclass__(
26
+ mcls,
27
+ *,
28
+ check_values: NamespaceCheckValue | None | type[_NOT_SET] = _NOT_SET,
29
+ case_insensitive: bool | type[_NOT_SET] = _NOT_SET,
30
+ **kwargs,
31
+ ):
32
+ super().__init_subclass__(**kwargs)
33
+
34
+ if check_values is not _NOT_SET:
35
+ mcls.__namespace_check_values__ = check_values
36
+ if case_insensitive is not _NOT_SET:
37
+ mcls.__namespace_case_insensitive__ = case_insensitive # type: ignore
38
+
39
+ __namespace_attrs__: ta.Mapping[str, V]
40
+ __namespace_values__: ta.Mapping[str, V]
41
+
42
+ def __new__(
43
+ mcls,
44
+ name,
45
+ bases,
46
+ namespace,
47
+ *,
48
+ check_values: NamespaceCheckValue | None | type[_NOT_SET] = _NOT_SET,
49
+ case_insensitive: bool | type[_NOT_SET] = _NOT_SET,
50
+ **kwargs,
51
+ ):
52
+ if bases:
53
+ for nc in (NotInstantiable,):
54
+ if nc not in bases:
55
+ bases += (nc,)
56
+
57
+ if check_values is _NOT_SET:
58
+ check_values = mcls.__namespace_check_values__
59
+ if case_insensitive is _NOT_SET:
60
+ case_insensitive = mcls.__namespace_case_insensitive__
61
+
62
+ cls = super().__new__(
63
+ mcls,
64
+ name,
65
+ bases,
66
+ namespace,
67
+ **kwargs,
68
+ )
69
+
70
+ cls.__namespace_check_values__ = check_values
71
+ cls.__namespace_case_insensitive__ = case_insensitive # type: ignore
72
+
73
+ if isinstance(check_values, (type, tuple)):
74
+ cvt = check_values
75
+
76
+ def _cv(o):
77
+ if not isinstance(o, cvt):
78
+ raise TypeError(o, cvt)
79
+ return True
80
+
81
+ check_values = _cv
82
+
83
+ a_dct: dict[str, V] = {}
84
+ v_dct: dict[str, V] = {}
85
+ for b_cls in cls.__mro__[-2::-1]:
86
+ # FIXME: must list() to avoid `RuntimeError: dictionary changed size during iteration`
87
+ for att in list(b_cls.__dict__):
88
+ if att.startswith('_') or att in a_dct:
89
+ continue
90
+
91
+ name = att
92
+ if case_insensitive:
93
+ name = att.lower()
94
+ if name in v_dct:
95
+ raise NameError(f'Ambiguous case-insensitive namespace attr: {name!r}, {att!r}')
96
+
97
+ obj = getattr(cls, att)
98
+ if check_values is not None and not check_values(obj):
99
+ raise ValueError(obj)
100
+
101
+ a_dct[att] = obj
102
+ v_dct[name] = obj
103
+
104
+ cls.__namespace_attrs__ = a_dct
105
+ cls.__namespace_values__ = v_dct
106
+
107
+ return cls
108
+
109
+ def __iter__(cls) -> ta.Iterator[tuple[str, V]]:
110
+ return iter(cls.__namespace_attrs__.items())
111
+
112
+ def __contains__(self, n: str) -> bool:
113
+ return n in self.__namespace_values__
114
+
115
+ def __getitem__(cls, n: str) -> V:
116
+ if cls.__namespace_case_insensitive__:
117
+ n = n.lower()
118
+ return cls.__namespace_values__[n]
119
+
120
+
121
+ class NamespaceMeta(GenericNamespaceMeta[ta.Any]):
122
+ pass
123
+
124
+
125
+ class Namespace(metaclass=NamespaceMeta):
126
+ pass
@@ -25,35 +25,6 @@ class SimpleMetaDict(dict):
25
25
  ##
26
26
 
27
27
 
28
- class _NamespaceMeta(abc.ABCMeta):
29
- def __new__(mcls, name, bases, namespace):
30
- if bases:
31
- for nc in (NotInstantiable,):
32
- if nc not in bases:
33
- bases += (nc,)
34
- return super().__new__(mcls, name, bases, namespace)
35
-
36
- def __iter__(cls) -> ta.Iterator[tuple[str, ta.Any]]:
37
- seen: set[str] = set()
38
- for bcls in reversed(cls.__mro__):
39
- for a in bcls.__dict__:
40
- if a in seen:
41
- continue
42
- seen.add(a)
43
- if not a.startswith('_'):
44
- yield (a, getattr(cls, a))
45
-
46
- def __getitem__(cls, n: str) -> ta.Any:
47
- return getattr(cls, n)
48
-
49
-
50
- class Namespace(metaclass=_NamespaceMeta):
51
- pass
52
-
53
-
54
- ##
55
-
56
-
57
28
  _MARKER_NAMESPACE_KEYS: set[str] | None = None
58
29
 
59
30
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: omlish
3
- Version: 0.0.0.dev319
3
+ Version: 0.0.0.dev321
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -1,5 +1,5 @@
1
1
  omlish/.manifests.json,sha256=orgsRvtpHu8tdhaCvlP9v3P495OJopYYiHKjK68WtWg,8587
2
- omlish/__about__.py,sha256=BUm8C0RUF_mH5RRsEW0hH9yf1ygPXOnka9jzpOJkyck,3478
2
+ omlish/__about__.py,sha256=Z65pxs6rr8SJn-5FRuFMCBItP-Q6fD-WkbO3KD2Q8ao,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
@@ -76,8 +76,9 @@ omlish/codecs/funcs.py,sha256=p4imNt7TobyZVXWC-WhntHVu9KfJrO4QwdtPRh-cVOk,850
76
76
  omlish/codecs/registry.py,sha256=2FnO5YP7ui1LzkguwESY0MP3WIdwgPTIJTM_4RyTOEg,3896
77
77
  omlish/codecs/standard.py,sha256=eiZ4u9ep0XrA4Z_D1zJI0vmWyuN8HLrX4Se_r_Cq_ZM,60
78
78
  omlish/codecs/text.py,sha256=JzrdwMpQPo2NBBg3K1EZszzQy5vEWmd82SIerJd4yeQ,5723
79
- omlish/collections/__init__.py,sha256=YHnllmObi8oL_q3h6SMjim7VaNaABmCGUSIiOh2cF2c,2333
79
+ omlish/collections/__init__.py,sha256=7r4qY9paGL-pC8ZNJn6taod9T2qAyMjIpcL7ptb8GaI,2394
80
80
  omlish/collections/abc.py,sha256=ikTJlJ5dhXjU6tlNsI0Wm0_7GaIEpe3mftpvdGY_nc8,2620
81
+ omlish/collections/bimap.py,sha256=3szDCscPJlFRtkpyVQNWneg4s50mr6Rd0jdTzVEIcnE,1661
81
82
  omlish/collections/coerce.py,sha256=tAls15v_7p5bUN33R7Zbko87KW5toWHl9fRialCqyNY,7030
82
83
  omlish/collections/errors.py,sha256=shcS-NCnEUudF8qC_SmO2TQyjivKlS4TDjaz_faqQ0c,44
83
84
  omlish/collections/frozen.py,sha256=LMbAHYDENIQk1hvjCTvpnx66m1TalrHa4CSn8n_tsXQ,4142
@@ -225,7 +226,7 @@ omlish/dispatch/_dispatch3.py,sha256=9Zjd7bINAC3keiaBdssc4v5dY0-8OI6XooV2DR9U7Z0
225
226
  omlish/dispatch/dispatch.py,sha256=KA5l49AiGLRjp4J7RDJW9RiDp9WUD1ewR1AOPEF8g38,3062
226
227
  omlish/dispatch/functions.py,sha256=cwNzGIg2ZIalEgn9I03cnJVbMTHjWloyDTaowlO3UPs,1524
227
228
  omlish/dispatch/impls.py,sha256=K_okKvpZml4NkTHJmTVyMQSrIaIJcqTEgkreGwukaOw,1895
228
- omlish/dispatch/methods.py,sha256=sSGA52swdrdHEbm_jAPBZVoKP9xMIfVcw2MnTvIJtrI,8913
229
+ omlish/dispatch/methods.py,sha256=GdVsC-Zo3N-OorE0mr3lFI70dATkD2aWqZ8TvExiR5k,9297
229
230
  omlish/docker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
230
231
  omlish/docker/all.py,sha256=xXRgJgLGPwAtr7bDMJ_Dp9jTfOwfGvohNhc6LsoELJc,514
231
232
  omlish/docker/cli.py,sha256=gtb9kitVfGnd4cr587NsVVk8D5Ok5y5SAsqD_SwGrSA,2565
@@ -403,7 +404,7 @@ omlish/iterators/iterators.py,sha256=RxW35yQ5ed8vBQ22IqpDXFx-i5JiLQdp7-pkMZXhJJ8
403
404
  omlish/iterators/recipes.py,sha256=wOwOZg-zWG9Zc3wcAxJFSe2rtavVBYwZOfG09qYEx_4,472
404
405
  omlish/iterators/tools.py,sha256=c4hArZEVV8y9_dFfmRwakusv1cWJLT4MkTkGRjnGN5U,2556
405
406
  omlish/iterators/unique.py,sha256=Nw0pSaNEcHAkve0ugfLPvJcirDOn9ECyC5wIL8JlJKI,1395
406
- omlish/lang/__init__.py,sha256=ZtAmS2HiXPaJexoyPXD2fCl-8DNA4s8zlErlvhU_2o0,6045
407
+ omlish/lang/__init__.py,sha256=FvYmM3q0Z2wYOq0m7DWiksMSYgszdxWrSHDHFetpW_0,6135
407
408
  omlish/lang/attrs.py,sha256=i7euRF81uNF8QDmUVXSK_BtqLGshaMi4VVdUnMjiMwg,5050
408
409
  omlish/lang/casing.py,sha256=cFUlbDdXLhwnWwcYx4qnM5c4zGX7hIRUfcjiZbxUD28,4636
409
410
  omlish/lang/clsdct.py,sha256=HAGIvBSbCefzRjXriwYSBLO7QHKRv2UsE78jixOb-fA,1828
@@ -431,9 +432,10 @@ omlish/lang/cached/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuF
431
432
  omlish/lang/cached/function.py,sha256=tch6VlDljfUUFMP61RY0LYXYyNwj1Sy8CAQQQMHCypA,11344
432
433
  omlish/lang/cached/property.py,sha256=WHYyg4-6EA86TcNMfbXTjVhjEZPc0kngt9hfY3WN5w8,2768
433
434
  omlish/lang/classes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
434
- omlish/lang/classes/abstract.py,sha256=n4rDlDraUKxPF0GtOWEFZ6mEzEDmP7Z8LSI6Jww_thw,3715
435
+ omlish/lang/classes/abstract.py,sha256=A-Jg5X8o_WvFryN0Cm2TpVkrZoTT1SYKQnv_pXjZk7o,3808
436
+ omlish/lang/classes/namespaces.py,sha256=_FBLekx2gNLql1C1ZRlpBtxuLWbcdFEzBm8CrD5XeOA,3589
435
437
  omlish/lang/classes/restrict.py,sha256=nCsQuSFsKTwLhYfmwZr9af00qdVA8TuPQXaSJQNKzBI,3543
436
- omlish/lang/classes/simple.py,sha256=XQ8b86WvQA0qtSYqlbMOJS7tHgE8sv9onda33uQmbkM,3294
438
+ omlish/lang/classes/simple.py,sha256=2C7u8k0K75xzcr6DT8zYd8U-1Yr_Xq1pfF3a0J6wo3g,2538
437
439
  omlish/lang/classes/virtual.py,sha256=z0MYQD9Q5MkX8DzF325wDB4J9XoYbsB09jZ1omC62To,3366
438
440
  omlish/lifecycles/__init__.py,sha256=1FjYceXs-4fc-S-C9zFYmc2axHs4znnQHcJVHdY7a6E,578
439
441
  omlish/lifecycles/abstract.py,sha256=70CQyZy-c9a2o0ZJxPeUT7eYjWZTBrp2HpUBnrHdAOM,1109
@@ -854,9 +856,9 @@ omlish/typedvalues/holder.py,sha256=ZTnHiw-K38ciOBLEdwgrltr7Xp8jjEs_0Lp69DH-G-o,
854
856
  omlish/typedvalues/marshal.py,sha256=hWHRLcrGav7lvXJDtb9bNI0ickl4SKPQ6F4BbTpqw3A,4219
855
857
  omlish/typedvalues/reflect.py,sha256=Ih1YgU-srUjsvBn_P7C66f73_VCvcwqE3ffeBnZBgt4,674
856
858
  omlish/typedvalues/values.py,sha256=ym46I-q2QJ_6l4UlERqv3yj87R-kp8nCKMRph0xQ3UA,1307
857
- omlish-0.0.0.dev319.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
858
- omlish-0.0.0.dev319.dist-info/METADATA,sha256=AJfjWjvSfK3uESd-jYGGUmEgPjkW22rJLSBh3h6hGbk,4416
859
- omlish-0.0.0.dev319.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
860
- omlish-0.0.0.dev319.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
861
- omlish-0.0.0.dev319.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
862
- omlish-0.0.0.dev319.dist-info/RECORD,,
859
+ omlish-0.0.0.dev321.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
860
+ omlish-0.0.0.dev321.dist-info/METADATA,sha256=3uDnP7gAUzMzohJIEtxSwSiVrYaZVYgAnNZdYuqbXTQ,4416
861
+ omlish-0.0.0.dev321.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
862
+ omlish-0.0.0.dev321.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
863
+ omlish-0.0.0.dev321.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
864
+ omlish-0.0.0.dev321.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.8.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5