dycw-utilities 0.109.7__py3-none-any.whl → 0.109.8__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dycw-utilities
3
- Version: 0.109.7
3
+ Version: 0.109.8
4
4
  Author-email: Derek Wan <d.wan@icloud.com>
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -1,4 +1,4 @@
1
- utilities/__init__.py,sha256=MUwL4q6Wbk3lcuTXRAV3j_zzg6Rwbca04bQFKgMtHec,60
1
+ utilities/__init__.py,sha256=HolaprMxFmj01s_l_QOeA1rUAo9639B4EnJ2_HF8s5o,60
2
2
  utilities/altair.py,sha256=NSyDsm8QlkAGmsGdxVwCkHnPxt_35yJBa9Lg7bz9Ays,9054
3
3
  utilities/astor.py,sha256=xuDUkjq0-b6fhtwjhbnebzbqQZAjMSHR1IIS5uOodVg,777
4
4
  utilities/asyncio.py,sha256=41oQUurWMvadFK5gFnaG21hMM0Vmfn2WS6OpC0R9mas,14757
@@ -11,7 +11,7 @@ utilities/contextlib.py,sha256=OOIIEa5lXKGzFAnauaul40nlQnQko6Na4ryiMJcHkIg,478
11
11
  utilities/contextvars.py,sha256=RsSGGrbQqqZ67rOydnM7WWIsM2lIE31UHJLejnHJPWY,505
12
12
  utilities/cryptography.py,sha256=HyOewI20cl3uRXsKivhIaeLVDInQdzgXZGaly7hS5dE,771
13
13
  utilities/cvxpy.py,sha256=Rv1-fD-XYerosCavRF8Pohop2DBkU3AlFaGTfD8AEAA,13776
14
- utilities/dataclasses.py,sha256=Rh5QajjwyXGpQqndeOFRT-VnPJXF0jWI515GjCSprS0,23326
14
+ utilities/dataclasses.py,sha256=rQS-G-JwhQNufV80aThSOD_ENliueqkz4N6NqtTTPN8,23294
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
@@ -40,7 +40,7 @@ utilities/operator.py,sha256=0M2yZJ0PODH47ogFEnkGMBe_cfxwZR02T_92LZVZvHo,3715
40
40
  utilities/optuna.py,sha256=loyJGWTzljgdJaoLhP09PT8Jz6o_pwBOwehY33lHkhw,1923
41
41
  utilities/orjson.py,sha256=Wj5pzG_VdgoAy14a7Luhem-BgYrRtRFvvl_POiszRd0,36930
42
42
  utilities/os.py,sha256=D_FyyT-6TtqiN9KSS7c9g1fnUtgxmyMtzAjmYLkk46A,3587
43
- utilities/parse.py,sha256=hzMDMUA9h3IpgsR48-Dk4CaojXofLm-eAn_bvJ8o6k8,7081
43
+ utilities/parse.py,sha256=D1rqqrULV1FkjnCZS6804Io26_AZbMrsEILf-pZGNzw,7192
44
44
  utilities/pathlib.py,sha256=31WPMXdLIyXgYOMMl_HOI2wlo66MGSE-cgeelk-Lias,1410
45
45
  utilities/period.py,sha256=ikHXsWtDLr553cfH6p9mMaiCnIAP69B7q84ckWV3HaA,10884
46
46
  utilities/pickle.py,sha256=Bhvd7cZl-zQKQDFjUerqGuSKlHvnW1K2QXeU5UZibtg,657
@@ -53,7 +53,7 @@ utilities/pyinstrument.py,sha256=ROq2txPwbe2ZUuYJ2IDNbfT97lu2ca0v5_C_yn6sSlM,800
53
53
  utilities/pyrsistent.py,sha256=TLJfiiKO4cKNU_pCoM3zDqmSM421qpuoaeaBNnyC_Ac,2489
54
54
  utilities/pytest.py,sha256=85QUax4g2VBBAqAHtM9wekcSLB7_9O8AKFTaCshztL8,7989
55
55
  utilities/pytest_regressions.py,sha256=-SVT9647Dg6-JcdsiaDKXe3NdOmmrvGevLKWwGjxq3c,5088
56
- utilities/python_dotenv.py,sha256=ZIz45FjpwoMs5fdYr9kRM6f4qEp2GNM5rKLnrRe8_7c,3218
56
+ utilities/python_dotenv.py,sha256=JDIGuaGIiVkOcOBDpA7OZZM_0vxrkZyrrfqOssB6cqE,3170
57
57
  utilities/random.py,sha256=lYdjgxB7GCfU_fwFVl5U-BIM_HV3q6_urL9byjrwDM8,4157
58
58
  utilities/re.py,sha256=5J4d8VwIPFVrX2Eb8zfoxImDv7IwiN_U7mJ07wR2Wvs,3958
59
59
  utilities/redis.py,sha256=CsDQqc9V6ASLzLQwtbQXZQEndyG9pJiCOhPlPeszt7Y,21203
