omlish 0.0.0.dev338__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 CHANGED
@@ -1,5 +1,5 @@
1
- __version__ = '0.0.0.dev338'
2
- __revision__ = '8d983648c5770796c8addb2cf217a0d7235a9b29'
1
+ __version__ = '0.0.0.dev339'
2
+ __revision__ = '0d8d4714d9a9ea7145586e0bce55833b86e980bd'
3
3
 
4
4
 
5
5
  #
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__))
@@ -3,6 +3,7 @@ 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
9
  import typing as ta
@@ -121,6 +122,7 @@ class SwitchesPlugin:
121
122
  def pytest_sessionstart(self, session):
122
123
  session.stash[self._states_key] = self._States(session)
123
124
 
125
+ @pytest.hookimpl(tryfirst=True)
124
126
  def pytest_collection_modifyitems(self, config, items):
125
127
  def process_item(item):
126
128
  state: SwitchesPlugin._States = item.session.stash[self._states_key]
@@ -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(module: str, *args, **kwargs):
15
- return pytest.mark.skipif(not lang.can_import(module, *args, **kwargs), reason=f'requires import {module}')
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')
@@ -22,6 +22,10 @@ from .holder import ( # noqa
22
22
  TypedValueHolder,
23
23
  )
24
24
 
25
+ from .of_ import ( # noqa
26
+ of,
27
+ )
28
+
25
29
  from .reflect import ( # noqa
26
30
  reflect_typed_values_impls,
27
31
  )
@@ -27,7 +27,11 @@ class _NOT_SET(lang.Marker): # noqa
27
27
  pass
28
28
 
29
29
 
30
- class TypedValuesAccessor(lang.Abstract, ta.Sequence[TypedValueT0]):
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.',
@@ -10,6 +10,7 @@ from .values import UniqueTypedValue
10
10
 
11
11
 
12
12
  TypedValueT = ta.TypeVar('TypedValueT', bound='TypedValue')
13
+ TypedValueU = ta.TypeVar('TypedValueU', bound='TypedValue')
13
14
 
14
15
  UniqueTypedValueT = ta.TypeVar('UniqueTypedValueT', bound='UniqueTypedValue')
15
16
 
@@ -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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: omlish
3
- Version: 0.0.0.dev338
3
+ Version: 0.0.0.dev339
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=p63JDbIzq9Uyt4DamGvFNixWASVUZ_s5JryuZGRCE5I,3478
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=YuPEZ3sIP6q5gGbISbQQ_CsOU5Zlu_IXHqxjO7muI-4,6251
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
@@ -743,7 +745,7 @@ omlish/testing/testing.py,sha256=zmBHw5gw1ZUUcDYC0uonSThjhRn0HNuorjpo0jLvju8,288
743
745
  omlish/testing/pytest/__init__.py,sha256=i4ti6Q2rVYJ-XBk9UYDfUUagCrEDTC5jOeSykBjYYZQ,234
744
746
  omlish/testing/pytest/helpers.py,sha256=HxiKvpJQ4b6WCiQXOqQTqKbmr7CMAgCF6hViT6pfIuw,202
745
747
  omlish/testing/pytest/marks.py,sha256=qhVnq-3LlQ5uRLS1LXYkh8Xk-8aQGOgs2Nr49T8YqOA,280
746
- omlish/testing/pytest/skip.py,sha256=imDrBhQKQkEmStaSn0Js-zsfyKMPmNod-mW1ANdIhak,989
748
+ omlish/testing/pytest/skip.py,sha256=tra8FM5CZTh4M7ZWVf9YPmKUX4yhesf61XRoIkO4s9c,954
747
749
  omlish/testing/pytest/inject/__init__.py,sha256=pdRKv1HcDmJ_yArKJbYITPXXZthRSGgBJWqITr0Er38,117
748
750
  omlish/testing/pytest/inject/harness.py,sha256=_Qf7lLcYc_dpauYOE68u_a65jPCFWmQUYv9m_OOdNqs,5724
