dycw-utilities 0.109.5__py3-none-any.whl → 0.109.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.109.5.dist-info → dycw_utilities-0.109.7.dist-info}/METADATA +2 -2
- {dycw_utilities-0.109.5.dist-info → dycw_utilities-0.109.7.dist-info}/RECORD +8 -8
- utilities/__init__.py +1 -1
- utilities/math.py +26 -1
- utilities/parse.py +35 -10
- utilities/whenever.py +3 -4
- {dycw_utilities-0.109.5.dist-info → dycw_utilities-0.109.7.dist-info}/WHEEL +0 -0
- {dycw_utilities-0.109.5.dist-info → dycw_utilities-0.109.7.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: dycw-utilities
|
3
|
-
Version: 0.109.
|
3
|
+
Version: 0.109.7
|
4
4
|
Author-email: Derek Wan <d.wan@icloud.com>
|
5
5
|
License-File: LICENSE
|
6
6
|
Requires-Python: >=3.12
|
@@ -177,7 +177,7 @@ Requires-Dist: scipy<1.16,>=1.15.2; extra == 'zzz-test-scipy'
|
|
177
177
|
Provides-Extra: zzz-test-sentinel
|
178
178
|
Provides-Extra: zzz-test-shelve
|
179
179
|
Provides-Extra: zzz-test-slack-sdk
|
180
|
-
Requires-Dist: aiohttp<3.12,>=3.11.
|
180
|
+
Requires-Dist: aiohttp<3.12,>=3.11.16; extra == 'zzz-test-slack-sdk'
|
181
181
|
Requires-Dist: slack-sdk<3.36,>=3.35.0; extra == 'zzz-test-slack-sdk'
|
182
182
|
Provides-Extra: zzz-test-socket
|
183
183
|
Provides-Extra: zzz-test-sqlalchemy
|
@@ -1,4 +1,4 @@
|
|
1
|
-
utilities/__init__.py,sha256=
|
1
|
+
utilities/__init__.py,sha256=MUwL4q6Wbk3lcuTXRAV3j_zzg6Rwbca04bQFKgMtHec,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
|
@@ -31,7 +31,7 @@ utilities/jupyter.py,sha256=ft5JA7fBxXKzP-L9W8f2-wbF0QeYc_2uLQNFDVk4Z-M,2917
|
|
31
31
|
utilities/logging.py,sha256=opIwFjGKOYyMntVeCsFNXOmTY2z02hMf2UtCB76SaI4,25142
|
32
32
|
utilities/loguru.py,sha256=MEMQVWrdECxk1e3FxGzmOf21vWT9j8CAir98SEXFKPA,3809
|
33
33
|
utilities/luigi.py,sha256=fpH9MbxJDuo6-k9iCXRayFRtiVbUtibCJKugf7ygpv0,5988
|
34
|
-
utilities/math.py,sha256=
|
34
|
+
utilities/math.py,sha256=TexfvLCI12d9Sw5_W4pKVBZ3nRr3zk2iPkcEU7xdEWU,26771
|
35
35
|
utilities/memory_profiler.py,sha256=tf2C51P2lCujPGvRt2Rfc7VEw5LDXmVPCG3z_AvBmbU,962
|
36
36
|
utilities/modules.py,sha256=SnhsRHRUS1po_acejrINauihGQpPvVsp8RDNCei1OLQ,3173
|
37
37
|
utilities/more_itertools.py,sha256=CPUxrMAcTwRxbzbhiqPKi3Xx9hxqI0t6gkWjutaibGk,5534
|
@@ -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=
|
43
|
+
utilities/parse.py,sha256=hzMDMUA9h3IpgsR48-Dk4CaojXofLm-eAn_bvJ8o6k8,7081
|
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
|
@@ -81,10 +81,10 @@ utilities/tzlocal.py,sha256=42BCquGF54oIqIKe5RGziP4K8Nbm3Ey7uqcNn6m5ge8,534
|
|
81
81
|
utilities/uuid.py,sha256=jJTFxz-CWgltqNuzmythB7iEQ-Q1mCwPevUfKthZT3c,611
|
82
82
|
utilities/version.py,sha256=QFuyEeQA6jI0ruBEcmhqG36f-etg1AEiD1drBBqhQrs,5358
|
83
83
|
utilities/warnings.py,sha256=yUgjnmkCRf6QhdyAXzl7u0qQFejhQG3PrjoSwxpbHrs,1819
|
84
|
-
utilities/whenever.py,sha256=
|
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.
|
88
|
-
dycw_utilities-0.109.
|
89
|
-
dycw_utilities-0.109.
|
90
|
-
dycw_utilities-0.109.
|
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,,
|
utilities/__init__.py
CHANGED
utilities/math.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import re
|
4
|
+
from contextlib import suppress
|
4
5
|
from dataclasses import dataclass
|
5
6
|
from math import ceil, exp, floor, isclose, isfinite, isinf, isnan, log, log10, modf
|
6
7
|
from re import Match, search
|
@@ -9,7 +10,8 @@ from typing import TYPE_CHECKING, Literal, assert_never, overload, override
|
|
9
10
|
from utilities.errors import ImpossibleCaseError
|
10
11
|
|
11
12
|
if TYPE_CHECKING:
|
12
|
-
from utilities.types import RoundMode
|
13
|
+
from utilities.types import Number, RoundMode
|
14
|
+
|
13
15
|
|
14
16
|
MIN_FLOAT32, MAX_FLOAT32 = -3.4028234663852886e38, 3.4028234663852886e38
|
15
17
|
MIN_FLOAT64, MAX_FLOAT64 = -1.7976931348623157e308, 1.7976931348623157e308
|
@@ -681,6 +683,27 @@ def order_of_magnitude(x: float, /, *, round_: bool = False) -> float:
|
|
681
683
|
##
|
682
684
|
|
683
685
|
|
686
|
+
def parse_number(number: str, /) -> Number:
|
687
|
+
"""Convert text into a number."""
|
688
|
+
with suppress(ValueError):
|
689
|
+
return int(number)
|
690
|
+
with suppress(ValueError):
|
691
|
+
return float(number)
|
692
|
+
raise ParseNumberError(number=number)
|
693
|
+
|
694
|
+
|
695
|
+
@dataclass(kw_only=True, slots=True)
|
696
|
+
class ParseNumberError(Exception):
|
697
|
+
number: str
|
698
|
+
|
699
|
+
@override
|
700
|
+
def __str__(self) -> str:
|
701
|
+
return f"Unable to parse number; got {self.number!r}"
|
702
|
+
|
703
|
+
|
704
|
+
##
|
705
|
+
|
706
|
+
|
684
707
|
def round_(
|
685
708
|
x: float,
|
686
709
|
/,
|
@@ -887,6 +910,7 @@ __all__ = [
|
|
887
910
|
"MIN_UINT64",
|
888
911
|
"CheckIntegerError",
|
889
912
|
"EWMParametersError",
|
913
|
+
"ParseNumberError",
|
890
914
|
"SafeRoundError",
|
891
915
|
"check_integer",
|
892
916
|
"ewm_parameters",
|
@@ -934,6 +958,7 @@ __all__ = [
|
|
934
958
|
"is_zero_or_non_micro_or_nan",
|
935
959
|
"number_of_decimals",
|
936
960
|
"order_of_magnitude",
|
961
|
+
"parse_number",
|
937
962
|
"round_",
|
938
963
|
"round_float_imprecisions",
|
939
964
|
"round_to_float",
|
utilities/parse.py
CHANGED
@@ -13,10 +13,18 @@ from utilities.datetime import is_subclass_date_not_datetime
|
|
13
13
|
from utilities.enum import ParseEnumError, parse_enum
|
14
14
|
from utilities.functions import is_subclass_int_not_bool
|
15
15
|
from utilities.iterables import OneEmptyError, OneNonUniqueError, one, one_str
|
16
|
+
from utilities.math import ParseNumberError, parse_number
|
16
17
|
from utilities.re import ExtractGroupError, extract_group
|
17
18
|
from utilities.sentinel import ParseSentinelError, Sentinel, parse_sentinel
|
18
19
|
from utilities.text import ParseBoolError, ParseNoneError, parse_bool, parse_none
|
19
|
-
from utilities.
|
20
|
+
from utilities.types import Duration, Number
|
21
|
+
from utilities.typing import (
|
22
|
+
get_args,
|
23
|
+
is_literal_type,
|
24
|
+
is_optional_type,
|
25
|
+
is_tuple_type,
|
26
|
+
is_union_type,
|
27
|
+
)
|
20
28
|
from utilities.version import ParseVersionError, Version, parse_version
|
21
29
|
|
22
30
|
if TYPE_CHECKING:
|
@@ -31,8 +39,8 @@ def parse_text(
|
|
31
39
|
text: str,
|
32
40
|
/,
|
33
41
|
*,
|
34
|
-
case_sensitive: bool = False,
|
35
42
|
head: bool = False,
|
43
|
+
case_sensitive: bool = False,
|
36
44
|
extra: Mapping[type[_T], Callable[[str], _T]] | None = None,
|
37
45
|
) -> Any:
|
38
46
|
"""Parse text."""
|
@@ -49,13 +57,12 @@ def parse_text(
|
|
49
57
|
with suppress(ParseNoneError):
|
50
58
|
return parse_none(text)
|
51
59
|
inner = one(arg for arg in get_args(obj) if arg is not NoneType)
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
raise _ParseTextParseError(obj=obj, text=text) from None
|
60
|
+
try:
|
61
|
+
return parse_text(
|
62
|
+
inner, text, head=head, case_sensitive=case_sensitive, extra=extra
|
63
|
+
)
|
64
|
+
except _ParseTextParseError:
|
65
|
+
raise _ParseTextParseError(obj=obj, text=text) from None
|
59
66
|
if is_tuple_type(obj):
|
60
67
|
args = get_args(obj)
|
61
68
|
try:
|
@@ -65,9 +72,11 @@ def parse_text(
|
|
65
72
|
if len(args) != len(texts):
|
66
73
|
raise _ParseTextParseError(obj=obj, text=text)
|
67
74
|
return tuple(
|
68
|
-
parse_text(arg, text, case_sensitive=case_sensitive,
|
75
|
+
parse_text(arg, text, head=head, case_sensitive=case_sensitive, extra=extra)
|
69
76
|
for arg, text in zip(args, texts, strict=True)
|
70
77
|
)
|
78
|
+
if is_union_type(obj):
|
79
|
+
return _parse_text_union_type(obj, text)
|
71
80
|
raise _ParseTextParseError(obj=obj, text=text) from None
|
72
81
|
|
73
82
|
|
@@ -161,6 +170,22 @@ def _parse_text_type(
|
|
161
170
|
raise _ParseTextParseError(obj=cls, text=text) from None
|
162
171
|
|
163
172
|
|
173
|
+
def _parse_text_union_type(obj: Any, text: str, /) -> Any:
|
174
|
+
if obj is Number:
|
175
|
+
try:
|
176
|
+
return parse_number(text)
|
177
|
+
except ParseNumberError:
|
178
|
+
raise _ParseTextParseError(obj=obj, text=text) from None
|
179
|
+
if obj is Duration:
|
180
|
+
from utilities.whenever import ParseDurationError, parse_duration
|
181
|
+
|
182
|
+
try:
|
183
|
+
return parse_duration(text)
|
184
|
+
except ParseDurationError:
|
185
|
+
raise _ParseTextParseError(obj=obj, text=text) from None
|
186
|
+
raise _ParseTextParseError(obj=obj, text=text) from None
|
187
|
+
|
188
|
+
|
164
189
|
@dataclass
|
165
190
|
class ParseTextError(Exception):
|
166
191
|
obj: Any
|
utilities/whenever.py
CHANGED
@@ -17,6 +17,7 @@ from utilities.datetime import (
|
|
17
17
|
parse_two_digit_year,
|
18
18
|
timedelta_to_microseconds,
|
19
19
|
)
|
20
|
+
from utilities.math import ParseNumberError, parse_number
|
20
21
|
from utilities.re import (
|
21
22
|
ExtractGroupError,
|
22
23
|
ExtractGroupsError,
|
@@ -298,10 +299,8 @@ class ParseDateTimeError(Exception):
|
|
298
299
|
|
299
300
|
def parse_duration(duration: str, /) -> Duration:
|
300
301
|
"""Parse a string into a Duration."""
|
301
|
-
with suppress(
|
302
|
-
return
|
303
|
-
with suppress(ValueError):
|
304
|
-
return float(duration)
|
302
|
+
with suppress(ParseNumberError):
|
303
|
+
return parse_number(duration)
|
305
304
|
try:
|
306
305
|
return parse_timedelta(duration)
|
307
306
|
except ParseTimedeltaError:
|
File without changes
|
File without changes
|