dycw-utilities 0.132.2__py3-none-any.whl → 0.132.4__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.132.2.dist-info → dycw_utilities-0.132.4.dist-info}/METADATA +1 -2
- {dycw_utilities-0.132.2.dist-info → dycw_utilities-0.132.4.dist-info}/RECORD +8 -9
- utilities/__init__.py +1 -1
- utilities/click.py +58 -0
- utilities/parse.py +13 -8
- utilities/types.py +8 -0
- utilities/pyrsistent.py +0 -89
- {dycw_utilities-0.132.2.dist-info → dycw_utilities-0.132.4.dist-info}/WHEEL +0 -0
- {dycw_utilities-0.132.2.dist-info → dycw_utilities-0.132.4.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: dycw-utilities
|
3
|
-
Version: 0.132.
|
3
|
+
Version: 0.132.4
|
4
4
|
Author-email: Derek Wan <d.wan@icloud.com>
|
5
5
|
License-File: LICENSE
|
6
6
|
Requires-Python: >=3.12
|
@@ -17,7 +17,6 @@ Requires-Dist: pytest-asyncio<1.1,>=1.0.0; extra == 'test'
|
|
17
17
|
Requires-Dist: pytest-cov<6.2,>=6.1.1; extra == 'test'
|
18
18
|
Requires-Dist: pytest-instafail<0.6,>=0.5.0; extra == 'test'
|
19
19
|
Requires-Dist: pytest-lazy-fixtures<1.2,>=1.1.4; extra == 'test'
|
20
|
-
Requires-Dist: pytest-randomly<3.17,>=3.16.0; extra == 'test'
|
21
20
|
Requires-Dist: pytest-regressions<2.9,>=2.8.0; extra == 'test'
|
22
21
|
Requires-Dist: pytest-rerunfailures<16,>=15.1; extra == 'test'
|
23
22
|
Requires-Dist: pytest-rng<1.1,>=1.0.0; extra == 'test'
|
@@ -1,11 +1,11 @@
|
|
1
|
-
utilities/__init__.py,sha256=
|
1
|
+
utilities/__init__.py,sha256=XNt4jtceKkZ5SzTlJ0nWpgaWnxz3PNjWlzmzu1iXOtI,60
|
2
2
|
utilities/aiolimiter.py,sha256=mD0wEiqMgwpty4XTbawFpnkkmJS6R4JRsVXFUaoitSU,628
|
3
3
|
utilities/altair.py,sha256=HeZBVUocjkrTNwwKrClppsIqgNFF-ykv05HfZSoHYno,9104
|
4
4
|
utilities/asyncio.py,sha256=USWMMrHqPVRr20vlIn_n5JLimyqa-5xLhuqDYWJed8A,37586
|
5
5
|
utilities/atomicwrites.py,sha256=geFjn9Pwn-tTrtoGjDDxWli9NqbYfy3gGL6ZBctiqSo,5393
|
6
6
|
utilities/atools.py,sha256=-bFGIrwYMFR7xl39j02DZMsO_u5x5_Ph7bRlBUFVYyw,1048
|
7
7
|
utilities/cachetools.py,sha256=uBtEv4hD-TuCPX_cQy1lOpLF-QqfwnYGSf0o4Soqydc,2826
|
8
|
-
utilities/click.py,sha256=
|
8
|
+
utilities/click.py,sha256=DI8yJFlpBpRvnc90Xc0kfLKGQRpFCvj797oOJiaE4k8,14998
|
9
9
|
utilities/concurrent.py,sha256=s2scTEd2AhXVTW4hpASU2qxV_DiVLALfms55cCQzCvM,2886
|
10
10
|
utilities/contextlib.py,sha256=lpaLJBy3X0UGLWjM98jkQZZq8so4fRmoK-Bheq0uOW4,1027
|
11
11
|
utilities/contextvars.py,sha256=RsSGGrbQqqZ67rOydnM7WWIsM2lIE31UHJLejnHJPWY,505
|
@@ -42,7 +42,7 @@ utilities/operator.py,sha256=DuiWdkmK0D-ddvFqOayDkazTQE1Ysvtl6-UiBN5gns8,3857
|
|
42
42
|
utilities/optuna.py,sha256=loyJGWTzljgdJaoLhP09PT8Jz6o_pwBOwehY33lHkhw,1923
|
43
43
|
utilities/orjson.py,sha256=y5ynSGhQjX7vikfvsHh_AklLnH7gjvsSkIC3h5tnx98,36474
|
44
44
|
utilities/os.py,sha256=D_FyyT-6TtqiN9KSS7c9g1fnUtgxmyMtzAjmYLkk46A,3587
|
45
|
-
utilities/parse.py,sha256=
|
45
|
+
utilities/parse.py,sha256=PCy73pBmXgFzjxV54BC7TzHVhV3caDQvdvfXYqE_UUQ,17642
|
46
46
|
utilities/pathlib.py,sha256=PK41rf1c9Wqv7h8f5R7H3_Lhq_gQZTUJD5tu3gMHVaU,3247
|
47
47
|
utilities/period.py,sha256=opqpBevBGSGXbA7NYfRJjtthi1JPxdMaZ7QV3xosnTc,4774
|
48
48
|
utilities/pickle.py,sha256=MBT2xZCsv0pH868IXLGKnlcqNx2IRVKYNpRcqiQQqxw,653
|
@@ -55,7 +55,6 @@ utilities/psutil.py,sha256=0j4YxtVb8VjaaKKiHg6UEK95SUPkEcENgPtLgPJsNv0,3760
|
|
55
55
|
utilities/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
56
56
|
utilities/pydantic.py,sha256=aP6OKowg2Md4rgQuQ5qTSF4bTbBuq7WtRb7zS3JSRGY,1841
|
57
57
|
utilities/pyinstrument.py,sha256=_Rfq6Gg4NKV2NF0dRYOpK2IRyyePxI7-3UmHIQLYrlQ,852
|
58
|
-
utilities/pyrsistent.py,sha256=wVOVIe_68AAaa-lUE9y-TEzDawVp1uEIc_zfoDgr5ww,2287
|
59
58
|
utilities/pytest.py,sha256=xSDybvkvdj7Ix-Tpc1INctKZV07qwrQvJlQonSimB7o,8273
|
60
59
|
utilities/pytest_regressions.py,sha256=YI55B7EtLjhz7zPJZ6NK9bWrxrKCKabWZJe1cwcbA5o,5082
|
61
60
|
utilities/python_dotenv.py,sha256=edXsvHZhZnYeqfMfrsRRpj7_9eJI6uizh3xLx8Q9B3w,3228
|
@@ -79,7 +78,7 @@ utilities/threading.py,sha256=GvBOp4CyhHfN90wGXZuA2VKe9fGzMaEa7oCl4f3nnPU,1009
|
|
79
78
|
utilities/timer.py,sha256=oYqRQ-G-DMOOHB6a4yP5-PJDVimLnbNkMnkOj_jUmFg,2474
|
80
79
|
utilities/traceback.py,sha256=i-790AQbTrDA8MiYyOcYPFpm48I558VR_kL_7x4ypfY,8503
|
81
80
|
utilities/typed_settings.py,sha256=DqJsJjSit9wd_OA3KyMDpx2zatKIi5QhuARI9TPl3rk,3701
|
82
|
-
utilities/types.py,sha256=
|
81
|
+
utilities/types.py,sha256=ZkTndROqNbpgUa_MX4pYlkfmU9E8prMqr4UvASruhsE,19013
|
83
82
|
utilities/typing.py,sha256=kVWK6ciV8T0MKxnFQcMSEr_XlRisspH5aBTTosMUh30,13872
|
84
83
|
utilities/tzdata.py,sha256=fgNVj66yUbCSI_-vrRVzSD3gtf-L_8IEJEPjP_Jel5Y,266
|
85
84
|
utilities/tzlocal.py,sha256=KyCXEgCTjqGFx-389JdTuhMRUaT06U1RCMdWoED-qro,728
|
@@ -89,7 +88,7 @@ utilities/warnings.py,sha256=un1LvHv70PU-LLv8RxPVmugTzDJkkGXRMZTE2-fTQHw,1771
|
|
89
88
|
utilities/whenever.py,sha256=tArX9unVEKhRYdvbUFa83e4hrzdtMKKCEN4QWTaYd8c,19524
|
90
89
|
utilities/zipfile.py,sha256=24lQc9ATcJxHXBPc_tBDiJk48pWyRrlxO2fIsFxU0A8,699
|
91
90
|
utilities/zoneinfo.py,sha256=oEH-nL3t4h9uawyZqWDtNtDAl6M-CLpLYGI_nI6DulM,1971
|
92
|
-
dycw_utilities-0.132.
|
93
|
-
dycw_utilities-0.132.
|
94
|
-
dycw_utilities-0.132.
|
95
|
-
dycw_utilities-0.132.
|
91
|
+
dycw_utilities-0.132.4.dist-info/METADATA,sha256=_AReviYgS7sJRlfoEv0VV19ABmMgXnFz2uWE0Rq3JNI,1522
|
92
|
+
dycw_utilities-0.132.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
93
|
+
dycw_utilities-0.132.4.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
|
94
|
+
dycw_utilities-0.132.4.dist-info/RECORD,,
|
utilities/__init__.py
CHANGED
utilities/click.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
+
import ipaddress
|
3
4
|
import pathlib
|
4
5
|
from typing import TYPE_CHECKING, Generic, TypedDict, TypeVar, assert_never, override
|
5
6
|
|
@@ -12,12 +13,15 @@ import utilities.whenever
|
|
12
13
|
from utilities.enum import EnsureEnumError, ensure_enum
|
13
14
|
from utilities.functions import EnsureStrError, ensure_str, get_class_name
|
14
15
|
from utilities.iterables import is_iterable_not_str
|
16
|
+
from utilities.parse import ParseObjectError, parse_object
|
15
17
|
from utilities.text import split_str
|
16
18
|
from utilities.types import (
|
17
19
|
DateDeltaLike,
|
18
20
|
DateLike,
|
19
21
|
DateTimeDeltaLike,
|
20
22
|
EnumLike,
|
23
|
+
IPv4AddressLike,
|
24
|
+
IPv6AddressLike,
|
21
25
|
MaybeStr,
|
22
26
|
PlainDateTimeLike,
|
23
27
|
TEnum,
|
@@ -173,6 +177,58 @@ class Enum(ParamType, Generic[TEnum]):
|
|
173
177
|
return _make_metavar(param, desc)
|
174
178
|
|
175
179
|
|
180
|
+
class IPv4Address(ParamType):
|
181
|
+
"""An IPv4 address-valued parameter."""
|
182
|
+
|
183
|
+
name = "ipv4 address"
|
184
|
+
|
185
|
+
@override
|
186
|
+
def __repr__(self) -> str:
|
187
|
+
return self.name.upper()
|
188
|
+
|
189
|
+
@override
|
190
|
+
def convert(
|
191
|
+
self, value: IPv4AddressLike, param: Parameter | None, ctx: Context | None
|
192
|
+
) -> ipaddress.IPv4Address:
|
193
|
+
"""Convert a value into the `IPv4Address` type."""
|
194
|
+
match value:
|
195
|
+
case ipaddress.IPv4Address():
|
196
|
+
return value
|
197
|
+
case str():
|
198
|
+
try:
|
199
|
+
return parse_object(ipaddress.IPv4Address, value)
|
200
|
+
except ParseObjectError as error:
|
201
|
+
self.fail(str(error), param, ctx)
|
202
|
+
case _ as never:
|
203
|
+
assert_never(never)
|
204
|
+
|
205
|
+
|
206
|
+
class IPv6Address(ParamType):
|
207
|
+
"""An IPv6 address-valued parameter."""
|
208
|
+
|
209
|
+
name = "ipv6 address"
|
210
|
+
|
211
|
+
@override
|
212
|
+
def __repr__(self) -> str:
|
213
|
+
return self.name.upper()
|
214
|
+
|
215
|
+
@override
|
216
|
+
def convert(
|
217
|
+
self, value: IPv6AddressLike, param: Parameter | None, ctx: Context | None
|
218
|
+
) -> ipaddress.IPv6Address:
|
219
|
+
"""Convert a value into the `IPv6Address` type."""
|
220
|
+
match value:
|
221
|
+
case ipaddress.IPv6Address():
|
222
|
+
return value
|
223
|
+
case str():
|
224
|
+
try:
|
225
|
+
return parse_object(ipaddress.IPv6Address, value)
|
226
|
+
except ParseObjectError as error:
|
227
|
+
self.fail(str(error), param, ctx)
|
228
|
+
case _ as never:
|
229
|
+
assert_never(never)
|
230
|
+
|
231
|
+
|
176
232
|
class Month(ParamType):
|
177
233
|
"""A month-valued parameter."""
|
178
234
|
|
@@ -467,6 +523,8 @@ __all__ = [
|
|
467
523
|
"FrozenSetEnums",
|
468
524
|
"FrozenSetParameter",
|
469
525
|
"FrozenSetStrs",
|
526
|
+
"IPv4Address",
|
527
|
+
"IPv6Address",
|
470
528
|
"ListEnums",
|
471
529
|
"ListParameter",
|
472
530
|
"ListStrs",
|
utilities/parse.py
CHANGED
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
3
3
|
from contextlib import suppress
|
4
4
|
from dataclasses import dataclass
|
5
5
|
from enum import Enum
|
6
|
+
from ipaddress import IPv4Address, IPv6Address
|
6
7
|
from pathlib import Path
|
7
8
|
from re import DOTALL
|
8
9
|
from types import NoneType
|
@@ -176,14 +177,9 @@ def _parse_object_type(
|
|
176
177
|
return parse_bool(text)
|
177
178
|
except ParseBoolError:
|
178
179
|
raise _ParseObjectParseError(type_=cls, text=text) from None
|
179
|
-
if is_subclass_gen(cls, int):
|
180
|
+
if is_subclass_gen(cls, int | float | IPv4Address | IPv6Address):
|
180
181
|
try:
|
181
|
-
return
|
182
|
-
except ValueError:
|
183
|
-
raise _ParseObjectParseError(type_=cls, text=text) from None
|
184
|
-
if issubclass(cls, float):
|
185
|
-
try:
|
186
|
-
return float(text)
|
182
|
+
return cls(text)
|
187
183
|
except ValueError:
|
188
184
|
raise _ParseObjectParseError(type_=cls, text=text) from None
|
189
185
|
if issubclass(cls, Enum):
|
@@ -443,7 +439,16 @@ def serialize_object(
|
|
443
439
|
with suppress(_SerializeObjectSerializeError):
|
444
440
|
return _serialize_object_extra(obj, extra)
|
445
441
|
if (obj is None) or isinstance(
|
446
|
-
obj,
|
442
|
+
obj,
|
443
|
+
bool
|
444
|
+
| int
|
445
|
+
| float
|
446
|
+
| str
|
447
|
+
| IPv4Address
|
448
|
+
| IPv6Address
|
449
|
+
| Path
|
450
|
+
| Sentinel
|
451
|
+
| Version,
|
447
452
|
):
|
448
453
|
return str(obj)
|
449
454
|
if isinstance(
|
utilities/types.py
CHANGED
@@ -4,6 +4,7 @@ import datetime as dt
|
|
4
4
|
from asyncio import Event
|
5
5
|
from collections.abc import Awaitable, Callable, Coroutine, Hashable, Iterable, Mapping
|
6
6
|
from enum import Enum
|
7
|
+
from ipaddress import IPv4Address, IPv6Address
|
7
8
|
from logging import Logger
|
8
9
|
from pathlib import Path
|
9
10
|
from random import Random
|
@@ -112,6 +113,11 @@ THashable1 = TypeVar("THashable1", bound=Hashable)
|
|
112
113
|
THashable2 = TypeVar("THashable2", bound=Hashable)
|
113
114
|
|
114
115
|
|
116
|
+
# ipaddress
|
117
|
+
IPv4AddressLike = MaybeStr[IPv4Address]
|
118
|
+
IPv6AddressLike = MaybeStr[IPv6Address]
|
119
|
+
|
120
|
+
|
115
121
|
# iterables
|
116
122
|
type MaybeIterable[_T] = _T | Iterable[_T]
|
117
123
|
type IterableHashable[_THashable: Hashable] = (
|
@@ -295,6 +301,8 @@ __all__ = [
|
|
295
301
|
"DateTimeRoundUnit",
|
296
302
|
"EnumLike",
|
297
303
|
"ExcInfo",
|
304
|
+
"IPv4AddressLike",
|
305
|
+
"IPv6AddressLike",
|
298
306
|
"IterableHashable",
|
299
307
|
"LogLevel",
|
300
308
|
"LoggerOrName",
|
utilities/pyrsistent.py
DELETED
@@ -1,89 +0,0 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
|
3
|
-
from typing import TYPE_CHECKING, Any, TypeVar, dataclass_transform, overload
|
4
|
-
|
5
|
-
from pyrsistent import PRecord as _PRecord
|
6
|
-
from pyrsistent import field as _field
|
7
|
-
from pyrsistent._field_common import (
|
8
|
-
PFIELD_NO_FACTORY,
|
9
|
-
PFIELD_NO_INITIAL,
|
10
|
-
PFIELD_NO_INVARIANT,
|
11
|
-
PFIELD_NO_SERIALIZER,
|
12
|
-
PFIELD_NO_TYPE,
|
13
|
-
)
|
14
|
-
|
15
|
-
if TYPE_CHECKING:
|
16
|
-
from collections.abc import Callable
|
17
|
-
|
18
|
-
from utilities.types import TypeLike
|
19
|
-
|
20
|
-
|
21
|
-
_T = TypeVar("_T")
|
22
|
-
_U = TypeVar("_U")
|
23
|
-
|
24
|
-
|
25
|
-
@overload
|
26
|
-
def field(
|
27
|
-
*,
|
28
|
-
type: type[_T],
|
29
|
-
invariant: Callable[[Any], tuple[bool, Any]] = ...,
|
30
|
-
default: Any = ...,
|
31
|
-
mandatory: bool = ...,
|
32
|
-
factory: Callable[[_U], _U] = ...,
|
33
|
-
serializer: Callable[[Any, Any], Any] = ...,
|
34
|
-
) -> _T: ...
|
35
|
-
@overload
|
36
|
-
def field(
|
37
|
-
*,
|
38
|
-
type: tuple[type[_T]],
|
39
|
-
invariant: Callable[[Any], tuple[bool, Any]] = ...,
|
40
|
-
default: Any = ...,
|
41
|
-
mandatory: bool = ...,
|
42
|
-
factory: Callable[[_U], _U] = ...,
|
43
|
-
serializer: Callable[[Any, Any], Any] = ...,
|
44
|
-
) -> _T: ...
|
45
|
-
@overload
|
46
|
-
def field(
|
47
|
-
*,
|
48
|
-
type: tuple[type[_T], type[_U]],
|
49
|
-
invariant: Callable[[Any], tuple[bool, Any]] = ...,
|
50
|
-
default: Any = ...,
|
51
|
-
mandatory: bool = ...,
|
52
|
-
factory: Callable[[_U], _U] = ...,
|
53
|
-
serializer: Callable[[Any, Any], Any] = ...,
|
54
|
-
) -> _T | _U: ...
|
55
|
-
@overload
|
56
|
-
def field(
|
57
|
-
*,
|
58
|
-
type: tuple[Any, ...] = ...,
|
59
|
-
invariant: Callable[[Any], tuple[bool, Any]] = ...,
|
60
|
-
default: Any = ...,
|
61
|
-
mandatory: bool = ...,
|
62
|
-
factory: Callable[[_U], _U] = ...,
|
63
|
-
serializer: Callable[[Any, Any], Any] = ...,
|
64
|
-
) -> Any: ...
|
65
|
-
def field(
|
66
|
-
*,
|
67
|
-
type: TypeLike[_T] = PFIELD_NO_TYPE, # noqa: A002
|
68
|
-
invariant: Callable[[Any], tuple[bool, Any]] = PFIELD_NO_INVARIANT,
|
69
|
-
default: Any = PFIELD_NO_INITIAL,
|
70
|
-
mandatory: bool = False,
|
71
|
-
factory: Callable[[_U], _U] = PFIELD_NO_FACTORY,
|
72
|
-
serializer: Callable[[Any, Any], Any] = PFIELD_NO_SERIALIZER,
|
73
|
-
) -> Any:
|
74
|
-
"""Field specification factory for :py:class:`PRecord`."""
|
75
|
-
return _field(
|
76
|
-
type=type,
|
77
|
-
invariant=invariant,
|
78
|
-
initial=default,
|
79
|
-
mandatory=mandatory,
|
80
|
-
factory=factory,
|
81
|
-
serializer=serializer,
|
82
|
-
)
|
83
|
-
|
84
|
-
|
85
|
-
@dataclass_transform(kw_only_default=True, field_specifiers=(field,))
|
86
|
-
class PRecord(_PRecord): ...
|
87
|
-
|
88
|
-
|
89
|
-
__all__ = ["PRecord", "field"]
|
File without changes
|
File without changes
|