749
751
  omlish/testing/pytest/plugins/__init__.py,sha256=ys1zXrYrNm7Uo6YOIVJ6Bd3dQo6kv387k7MbTYlqZSI,467
@@ -767,7 +769,7 @@ omlish/testing/pytest/plugins/asyncs/backends/base.py,sha256=fTZ6R_iKpAp-8DVw8js
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
769
771
  omlish/testing/pytest/plugins/switches/__init__.py,sha256=KTdm9xe8AYQvNT-IKSGr9O8q_hgRGEqhK3zcto0EbWk,43
770
- omlish/testing/pytest/plugins/switches/plugin.py,sha256=kHHXpawEgyDMzvcLgfdYBUhcCML2xAo9sdJ6611sm-M,5744
772
+ omlish/testing/pytest/plugins/switches/plugin.py,sha256=RBxjefl9RDJuSmT_W0lTSd9DlAT-nkyy_U2fBYzdWNs,5835
771
773
  omlish/testing/pytest/plugins/switches/switches.py,sha256=lj8S9RMwUAW7a93ZqqTjoD4dRVkeGts2sl8Cn-H17hc,1890
772
774
  omlish/text/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
773
775
  omlish/text/asdl.py,sha256=AS3irh-sag5pqyH3beJif78PjCbOaFso1NeKq-HXuTs,16867
@@ -852,18 +854,19 @@ omlish/text/antlr/_runtime/xpath/XPathLexer.py,sha256=WvGKQjQnu7pX5C4CFKtsCzba2B
852
854
  omlish/text/antlr/_runtime/xpath/__init__.py,sha256=lMd_BbXYdlDhZQN_q0TKN978XW5G0pq618F0NaLkpFE,71
853
855
  omlish/text/go/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
854
856
  omlish/text/go/quoting.py,sha256=N9EYdnFdEX_A8fOviH-1w4jwV3XOQ7VU2WsoUNubYVY,9137
855
- omlish/typedvalues/__init__.py,sha256=nzpnoRW_wScMPit5Xz37ky3nKBdzzkgtnQA4SfVHN8E,684
856
- omlish/typedvalues/accessor.py,sha256=_NEGBmQ84-h_rDfYeoq7DA20fhj3dogQuvzxXKhjx54,3121
857
- omlish/typedvalues/collection.py,sha256=TjNuEEyTXbGfbsk7nvBB_Jhgz94R5JSs0u6ocNAlj3Y,5511
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
858
860
  omlish/typedvalues/consumer.py,sha256=peDQAgriSyBx_Hc8QHAhEgYy0oSS52qQ_7Tqdssl2AE,4375
859
861
  omlish/typedvalues/generic.py,sha256=ft-x4X3k1oFirtYnDfsvrI3ZQikWM8lGLrvrOEbcGq0,742
860
862
  omlish/typedvalues/holder.py,sha256=vu-umn-h1nvUqmtV5T9ZfQ_OoOYsERu8PhI2N48Ryns,1133
861
863
  omlish/typedvalues/marshal.py,sha256=AtBz7Jq-BfW8vwM7HSxSpR85JAXmxK2T0xDblmm1HI0,4956
864
+ omlish/typedvalues/of_.py,sha256=UXkxSj504WI2UrFlqdZJbu2hyDwBhL7XVrc2qdR02GQ,1309
862
865
  omlish/typedvalues/reflect.py,sha256=PAvKW6T4cW7u--iX80w3HWwZUS3SmIZ2_lQjT65uAyk,1026
863
866
  omlish/typedvalues/values.py,sha256=ym46I-q2QJ_6l4UlERqv3yj87R-kp8nCKMRph0xQ3UA,1307
864
- omlish-0.0.0.dev338.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
865
- omlish-0.0.0.dev338.dist-info/METADATA,sha256=ZPnPJxCXqfpdEK-ad8rFWYgxjkUBGLj97TEUYcPQ6dc,4416
866
- omlish-0.0.0.dev338.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
867
- omlish-0.0.0.dev338.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
868
- omlish-0.0.0.dev338.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
869
- omlish-0.0.0.dev338.dist-info/RECORD,,
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,,