@@ -74,7 +74,7 @@ utilities/text.py,sha256=X_EjRQeV_PsG3oP7OiGYIyXGKWqciTnSwoKhM2tsy6M,3120
74
74
  utilities/threading.py,sha256=GvBOp4CyhHfN90wGXZuA2VKe9fGzMaEa7oCl4f3nnPU,1009
75
75
  utilities/timer.py,sha256=Rkc49KSpHuC8s7vUxGO9DU55U9I6yDKnchsQqrUCVBs,4075
76
76
  utilities/traceback.py,sha256=KwHPLdEbdj0fFhXo8MBfxcvem8A-VXYDwFMNJ6f0cTM,27328
77
- utilities/types.py,sha256=QK8kgH80TJdh_vktaZHrCEk7f1f8kHiDr8dJlK8aSac,17814
77
+ utilities/types.py,sha256=fkaqL67A_1p0-Q88JTu1dt_GV3mVo5mSslYa9DGWNq4,17903
78
78
  utilities/typing.py,sha256=gLg4EbE1FX52fJ1d3ji4i08qolwu9qgWt8w_w_Y5DTk,5512
79
79
  utilities/tzdata.py,sha256=2ZsPmhTVM9Ptrxb4QrWKtKOB9RiH8IOO-A1u7ULdVbg,176
80
80
  utilities/tzlocal.py,sha256=42BCquGF54oIqIKe5RGziP4K8Nbm3Ey7uqcNn6m5ge8,534
@@ -84,7 +84,7 @@ utilities/warnings.py,sha256=yUgjnmkCRf6QhdyAXzl7u0qQFejhQG3PrjoSwxpbHrs,1819
84
84
  utilities/whenever.py,sha256=TjoTAJ1R27-rKXiXzdE4GzPidmYqm0W58XydDXp-QZM,17786
85
85
  utilities/zipfile.py,sha256=24lQc9ATcJxHXBPc_tBDiJk48pWyRrlxO2fIsFxU0A8,699
86
86
  utilities/zoneinfo.py,sha256=-DQz5a0Ikw9jfSZtL0BEQkXOMC9yGn_xiJYNCLMiqEc,1989
87
- dycw_utilities-0.109.7.dist-info/METADATA,sha256=pDfjhbqQ0EwowMUVigqpK60JwGhbUysd3RLQVL398aw,13004
88
- dycw_utilities-0.109.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
89
- dycw_utilities-0.109.7.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
90
- dycw_utilities-0.109.7.dist-info/RECORD,,
87
+ dycw_utilities-0.109.8.dist-info/METADATA,sha256=MIDeCogv3Eg50hnzviSxygm6L6i4mPPDY7_VzeKIrR0,13004
88
+ dycw_utilities-0.109.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
89
+ dycw_utilities-0.109.8.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
90
+ dycw_utilities-0.109.8.dist-info/RECORD,,
utilities/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.109.7"
3
+ __version__ = "0.109.8"
utilities/dataclasses.py CHANGED
@@ -24,7 +24,7 @@ from utilities.iterables import OneStrEmptyError, OneStrNonUniqueError, one_str
24
24
  from utilities.operator import is_equal
25
25
  from utilities.parse import ParseTextError, parse_text
26
26
  from utilities.sentinel import Sentinel, sentinel
27
- from utilities.types import TDataclass
27
+ from utilities.types import ParseTextExtra, TDataclass
28
28
  from utilities.typing import get_type_hints
29
29
 
30
30
  if TYPE_CHECKING:
@@ -454,7 +454,7 @@ def text_to_dataclass(
454
454
  head: bool = False,
455
455
  case_sensitive: bool = False,
456
456
  allow_extra_keys: bool = False,
457
- extra_parsers: Mapping[type[_T], Callable[[str], _T]] | None = None,
457
+ extra_parsers: ParseTextExtra | None = None,
458
458
  ) -> TDataclass:
459
459
  """Construct a dataclass from a string or a mapping or strings."""
460
460
  match text_or_mapping:
@@ -524,7 +524,7 @@ def _text_to_dataclass_parse(
524
524
  *,
525
525
  head: bool = False,
526
526
  case_sensitive: bool = False,
527
- extra: Mapping[type[_T], Callable[[str], _T]] | None = None,
527
+ extra: ParseTextExtra | None = None,
528
528
  ) -> Any:
529
529
  try:
530
530
  return parse_text(
utilities/parse.py CHANGED
@@ -7,7 +7,7 @@ from enum import Enum
7
7
  from pathlib import Path
8
8
  from re import DOTALL
9
9
  from types import NoneType
10
- from typing import TYPE_CHECKING, Any, TypeVar, override
10
+ from typing import Any, override
11
11
 
12
12
  from utilities.datetime import is_subclass_date_not_datetime
13
13
  from utilities.enum import ParseEnumError, parse_enum
@@ -17,7 +17,7 @@ from utilities.math import ParseNumberError, parse_number
17
17
  from utilities.re import ExtractGroupError, extract_group
18
18
  from utilities.sentinel import ParseSentinelError, Sentinel, parse_sentinel
19
19
  from utilities.text import ParseBoolError, ParseNoneError, parse_bool, parse_none
20
- from utilities.types import Duration, Number
20
+ from utilities.types import Duration, Number, ParseTextExtra
21
21
  from utilities.typing import (
22
22
  get_args,
23
23
  is_literal_type,
@@ -27,12 +27,6 @@ from utilities.typing import (
27
27
  )
28
28
  from utilities.version import ParseVersionError, Version, parse_version
29
29
 
30
- if TYPE_CHECKING:
31
- from collections.abc import Callable, Mapping
32
-
33
-
34
- _T = TypeVar("_T")
35
-
36
30
 
37
31
  def parse_text(
38
32
  obj: Any,
@@ -41,7 +35,7 @@ def parse_text(
41
35
  *,
42
36
  head: bool = False,
43
37
  case_sensitive: bool = False,
44
- extra: Mapping[type[_T], Callable[[str], _T]] | None = None,
38
+ extra: ParseTextExtra | None = None,
45
39
  ) -> Any:
46
40
  """Parse text."""
47
41
  if obj is None:
@@ -76,7 +70,7 @@ def parse_text(
76
70
  for arg, text in zip(args, texts, strict=True)
77
71
  )
78
72
  if is_union_type(obj):
79
- return _parse_text_union_type(obj, text)
73
+ return _parse_text_union_type(obj, text, extra=extra)
80
74
  raise _ParseTextParseError(obj=obj, text=text) from None
81
75
 
82
76
 
@@ -86,7 +80,7 @@ def _parse_text_type(
86
80
  /,
87
81
  *,
88
82
  case_sensitive: bool = False,
89
- extra: Mapping[type[_T], Callable[[str], _T]] | None = None,
83
+ extra: ParseTextExtra | None = None,
90
84
  ) -> Any:
91
85
  """Parse text."""
92
86
  if issubclass(cls, NoneType):
@@ -170,7 +164,9 @@ def _parse_text_type(
170
164
  raise _ParseTextParseError(obj=cls, text=text) from None
171
165
 
172
166
 
173
- def _parse_text_union_type(obj: Any, text: str, /) -> Any:
167
+ def _parse_text_union_type(
168
+ obj: Any, text: str, /, *, extra: ParseTextExtra | None = None
169
+ ) -> Any:
174
170
  if obj is Number:
175
171
  try:
176
172
  return parse_number(text)
@@ -183,6 +179,13 @@ def _parse_text_union_type(obj: Any, text: str, /) -> Any:
183
179
  return parse_duration(text)
184
180
  except ParseDurationError:
185
181
  raise _ParseTextParseError(obj=obj, text=text) from None
182
+ if extra is not None:
183
+ try:
184
+ parser = one(p for c, p in extra.items() if c is obj)
185
+ except OneEmptyError:
186
+ pass
187
+ else:
188
+ return parser(text)
186
189
  raise _ParseTextParseError(obj=obj, text=text) from None
187
190
 
188
191
 
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from dataclasses import dataclass
4
4
  from os import environ
5
- from typing import TYPE_CHECKING, TypeVar, override
5
+ from typing import TYPE_CHECKING, override
6
6
 
7
7
  from dotenv import dotenv_values
8
8
 
@@ -13,14 +13,11 @@ from utilities.pathlib import PWD
13
13
  from utilities.reprlib import get_repr
14
14
 
15
15
  if TYPE_CHECKING:
16
- from collections.abc import Callable, Mapping
16
+ from collections.abc import Mapping
17
17
  from collections.abc import Set as AbstractSet
18
18
  from pathlib import Path
19
19
 
20
- from utilities.types import PathLike, StrMapping, TDataclass
21
-
22
-
23
- _T = TypeVar("_T")
20
+ from utilities.types import ParseTextExtra, PathLike, StrMapping, TDataclass
24
21
 
25
22
 
26
23
  def load_settings(
@@ -33,7 +30,7 @@ def load_settings(
33
30
  warn_name_errors: bool = False,
34
31
  head: bool = False,
35
32
  case_sensitive: bool = False,
36
- extra_parsers: Mapping[type[_T], Callable[[str], _T]] | None = None,
33
+ extra_parsers: ParseTextExtra | None = None,
37
34
  ) -> TDataclass:
38
35
  """Load a set of settings from the `.env` file."""
39
36
  path = get_repo_root(cwd=cwd).joinpath(".env")
utilities/types.py CHANGED
@@ -229,6 +229,10 @@ class SupportsRound(Protocol[_T_co]):
229
229
  def __round__(self, ndigits: int, /) -> _T_co: ...
230
230
 
231
231
 
232
+ # parse
233
+ type ParseTextExtra = Mapping[Any, Callable[[str], Any]]
234
+
235
+
232
236
  # pathlib
233
237
  type PathLike = MaybeStr[Path]
234
238
  type PathLikeOrCallable = PathLike | Callable[[], PathLike]
@@ -278,6 +282,7 @@ __all__ = [
278
282
  "OpenMode",
279
283
  "OptExcInfo",
280
284
  "Parallelism",
285
+ "ParseTextExtra",
281
286
  "PathLike",
282
287
  "PathLikeOrCallable",
283
288
  "RoundMode",