dycw-utilities 0.110.5__py3-none-any.whl → 0.110.7__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.
- {dycw_utilities-0.110.5.dist-info → dycw_utilities-0.110.7.dist-info}/METADATA +1 -1
- {dycw_utilities-0.110.5.dist-info → dycw_utilities-0.110.7.dist-info}/RECORD +13 -13
- utilities/__init__.py +1 -1
- utilities/eventkit.py +5 -5
- utilities/functions.py +52 -23
- utilities/modules.py +3 -1
- utilities/parse.py +2 -2
- utilities/pyrsistent.py +3 -1
- utilities/redis.py +35 -9
- utilities/types.py +5 -3
- utilities/warnings.py +5 -7
- {dycw_utilities-0.110.5.dist-info → dycw_utilities-0.110.7.dist-info}/WHEEL +0 -0
- {dycw_utilities-0.110.5.dist-info → dycw_utilities-0.110.7.dist-info}/licenses/LICENSE +0 -0
@@ -1,4 +1,4 @@
|
|
1
|
-
utilities/__init__.py,sha256=
|
1
|
+
utilities/__init__.py,sha256=RH75kOPQZPuI3PzW-iy4R8ZfTSbKQHPjZwc14TPFLN8,60
|
2
2
|
utilities/altair.py,sha256=Gpja-flOo-Db0PIPJLJsgzAlXWoKUjPU1qY-DQ829ek,9156
|
3
3
|
utilities/astor.py,sha256=xuDUkjq0-b6fhtwjhbnebzbqQZAjMSHR1IIS5uOodVg,777
|
4
4
|
utilities/asyncio.py,sha256=41oQUurWMvadFK5gFnaG21hMM0Vmfn2WS6OpC0R9mas,14757
|
@@ -15,10 +15,10 @@ utilities/dataclasses.py,sha256=Q197PVnE_vUMn_SNnqJBCo4eRy4bdHtgMHWRbSJPtFk,2667
|
|
15
15
|
utilities/datetime.py,sha256=GOs-MIEW_A49kzqa1yhIoeNeSqqPVgGO-h2AThtgTDk,37326
|
16
16
|
utilities/enum.py,sha256=HoRwVCWzsnH0vpO9ZEcAAIZLMv0Sn2vJxxA4sYMQgDs,5793
|
17
17
|
utilities/errors.py,sha256=BtSNP0JC3ik536ddPyTerLomCRJV9f6kdMe6POz0QHM,361
|
18
|
-
utilities/eventkit.py,sha256=
|
18
|
+
utilities/eventkit.py,sha256=6M5Xu1SzN-juk9PqBHwy5dS-ta7T0qA6SMpDsakOJ0E,13039
|
19
19
|
utilities/fastapi.py,sha256=uwqOGbGwzIbP-lfm-ApG1ZEN3BA_TDsaiuTghhLmxb8,2413
|
20
20
|
utilities/fpdf2.py,sha256=zM3gwOYcAfv7P4qhbyvzPmRY4PPAiAQ-ZnPC6I9SZ1M,1832
|
21
|
-
utilities/functions.py,sha256=
|
21
|
+
utilities/functions.py,sha256=lAJeERNrmcpwon3drcTIlizLVRd8D-gdXojxtKFN0LM,28736
|
22
22
|
utilities/functools.py,sha256=WrpHt7NLNWSUn9A1Q_ZIWlNaYZOEI4IFKyBG9HO3BC4,1643
|
23
23
|
utilities/getpass.py,sha256=DfN5UgMAtFCqS3dSfFHUfqIMZX2shXvwphOz_6J6f6A,103
|
24
24
|
utilities/git.py,sha256=wpt5dZ5Oi5931pN24_VLZYaQOvmR0OcQuVtgHzFUN1k,2359
|
@@ -34,14 +34,14 @@ utilities/loguru.py,sha256=MEMQVWrdECxk1e3FxGzmOf21vWT9j8CAir98SEXFKPA,3809
|
|
34
34
|
utilities/luigi.py,sha256=fpH9MbxJDuo6-k9iCXRayFRtiVbUtibCJKugf7ygpv0,5988
|
35
35
|
utilities/math.py,sha256=TexfvLCI12d9Sw5_W4pKVBZ3nRr3zk2iPkcEU7xdEWU,26771
|
36
36
|
utilities/memory_profiler.py,sha256=tf2C51P2lCujPGvRt2Rfc7VEw5LDXmVPCG3z_AvBmbU,962
|
37
|
-
utilities/modules.py,sha256=
|
37
|
+
utilities/modules.py,sha256=iuvLluJya-hvl1Q25-Jk3dLgx2Es3ck4SjJiEkAlVTs,3195
|
38
38
|
utilities/more_itertools.py,sha256=CPUxrMAcTwRxbzbhiqPKi3Xx9hxqI0t6gkWjutaibGk,5534
|
39
39
|
utilities/numpy.py,sha256=cBgCBet8YfZP_rb4nkCJHZx9_03qPEinVENMk1dGVYQ,25683
|
40
40
|
utilities/operator.py,sha256=0M2yZJ0PODH47ogFEnkGMBe_cfxwZR02T_92LZVZvHo,3715
|
41
41
|
utilities/optuna.py,sha256=loyJGWTzljgdJaoLhP09PT8Jz6o_pwBOwehY33lHkhw,1923
|
42
42
|
utilities/orjson.py,sha256=Wj5pzG_VdgoAy14a7Luhem-BgYrRtRFvvl_POiszRd0,36930
|
43
43
|
utilities/os.py,sha256=D_FyyT-6TtqiN9KSS7c9g1fnUtgxmyMtzAjmYLkk46A,3587
|
44
|
-
utilities/parse.py,sha256=
|
44
|
+
utilities/parse.py,sha256=fki2mnPGa1Ex-aeWiXDkUBHWb7FEk4F6AzMiHjqHXdw,19081
|
45
45
|
utilities/pathlib.py,sha256=31WPMXdLIyXgYOMMl_HOI2wlo66MGSE-cgeelk-Lias,1410
|
46
46
|
utilities/period.py,sha256=ikHXsWtDLr553cfH6p9mMaiCnIAP69B7q84ckWV3HaA,10884
|
47
47
|
utilities/pickle.py,sha256=Bhvd7cZl-zQKQDFjUerqGuSKlHvnW1K2QXeU5UZibtg,657
|
@@ -52,13 +52,13 @@ utilities/pqdm.py,sha256=foRytQybmOQ05pjt5LF7ANyzrIa--4ScDE3T2wd31a4,3118
|
|
52
52
|
utilities/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
53
53
|
utilities/pydantic.py,sha256=f6qtR5mO2YMuyvNmbaEj5YeD9eGA4YYfb7Bjzh9jUs0,1845
|
54
54
|
utilities/pyinstrument.py,sha256=ROq2txPwbe2ZUuYJ2IDNbfT97lu2ca0v5_C_yn6sSlM,800
|
55
|
-
utilities/pyrsistent.py,sha256=
|
55
|
+
utilities/pyrsistent.py,sha256=MoDcAqQGlSNkmlS32DCJLw-cZFAfHB6K9kpox_iyI4k,2512
|
56
56
|
utilities/pytest.py,sha256=85QUax4g2VBBAqAHtM9wekcSLB7_9O8AKFTaCshztL8,7989
|
57
57
|
utilities/pytest_regressions.py,sha256=-SVT9647Dg6-JcdsiaDKXe3NdOmmrvGevLKWwGjxq3c,5088
|
58
58
|
utilities/python_dotenv.py,sha256=6viKAI7zx9YQU2ewITaOcad7wMwkrf6FbYpBmCl4vCA,3170
|
59
59
|
utilities/random.py,sha256=lYdjgxB7GCfU_fwFVl5U-BIM_HV3q6_urL9byjrwDM8,4157
|
60
60
|
utilities/re.py,sha256=5J4d8VwIPFVrX2Eb8zfoxImDv7IwiN_U7mJ07wR2Wvs,3958
|
61
|
-
utilities/redis.py,sha256=
|
61
|
+
utilities/redis.py,sha256=fAUbfOlCmxcxhh47PXQX63w0CU5iOFKfdUJ7jDn9ntM,22096
|
62
62
|
utilities/reprlib.py,sha256=Re9bk3n-kC__9DxQmRlevqFA86pE6TtVfWjUgpbVOv0,1849
|
63
63
|
utilities/rich.py,sha256=t50MwwVBsoOLxzmeVFSVpjno4OW6Ufum32skXbV8-Bs,1911
|
64
64
|
utilities/scipy.py,sha256=X6ROnHwiUhAmPhM0jkfEh0-Fd9iRvwiqtCQMOLmOQF8,945
|
@@ -77,17 +77,17 @@ utilities/text.py,sha256=hfcBKF22fKT6s_U-ZdP-g5TjFQ0-NrIrQdvIwERWT80,10971
|
|
77
77
|
utilities/threading.py,sha256=GvBOp4CyhHfN90wGXZuA2VKe9fGzMaEa7oCl4f3nnPU,1009
|
78
78
|
utilities/timer.py,sha256=Rkc49KSpHuC8s7vUxGO9DU55U9I6yDKnchsQqrUCVBs,4075
|
79
79
|
utilities/traceback.py,sha256=KwHPLdEbdj0fFhXo8MBfxcvem8A-VXYDwFMNJ6f0cTM,27328
|
80
|
-
utilities/types.py,sha256=
|
80
|
+
utilities/types.py,sha256=kVY71hZkcnyYNIlYSse0mLm8yeP3OBkzhDPMME6jXxo,18126
|
81
81
|
utilities/typing.py,sha256=gLg4EbE1FX52fJ1d3ji4i08qolwu9qgWt8w_w_Y5DTk,5512
|
82
82
|
utilities/tzdata.py,sha256=2ZsPmhTVM9Ptrxb4QrWKtKOB9RiH8IOO-A1u7ULdVbg,176
|
83
83
|
utilities/tzlocal.py,sha256=42BCquGF54oIqIKe5RGziP4K8Nbm3Ey7uqcNn6m5ge8,534
|
84
84
|
utilities/uuid.py,sha256=jJTFxz-CWgltqNuzmythB7iEQ-Q1mCwPevUfKthZT3c,611
|
85
85
|
utilities/version.py,sha256=QFuyEeQA6jI0ruBEcmhqG36f-etg1AEiD1drBBqhQrs,5358
|
86
|
-
utilities/warnings.py,sha256=
|
86
|
+
utilities/warnings.py,sha256=un1LvHv70PU-LLv8RxPVmugTzDJkkGXRMZTE2-fTQHw,1771
|
87
87
|
utilities/whenever.py,sha256=TjoTAJ1R27-rKXiXzdE4GzPidmYqm0W58XydDXp-QZM,17786
|
88
88
|
utilities/zipfile.py,sha256=24lQc9ATcJxHXBPc_tBDiJk48pWyRrlxO2fIsFxU0A8,699
|
89
89
|
utilities/zoneinfo.py,sha256=-DQz5a0Ikw9jfSZtL0BEQkXOMC9yGn_xiJYNCLMiqEc,1989
|
90
|
-
dycw_utilities-0.110.
|
91
|
-
dycw_utilities-0.110.
|
92
|
-
dycw_utilities-0.110.
|
93
|
-
dycw_utilities-0.110.
|
90
|
+
dycw_utilities-0.110.7.dist-info/METADATA,sha256=wFw9aZuOwiyPR1o4QtTmz5fPx9y5gBbKheuvV0XKhA8,13004
|
91
|
+
dycw_utilities-0.110.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
92
|
+
dycw_utilities-0.110.7.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
|
93
|
+
dycw_utilities-0.110.7.dist-info/RECORD,,
|
utilities/__init__.py
CHANGED
utilities/eventkit.py
CHANGED
@@ -39,7 +39,7 @@ from eventkit import (
|
|
39
39
|
from utilities.functions import apply_decorators
|
40
40
|
from utilities.iterables import always_iterable
|
41
41
|
from utilities.logging import get_logger
|
42
|
-
from utilities.types import TCallable, TCallableMaybeCoroutine1None
|
42
|
+
from utilities.types import TCallable, TCallableMaybeCoroutine1None, TypeLike
|
43
43
|
|
44
44
|
if TYPE_CHECKING:
|
45
45
|
from collections.abc import Callable
|
@@ -59,7 +59,7 @@ def add_listener(
|
|
59
59
|
/,
|
60
60
|
*,
|
61
61
|
error: Callable[[Event, BaseException], MaybeCoroutine1[None]] | None = None,
|
62
|
-
ignore:
|
62
|
+
ignore: TypeLike[BaseException] | None = None,
|
63
63
|
logger: LoggerOrName | None = None,
|
64
64
|
decorators: MaybeIterable[Callable[[TCallable], TCallable]] | None = None,
|
65
65
|
done: Callable[..., MaybeCoroutine1[None]] | None = None,
|
@@ -104,7 +104,7 @@ class LiftedEvent(Generic[TCallableMaybeCoroutine1None]):
|
|
104
104
|
/,
|
105
105
|
*,
|
106
106
|
error: Callable[[Event, BaseException], MaybeCoroutine1[None]] | None = None,
|
107
|
-
ignore:
|
107
|
+
ignore: TypeLike[BaseException] | None = None,
|
108
108
|
logger: LoggerOrName | None = None,
|
109
109
|
decorators: MaybeIterable[Callable[[TCallable], TCallable]] | None = None,
|
110
110
|
done: Callable[..., MaybeCoroutine1[None]] | None = None,
|
@@ -267,7 +267,7 @@ class TypedEvent(Event, Generic[TCallableMaybeCoroutine1None]):
|
|
267
267
|
done: Callable[[Self], MaybeCoroutine1[None]] | None = None,
|
268
268
|
keep_ref: bool = False,
|
269
269
|
*,
|
270
|
-
ignore:
|
270
|
+
ignore: TypeLike[BaseException] | None = None,
|
271
271
|
logger: LoggerOrName | None = None,
|
272
272
|
decorators: MaybeIterable[Callable[[TCallable], TCallable]] | None = None,
|
273
273
|
) -> Self:
|
@@ -295,7 +295,7 @@ def lift_listener(
|
|
295
295
|
/,
|
296
296
|
*,
|
297
297
|
error: Callable[[Event, BaseException], MaybeCoroutine1[None]] | None = None,
|
298
|
-
ignore:
|
298
|
+
ignore: TypeLike[BaseException] | None = None,
|
299
299
|
logger: LoggerOrName | None = None,
|
300
300
|
decorators: MaybeIterable[Callable[[TCallable], TCallable]] | None = None,
|
301
301
|
) -> Callable[..., MaybeCoroutine1[None]]:
|
utilities/functions.py
CHANGED
@@ -22,6 +22,7 @@ from typing import (
|
|
22
22
|
Literal,
|
23
23
|
TypeGuard,
|
24
24
|
TypeVar,
|
25
|
+
assert_never,
|
25
26
|
cast,
|
26
27
|
overload,
|
27
28
|
override,
|
@@ -40,6 +41,7 @@ from utilities.types import (
|
|
40
41
|
TCallable2,
|
41
42
|
TSupportsRichComparison,
|
42
43
|
TupleOrStrMapping,
|
44
|
+
TypeLike,
|
43
45
|
)
|
44
46
|
|
45
47
|
if TYPE_CHECKING:
|
@@ -181,9 +183,9 @@ def ensure_class(
|
|
181
183
|
*,
|
182
184
|
nullable: Literal[False] = False,
|
183
185
|
) -> _T1 | _T2 | _T3 | _T4 | _T5: ...
|
184
|
-
|
185
|
-
|
186
|
-
) -> Any:
|
186
|
+
@overload
|
187
|
+
def ensure_class(obj: Any, cls: TypeLike[_T], /, *, nullable: bool = False) -> Any: ...
|
188
|
+
def ensure_class(obj: Any, cls: TypeLike[_T], /, *, nullable: bool = False) -> Any:
|
187
189
|
"""Ensure an object is of the required class."""
|
188
190
|
if isinstance(obj, cls) or ((obj is None) and nullable):
|
189
191
|
return obj
|
@@ -193,7 +195,7 @@ def ensure_class(
|
|
193
195
|
@dataclass(kw_only=True, slots=True)
|
194
196
|
class EnsureClassError(Exception):
|
195
197
|
obj: Any
|
196
|
-
cls:
|
198
|
+
cls: TypeLike[Any]
|
197
199
|
nullable: bool
|
198
200
|
|
199
201
|
@override
|
@@ -658,9 +660,23 @@ def is_hashable(obj: Any, /) -> TypeGuard[Hashable]:
|
|
658
660
|
##
|
659
661
|
|
660
662
|
|
661
|
-
def
|
662
|
-
|
663
|
-
|
663
|
+
def is_instance_not_bool_int(
|
664
|
+
obj: Any, class_or_tuple: TypeLike[Any], /
|
665
|
+
) -> TypeGuard[int]:
|
666
|
+
"""Check if an instance relationship holds, except bool<int."""
|
667
|
+
match class_or_tuple:
|
668
|
+
case type() as type_:
|
669
|
+
return _is_instance_not_bool_int(obj, type_)
|
670
|
+
case tuple() as types:
|
671
|
+
return any(_is_instance_not_bool_int(obj, p) for p in types)
|
672
|
+
case _ as never:
|
673
|
+
assert_never(never)
|
674
|
+
|
675
|
+
|
676
|
+
def _is_instance_not_bool_int(obj: Any, type_: type[Any], /) -> bool:
|
677
|
+
return isinstance(obj, type_) and not (
|
678
|
+
isinstance(obj, bool) and issubclass(type_, int) and not issubclass(type_, bool)
|
679
|
+
)
|
664
680
|
|
665
681
|
|
666
682
|
##
|
@@ -686,7 +702,9 @@ def is_iterable_of(
|
|
686
702
|
def is_iterable_of(
|
687
703
|
obj: Any, cls: tuple[type[_T1], type[_T2], type[_T3], type[_T4], type[_T5]], /
|
688
704
|
) -> TypeGuard[Iterable[_T1 | _T2 | _T3 | _T4 | _T5]]: ...
|
689
|
-
|
705
|
+
@overload
|
706
|
+
def is_iterable_of(obj: Any, cls: TypeLike[_T], /) -> TypeGuard[Iterable[_T]]: ...
|
707
|
+
def is_iterable_of(obj: Any, cls: TypeLike[_T], /) -> TypeGuard[Iterable[_T]]:
|
690
708
|
"""Check if an object is a iterable of tuple or string mappings."""
|
691
709
|
return isinstance(obj, Iterable) and all(map(make_isinstance(cls), obj))
|
692
710
|
|
@@ -730,7 +748,9 @@ def is_sequence_of(
|
|
730
748
|
def is_sequence_of(
|
731
749
|
obj: Any, cls: tuple[type[_T1], type[_T2], type[_T3], type[_T4], type[_T5]], /
|
732
750
|
) -> TypeGuard[Sequence[_T1 | _T2 | _T3 | _T4 | _T5]]: ...
|
733
|
-
|
751
|
+
@overload
|
752
|
+
def is_sequence_of(obj: Any, cls: TypeLike[_T], /) -> TypeGuard[Sequence[_T]]: ...
|
753
|
+
def is_sequence_of(obj: Any, cls: TypeLike[_T], /) -> TypeGuard[Sequence[_T]]:
|
734
754
|
"""Check if an object is a sequence of tuple or string mappings."""
|
735
755
|
return isinstance(obj, Sequence) and is_iterable_of(obj, cls)
|
736
756
|
|
@@ -776,9 +796,23 @@ def is_string_mapping(obj: Any, /) -> TypeGuard[StrMapping]:
|
|
776
796
|
##
|
777
797
|
|
778
798
|
|
779
|
-
def
|
780
|
-
"""Check if a
|
781
|
-
|
799
|
+
def is_subclass_not_bool_int(cls: type[Any], class_or_tuple: TypeLike[Any], /) -> bool:
|
800
|
+
"""Check if a subclass relationship holds, except bool<int."""
|
801
|
+
match class_or_tuple:
|
802
|
+
case type() as parent:
|
803
|
+
return _is_subclass_int_not_bool_one(cls, parent)
|
804
|
+
case tuple() as parents:
|
805
|
+
return any(_is_subclass_int_not_bool_one(cls, p) for p in parents)
|
806
|
+
case _ as never:
|
807
|
+
assert_never(never)
|
808
|
+
|
809
|
+
|
810
|
+
def _is_subclass_int_not_bool_one(cls: type[Any], parent: type[Any], /) -> bool:
|
811
|
+
return issubclass(cls, parent) and not (
|
812
|
+
issubclass(cls, bool)
|
813
|
+
and issubclass(parent, int)
|
814
|
+
and not issubclass(parent, bool)
|
815
|
+
)
|
782
816
|
|
783
817
|
|
784
818
|
##
|
@@ -820,19 +854,14 @@ def make_isinstance(
|
|
820
854
|
def make_isinstance(
|
821
855
|
cls: tuple[type[_T1], type[_T2], type[_T3], type[_T4], type[_T5]], /
|
822
856
|
) -> Callable[[Any], TypeGuard[_T1 | _T2 | _T3 | _T4 | _T5]]: ...
|
823
|
-
|
824
|
-
|
825
|
-
) -> Callable[[Any], TypeGuard[
|
857
|
+
@overload
|
858
|
+
def make_isinstance(cls: TypeLike[_T], /) -> Callable[[Any], TypeGuard[_T]]: ...
|
859
|
+
def make_isinstance(cls: TypeLike[_T], /) -> Callable[[Any], TypeGuard[_T]]:
|
826
860
|
"""Make a curried `isinstance` function."""
|
827
861
|
return partial(_make_instance_core, cls=cls)
|
828
862
|
|
829
863
|
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
def _make_instance_core(
|
834
|
-
obj: Any, /, *, cls: type[_T] | tuple[type[_T], ...]
|
835
|
-
) -> TypeGuard[_T]:
|
864
|
+
def _make_instance_core(obj: Any, /, *, cls: TypeLike[_T]) -> TypeGuard[_T]:
|
836
865
|
return isinstance(obj, cls)
|
837
866
|
|
838
867
|
|
@@ -1046,7 +1075,7 @@ __all__ = [
|
|
1046
1075
|
"is_dataclass_class",
|
1047
1076
|
"is_dataclass_instance",
|
1048
1077
|
"is_hashable",
|
1049
|
-
"
|
1078
|
+
"is_instance_not_bool_int",
|
1050
1079
|
"is_iterable_of",
|
1051
1080
|
"is_none",
|
1052
1081
|
"is_not_none",
|
@@ -1054,7 +1083,7 @@ __all__ = [
|
|
1054
1083
|
"is_sized",
|
1055
1084
|
"is_sized_not_str",
|
1056
1085
|
"is_string_mapping",
|
1057
|
-
"
|
1086
|
+
"is_subclass_not_bool_int",
|
1058
1087
|
"is_tuple",
|
1059
1088
|
"is_tuple_or_str_mapping",
|
1060
1089
|
"make_isinstance",
|
utilities/modules.py
CHANGED
@@ -11,6 +11,8 @@ if TYPE_CHECKING:
|
|
11
11
|
from collections.abc import Callable, Iterable, Iterator
|
12
12
|
from types import ModuleType
|
13
13
|
|
14
|
+
from utilities.types import TypeLike
|
15
|
+
|
14
16
|
|
15
17
|
def is_installed(module: str, /) -> bool:
|
16
18
|
"""Check if a module is installed."""
|
@@ -63,7 +65,7 @@ def yield_module_contents(
|
|
63
65
|
*,
|
64
66
|
missing_ok: Iterable[str] | None = None,
|
65
67
|
recursive: bool = False,
|
66
|
-
type:
|
68
|
+
type: TypeLike[Any] | None = None, # noqa: A002
|
67
69
|
predicate: Callable[[Any], bool] | None = None,
|
68
70
|
) -> Iterator[Any]:
|
69
71
|
"""Yield all the module contents under a package.
|
utilities/parse.py
CHANGED
@@ -14,7 +14,7 @@ from utilities.datetime import (
|
|
14
14
|
is_subclass_date_not_datetime,
|
15
15
|
)
|
16
16
|
from utilities.enum import ParseEnumError, parse_enum
|
17
|
-
from utilities.functions import
|
17
|
+
from utilities.functions import is_subclass_not_bool_int
|
18
18
|
from utilities.iterables import OneEmptyError, OneNonUniqueError, one, one_str
|
19
19
|
from utilities.math import ParseNumberError, parse_number
|
20
20
|
from utilities.re import ExtractGroupError, extract_group
|
@@ -174,7 +174,7 @@ def _parse_object_type(
|
|
174
174
|
return parse_bool(text)
|
175
175
|
except ParseBoolError:
|
176
176
|
raise _ParseObjectParseError(type_=cls, text=text) from None
|
177
|
-
if
|
177
|
+
if is_subclass_not_bool_int(cls, int):
|
178
178
|
try:
|
179
179
|
return int(text)
|
180
180
|
except ValueError:
|
utilities/pyrsistent.py
CHANGED
@@ -15,6 +15,8 @@ from pyrsistent._field_common import (
|
|
15
15
|
if TYPE_CHECKING:
|
16
16
|
from collections.abc import Callable
|
17
17
|
|
18
|
+
from utilities.types import TypeLike
|
19
|
+
|
18
20
|
|
19
21
|
_T = TypeVar("_T")
|
20
22
|
_U = TypeVar("_U")
|
@@ -62,7 +64,7 @@ def field(
|
|
62
64
|
) -> Any: ...
|
63
65
|
def field(
|
64
66
|
*,
|
65
|
-
type:
|
67
|
+
type: TypeLike[_T] = PFIELD_NO_TYPE, # noqa: A002
|
66
68
|
invariant: Callable[[Any], tuple[bool, Any]] = PFIELD_NO_INVARIANT,
|
67
69
|
default: Any = PFIELD_NO_INITIAL,
|
68
70
|
mandatory: bool = False,
|
utilities/redis.py
CHANGED
@@ -42,7 +42,7 @@ if TYPE_CHECKING:
|
|
42
42
|
from redis.typing import ResponseT
|
43
43
|
|
44
44
|
from utilities.iterables import MaybeIterable
|
45
|
-
from utilities.types import Duration
|
45
|
+
from utilities.types import Duration, TypeLike
|
46
46
|
|
47
47
|
|
48
48
|
_K = TypeVar("_K")
|
@@ -69,9 +69,9 @@ class RedisHashMapKey(Generic[_K, _V]):
|
|
69
69
|
"""A hashmap key in a redis store."""
|
70
70
|
|
71
71
|
name: str
|
72
|
-
key:
|
72
|
+
key: TypeLike[_K]
|
73
73
|
key_serializer: Callable[[_K], bytes] | None = None
|
74
|
-
value:
|
74
|
+
value: TypeLike[_V]
|
75
75
|
value_serializer: Callable[[_V], bytes] | None = None
|
76
76
|
value_deserializer: Callable[[bytes], _V] | None = None
|
77
77
|
timeout: Duration | None = None
|
@@ -262,10 +262,24 @@ def redis_hash_map_key(
|
|
262
262
|
error: type[Exception] = TimeoutError,
|
263
263
|
ttl: Duration | None = None,
|
264
264
|
) -> RedisHashMapKey[_K1 | _K2 | _K3, _V1 | _V2 | _V3]: ...
|
265
|
+
@overload
|
266
|
+
def redis_hash_map_key(
|
267
|
+
name: str,
|
268
|
+
key: TypeLike[_K],
|
269
|
+
value: TypeLike[_V],
|
270
|
+
/,
|
271
|
+
*,
|
272
|
+
key_serializer: Callable[[_K1 | _K2 | _K3], bytes] | None = None,
|
273
|
+
value_serializer: Callable[[_V1 | _V2 | _V3], bytes] | None = None,
|
274
|
+
value_deserializer: Callable[[bytes], _V1 | _V2 | _V3] | None = None,
|
275
|
+
timeout: Duration | None = None,
|
276
|
+
error: type[Exception] = TimeoutError,
|
277
|
+
ttl: Duration | None = None,
|
278
|
+
) -> RedisHashMapKey[_K, _V]: ...
|
265
279
|
def redis_hash_map_key(
|
266
280
|
name: str,
|
267
|
-
key:
|
268
|
-
value:
|
281
|
+
key: TypeLike[_K],
|
282
|
+
value: TypeLike[_V],
|
269
283
|
/,
|
270
284
|
*,
|
271
285
|
key_serializer: Callable[[Any], bytes] | None = None,
|
@@ -274,7 +288,7 @@ def redis_hash_map_key(
|
|
274
288
|
timeout: Duration | None = None,
|
275
289
|
ttl: Duration | None = None,
|
276
290
|
error: type[Exception] = TimeoutError,
|
277
|
-
) -> RedisHashMapKey[
|
291
|
+
) -> RedisHashMapKey[_K, _V]:
|
278
292
|
"""Create a redis key."""
|
279
293
|
return RedisHashMapKey( # skipif-ci-and-not-linux
|
280
294
|
name=name,
|
@@ -297,7 +311,7 @@ class RedisKey(Generic[_T]):
|
|
297
311
|
"""A key in a redis store."""
|
298
312
|
|
299
313
|
name: str
|
300
|
-
type:
|
314
|
+
type: TypeLike[_T]
|
301
315
|
serializer: Callable[[_T], bytes] | None = None
|
302
316
|
deserializer: Callable[[bytes], _T] | None = None
|
303
317
|
timeout: Duration | None = None
|
@@ -420,9 +434,21 @@ def redis_key(
|
|
420
434
|
error: type[Exception] = TimeoutError,
|
421
435
|
ttl: Duration | None = None,
|
422
436
|
) -> RedisKey[_T1 | _T2 | _T3 | _T4 | _T5]: ...
|
437
|
+
@overload
|
438
|
+
def redis_key(
|
439
|
+
name: str,
|
440
|
+
type_: TypeLike[_T],
|
441
|
+
/,
|
442
|
+
*,
|
443
|
+
serializer: Callable[[_T1 | _T2 | _T3 | _T4 | _T5], bytes] | None = None,
|
444
|
+
deserializer: Callable[[bytes], _T1 | _T2 | _T3 | _T4 | _T5] | None = None,
|
445
|
+
timeout: Duration | None = None,
|
446
|
+
error: type[Exception] = TimeoutError,
|
447
|
+
ttl: Duration | None = None,
|
448
|
+
) -> RedisKey[_T]: ...
|
423
449
|
def redis_key(
|
424
450
|
name: str,
|
425
|
-
type_:
|
451
|
+
type_: TypeLike[_T],
|
426
452
|
/,
|
427
453
|
*,
|
428
454
|
serializer: Callable[[Any], bytes] | None = None,
|
@@ -430,7 +456,7 @@ def redis_key(
|
|
430
456
|
timeout: Duration | None = None,
|
431
457
|
error: type[Exception] = TimeoutError,
|
432
458
|
ttl: Duration | None = None,
|
433
|
-
) -> RedisKey[
|
459
|
+
) -> RedisKey[_T]:
|
434
460
|
"""Create a redis key."""
|
435
461
|
return RedisKey( # skipif-ci-and-not-linux
|
436
462
|
name=name,
|
utilities/types.py
CHANGED
@@ -45,12 +45,13 @@ type OpenMode = Literal[
|
|
45
45
|
"x+b",
|
46
46
|
"a+b",
|
47
47
|
]
|
48
|
-
type StrMapping = Mapping[str, Any]
|
49
|
-
type StrStrMapping = Mapping[str, str]
|
50
|
-
type TupleOrStrMapping = tuple[Any, ...] | StrMapping
|
51
48
|
type MaybeCallable[_T] = _T | Callable[[], _T]
|
52
49
|
type MaybeStr[_T] = _T | str
|
53
50
|
type MaybeType[_T] = _T | type[_T]
|
51
|
+
type StrMapping = Mapping[str, Any]
|
52
|
+
type StrStrMapping = Mapping[str, str]
|
53
|
+
type TypeLike[_T] = type[_T] | tuple[type[_T], ...]
|
54
|
+
type TupleOrStrMapping = tuple[Any, ...] | StrMapping
|
54
55
|
|
55
56
|
|
56
57
|
# asyncio
|
@@ -327,5 +328,6 @@ __all__ = [
|
|
327
328
|
"TimeZone",
|
328
329
|
"TimeZoneLike",
|
329
330
|
"TupleOrStrMapping",
|
331
|
+
"TypeLike",
|
330
332
|
"WeekDay",
|
331
333
|
]
|
utilities/warnings.py
CHANGED
@@ -7,12 +7,12 @@ from warnings import catch_warnings, filterwarnings
|
|
7
7
|
if TYPE_CHECKING:
|
8
8
|
from collections.abc import Iterator
|
9
9
|
|
10
|
+
from utilities.types import TypeLike
|
11
|
+
|
10
12
|
|
11
13
|
@contextmanager
|
12
14
|
def catch_warnings_as_errors(
|
13
|
-
*,
|
14
|
-
message: str = "",
|
15
|
-
category: type[Warning] | tuple[type[Warning], ...] | None = None,
|
15
|
+
*, message: str = "", category: TypeLike[Warning] | None = None
|
16
16
|
) -> Iterator[None]:
|
17
17
|
"""Catch warnings as errors."""
|
18
18
|
with _handle_warnings("error", message=message, category=category):
|
@@ -21,9 +21,7 @@ def catch_warnings_as_errors(
|
|
21
21
|
|
22
22
|
@contextmanager
|
23
23
|
def suppress_warnings(
|
24
|
-
*,
|
25
|
-
message: str = "",
|
26
|
-
category: type[Warning] | tuple[type[Warning], ...] | None = None,
|
24
|
+
*, message: str = "", category: TypeLike[Warning] | None = None
|
27
25
|
) -> Iterator[None]:
|
28
26
|
"""Suppress warnings."""
|
29
27
|
with _handle_warnings("ignore", message=message, category=category):
|
@@ -38,7 +36,7 @@ def _handle_warnings(
|
|
38
36
|
/,
|
39
37
|
*,
|
40
38
|
message: str = "",
|
41
|
-
category:
|
39
|
+
category: TypeLike[Warning] | None = None,
|
42
40
|
) -> ExitStack:
|
43
41
|
"""Handle a set of warnings."""
|
44
42
|
stack = ExitStack()
|
File without changes
|
File without changes
|