dycw-utilities 0.112.14__py3-none-any.whl → 0.113.1__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.112.14.dist-info → dycw_utilities-0.113.1.dist-info}/METADATA +1 -2
- {dycw_utilities-0.112.14.dist-info → dycw_utilities-0.113.1.dist-info}/RECORD +10 -10
- utilities/__init__.py +1 -1
- utilities/dataclasses.py +24 -1
- utilities/iterables.py +30 -14
- utilities/math.py +2 -2
- utilities/polars.py +3 -124
- utilities/types.py +2 -0
- {dycw_utilities-0.112.14.dist-info → dycw_utilities-0.113.1.dist-info}/WHEEL +0 -0
- {dycw_utilities-0.112.14.dist-info → dycw_utilities-0.113.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: dycw-utilities
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.113.1
|
4
4
|
Author-email: Derek Wan <d.wan@icloud.com>
|
5
5
|
License-File: LICENSE
|
6
6
|
Requires-Python: >=3.12
|
@@ -137,7 +137,6 @@ Provides-Extra: zzz-test-pickle
|
|
137
137
|
Requires-Dist: atomicwrites<1.5,>=1.4.1; extra == 'zzz-test-pickle'
|
138
138
|
Provides-Extra: zzz-test-platform
|
139
139
|
Provides-Extra: zzz-test-polars
|
140
|
-
Requires-Dist: dacite<1.10,>=1.9.2; extra == 'zzz-test-polars'
|
141
140
|
Requires-Dist: polars-lts-cpu<1.30,>=1.29.0; extra == 'zzz-test-polars'
|
142
141
|
Requires-Dist: whenever<0.8,>=0.7.3; extra == 'zzz-test-polars'
|
143
142
|
Provides-Extra: zzz-test-pqdm
|
@@ -1,4 +1,4 @@
|
|
1
|
-
utilities/__init__.py,sha256=
|
1
|
+
utilities/__init__.py,sha256=jYMM0M9M6TZGpXyYU7Rwr3r3k0NY3IhjcbJz_O8C9oM,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
|
@@ -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=
|
14
|
+
utilities/dataclasses.py,sha256=iiC1wpGXWhaocIikzwBt8bbLWyImoUlOlcDZJGejaIg,33011
|
15
15
|
utilities/datetime.py,sha256=OF7jZE702UecnwAbq9D3N-GINpp9gSGoidki1RhimCE,35752
|
16
16
|
utilities/enum.py,sha256=HoRwVCWzsnH0vpO9ZEcAAIZLMv0Sn2vJxxA4sYMQgDs,5793
|
17
17
|
utilities/errors.py,sha256=BtSNP0JC3ik536ddPyTerLomCRJV9f6kdMe6POz0QHM,361
|
@@ -26,13 +26,13 @@ utilities/hashlib.py,sha256=SVTgtguur0P4elppvzOBbLEjVM3Pea0eWB61yg2ilxo,309
|
|
26
26
|
utilities/http.py,sha256=WcahTcKYRtZ04WXQoWt5EGCgFPcyHD3EJdlMfxvDt-0,946
|
27
27
|
utilities/hypothesis.py,sha256=OpZhPdPmsYWvqMytFDc-G196eODosUzxQSuo-LfMYmM,46262
|
28
28
|
utilities/ipython.py,sha256=V2oMYHvEKvlNBzxDXdLvKi48oUq2SclRg5xasjaXStw,763
|
29
|
-
utilities/iterables.py,sha256=
|
29
|
+
utilities/iterables.py,sha256=prKXBdF5QfLTGC-q4567DwO8xzUng_Z-2a4wBkMqyDo,45360
|
30
30
|
utilities/jupyter.py,sha256=ft5JA7fBxXKzP-L9W8f2-wbF0QeYc_2uLQNFDVk4Z-M,2917
|
31
31
|
utilities/lightweight_charts.py,sha256=vyVOzarYhBIOZj2xDhqdbP85qbSKUjdc6Au91rc1W4M,2814
|
32
32
|
utilities/logging.py,sha256=55LVJYd2BKzeTTQr4tG7uSNMDVEgUO56wK4s-rldjrM,25326
|
33
33
|
utilities/loguru.py,sha256=MEMQVWrdECxk1e3FxGzmOf21vWT9j8CAir98SEXFKPA,3809
|
34
34
|
utilities/luigi.py,sha256=fpH9MbxJDuo6-k9iCXRayFRtiVbUtibCJKugf7ygpv0,5988
|
35
|
-
utilities/math.py,sha256
|
35
|
+
utilities/math.py,sha256=-mQgbah-dPJwOEWf3SonrFoVZ2AVxMgpeQ3dfVa-oJA,26764
|
36
36
|
utilities/memory_profiler.py,sha256=tf2C51P2lCujPGvRt2Rfc7VEw5LDXmVPCG3z_AvBmbU,962
|
37
37
|
utilities/modules.py,sha256=iuvLluJya-hvl1Q25-Jk3dLgx2Es3ck4SjJiEkAlVTs,3195
|
38
38
|
utilities/more_itertools.py,sha256=6T0225gBFZtv47-B0JRFOKMz836Wg3Hct79ePPLGpuo,5827
|
@@ -46,7 +46,7 @@ utilities/pathlib.py,sha256=31WPMXdLIyXgYOMMl_HOI2wlo66MGSE-cgeelk-Lias,1410
|
|
46
46
|
utilities/period.py,sha256=RWfcNVoNlW07RNdU47g_zuLZMKbtgfK4bE6G-9tVjY8,11024
|
47
47
|
utilities/pickle.py,sha256=Bhvd7cZl-zQKQDFjUerqGuSKlHvnW1K2QXeU5UZibtg,657
|
48
48
|
utilities/platform.py,sha256=NU7ycTvAXAG-fdYmDXaM1m4EOml2cGiaYwaUzfzSqyU,1767
|
49
|
-
utilities/polars.py,sha256=
|
49
|
+
utilities/polars.py,sha256=fxfSm4xVHwKvRxu50IhYNKCKOagp12FdwsVf04ARKpk,63692
|
50
50
|
utilities/polars_ols.py,sha256=efhXf0gjrHUpQrvS6a7g8yJQJWf_ATKtJnqqF2inCOU,5680
|
51
51
|
utilities/pqdm.py,sha256=foRytQybmOQ05pjt5LF7ANyzrIa--4ScDE3T2wd31a4,3118
|
52
52
|
utilities/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -77,7 +77,7 @@ utilities/text.py,sha256=Fo12N4aA7k2rnb4W4vH9iiDh88Q5_nvRssTkfNsvVM8,10965
|
|
77
77
|
utilities/threading.py,sha256=GvBOp4CyhHfN90wGXZuA2VKe9fGzMaEa7oCl4f3nnPU,1009
|
78
78
|
utilities/timer.py,sha256=Rkc49KSpHuC8s7vUxGO9DU55U9I6yDKnchsQqrUCVBs,4075
|
79
79
|
utilities/traceback.py,sha256=secexUnBsecfWV4ZuqP1W4pGF3prOeO1CRyJK-8zQDU,27402
|
80
|
-
utilities/types.py,sha256=
|
80
|
+
utilities/types.py,sha256=B5slv6Vdj6uRmE1xnEBEJfWJmK_0odEwIUCVC9KHikw,18168
|
81
81
|
utilities/typing.py,sha256=H6ysJkI830aRwLsMKz0SZIw4cpcsm7d6KhQOwr-SDh0,13817
|
82
82
|
utilities/tzdata.py,sha256=yCf70NICwAeazN3_JcXhWvRqCy06XJNQ42j7r6gw3HY,1217
|
83
83
|
utilities/tzlocal.py,sha256=3upDNFBvGh1l9njmLR2z2S6K6VxQSb7QizYGUbAH3JU,960
|
@@ -87,7 +87,7 @@ utilities/warnings.py,sha256=un1LvHv70PU-LLv8RxPVmugTzDJkkGXRMZTE2-fTQHw,1771
|
|
87
87
|
utilities/whenever.py,sha256=iLRP_-8CZtBpHKbGZGu-kjSMg1ZubJ-VSmgSy7Eudxw,17787
|
88
88
|
utilities/zipfile.py,sha256=24lQc9ATcJxHXBPc_tBDiJk48pWyRrlxO2fIsFxU0A8,699
|
89
89
|
utilities/zoneinfo.py,sha256=-Xm57PMMwDTYpxJdkiJG13wnbwK--I7XItBh5WVhD-o,1874
|
90
|
-
dycw_utilities-0.
|
91
|
-
dycw_utilities-0.
|
92
|
-
dycw_utilities-0.
|
93
|
-
dycw_utilities-0.
|
90
|
+
dycw_utilities-0.113.1.dist-info/METADATA,sha256=yaeQ1FFLx3bZShYnRwFit1bF6k9iieYw8kInaN6kQ2w,12941
|
91
|
+
dycw_utilities-0.113.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
92
|
+
dycw_utilities-0.113.1.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
|
93
|
+
dycw_utilities-0.113.1.dist-info/RECORD,,
|
utilities/__init__.py
CHANGED
utilities/dataclasses.py
CHANGED
@@ -20,7 +20,12 @@ from utilities.functions import (
|
|
20
20
|
is_dataclass_class,
|
21
21
|
is_dataclass_instance,
|
22
22
|
)
|
23
|
-
from utilities.iterables import
|
23
|
+
from utilities.iterables import (
|
24
|
+
OneStrEmptyError,
|
25
|
+
OneStrNonUniqueError,
|
26
|
+
cmp_nullable,
|
27
|
+
one_str,
|
28
|
+
)
|
24
29
|
from utilities.operator import is_equal
|
25
30
|
from utilities.parse import (
|
26
31
|
_ParseObjectExtraNonUniqueError,
|
@@ -43,6 +48,7 @@ from utilities.types import (
|
|
43
48
|
SerializeObjectExtra,
|
44
49
|
StrStrMapping,
|
45
50
|
TDataclass,
|
51
|
+
TSupportsLT,
|
46
52
|
)
|
47
53
|
from utilities.typing import get_type_hints
|
48
54
|
|
@@ -215,6 +221,22 @@ def dataclass_to_dict(
|
|
215
221
|
##
|
216
222
|
|
217
223
|
|
224
|
+
def is_nullable_lt(x: TSupportsLT | None, y: TSupportsLT | None, /) -> bool | None:
|
225
|
+
"""Compare two nullable fields."""
|
226
|
+
match cmp_nullable(x, y):
|
227
|
+
case 1:
|
228
|
+
return False
|
229
|
+
case -1:
|
230
|
+
return True
|
231
|
+
case 0:
|
232
|
+
return None
|
233
|
+
case _ as never:
|
234
|
+
assert_never(never)
|
235
|
+
|
236
|
+
|
237
|
+
##
|
238
|
+
|
239
|
+
|
218
240
|
def mapping_to_dataclass(
|
219
241
|
cls: type[TDataclass],
|
220
242
|
mapping: StrMapping,
|
@@ -1056,6 +1078,7 @@ __all__ = [
|
|
1056
1078
|
"YieldFieldsError",
|
1057
1079
|
"dataclass_repr",
|
1058
1080
|
"dataclass_to_dict",
|
1081
|
+
"is_nullable_lt",
|
1059
1082
|
"mapping_to_dataclass",
|
1060
1083
|
"one_field",
|
1061
1084
|
"parse_dataclass",
|
utilities/iterables.py
CHANGED
@@ -45,7 +45,7 @@ from utilities.math import (
|
|
45
45
|
)
|
46
46
|
from utilities.reprlib import get_repr
|
47
47
|
from utilities.sentinel import Sentinel, sentinel
|
48
|
-
from utilities.types import THashable, THashable2, TSupportsAdd
|
48
|
+
from utilities.types import Sign, THashable, THashable2, TSupportsAdd, TSupportsLT
|
49
49
|
from utilities.zoneinfo import UTC
|
50
50
|
|
51
51
|
if TYPE_CHECKING:
|
@@ -696,6 +696,24 @@ class _CheckUniqueModuloCaseDuplicateLowerCaseStringsError(CheckUniqueModuloCase
|
|
696
696
|
##
|
697
697
|
|
698
698
|
|
699
|
+
def cmp_nullable(x: TSupportsLT | None, y: TSupportsLT | None, /) -> Sign:
|
700
|
+
"""Compare two nullable objects."""
|
701
|
+
match x, y:
|
702
|
+
case None, None:
|
703
|
+
return 0
|
704
|
+
case None, _:
|
705
|
+
return -1
|
706
|
+
case _, None:
|
707
|
+
return 1
|
708
|
+
case _, _:
|
709
|
+
return cast("Sign", (x > y) - (x < y))
|
710
|
+
case _ as never:
|
711
|
+
assert_never(never)
|
712
|
+
|
713
|
+
|
714
|
+
##
|
715
|
+
|
716
|
+
|
699
717
|
def chunked(iterable: Iterable[_T], n: int, /) -> Iterator[Sequence[_T]]:
|
700
718
|
"""Break an iterable into lists of length n."""
|
701
719
|
return iter(partial(take, n, iter(iterable)), [])
|
@@ -1293,7 +1311,7 @@ def sort_iterable(iterable: Iterable[_T], /) -> list[_T]:
|
|
1293
1311
|
return sorted(iterable, key=cmp_to_key(_sort_iterable_cmp))
|
1294
1312
|
|
1295
1313
|
|
1296
|
-
def _sort_iterable_cmp(x: Any, y: Any, /) ->
|
1314
|
+
def _sort_iterable_cmp(x: Any, y: Any, /) -> Sign:
|
1297
1315
|
"""Compare two quantities."""
|
1298
1316
|
if type(x) is not type(y):
|
1299
1317
|
x_qualname = type(x).__qualname__
|
@@ -1318,7 +1336,7 @@ def _sort_iterable_cmp(x: Any, y: Any, /) -> Literal[-1, 0, 1]:
|
|
1318
1336
|
return _sort_iterable_cmp_floats(x, y)
|
1319
1337
|
if isinstance(x, str): # else Sequence
|
1320
1338
|
y = cast("str", y)
|
1321
|
-
return cast("
|
1339
|
+
return cast("Sign", (x > y) - (x < y))
|
1322
1340
|
|
1323
1341
|
# collections
|
1324
1342
|
if isinstance(x, Sized):
|
@@ -1333,14 +1351,14 @@ def _sort_iterable_cmp(x: Any, y: Any, /) -> Literal[-1, 0, 1]:
|
|
1333
1351
|
return _sort_iterable_cmp(sort_iterable(x), sort_iterable(y))
|
1334
1352
|
if isinstance(x, Sequence):
|
1335
1353
|
y = cast("Sequence[Any]", y)
|
1336
|
-
it: Iterable[
|
1354
|
+
it: Iterable[Sign] = (
|
1337
1355
|
_sort_iterable_cmp(x_i, y_i) for x_i, y_i in zip(x, y, strict=True)
|
1338
1356
|
)
|
1339
1357
|
with suppress(StopIteration):
|
1340
1358
|
return next(r for r in it if r != 0)
|
1341
1359
|
|
1342
1360
|
try:
|
1343
|
-
return cast("
|
1361
|
+
return cast("Sign", (x > y) - (x < y))
|
1344
1362
|
except TypeError:
|
1345
1363
|
raise SortIterableError(x=x, y=y) from None
|
1346
1364
|
|
@@ -1355,13 +1373,11 @@ class SortIterableError(Exception):
|
|
1355
1373
|
return f"Unable to sort {get_repr(self.x)} and {get_repr(self.y)}"
|
1356
1374
|
|
1357
1375
|
|
1358
|
-
def _sort_iterable_cmp_datetimes(
|
1359
|
-
x: dt.datetime, y: dt.datetime, /
|
1360
|
-
) -> Literal[-1, 0, 1]:
|
1376
|
+
def _sort_iterable_cmp_datetimes(x: dt.datetime, y: dt.datetime, /) -> Sign:
|
1361
1377
|
"""Compare two datetimes."""
|
1362
1378
|
match x.tzinfo, y.tzinfo:
|
1363
1379
|
case None, None:
|
1364
|
-
return cast("
|
1380
|
+
return cast("Sign", (x > y) - (x < y))
|
1365
1381
|
case dt.tzinfo(), None:
|
1366
1382
|
return 1
|
1367
1383
|
case None, dt.tzinfo():
|
@@ -1369,20 +1385,19 @@ def _sort_iterable_cmp_datetimes(
|
|
1369
1385
|
case dt.tzinfo(), dt.tzinfo():
|
1370
1386
|
x_utc = x.astimezone(tz=UTC)
|
1371
1387
|
y_utc = y.astimezone(tz=UTC)
|
1372
|
-
result = cast("
|
1388
|
+
result = cast("Sign", (x_utc > y_utc) - (x_utc < y_utc))
|
1373
1389
|
if result != 0:
|
1374
1390
|
return result
|
1375
1391
|
x_time_zone = ensure_not_none(ensure_not_none(x.tzinfo).tzname(x))
|
1376
1392
|
y_time_zone = ensure_not_none(ensure_not_none(y.tzinfo).tzname(y))
|
1377
1393
|
return cast(
|
1378
|
-
"
|
1379
|
-
(x_time_zone > y_time_zone) - (x_time_zone < y_time_zone),
|
1394
|
+
"Sign", (x_time_zone > y_time_zone) - (x_time_zone < y_time_zone)
|
1380
1395
|
)
|
1381
1396
|
case _ as never:
|
1382
1397
|
assert_never(never)
|
1383
1398
|
|
1384
1399
|
|
1385
|
-
def _sort_iterable_cmp_floats(x: float, y: float, /) ->
|
1400
|
+
def _sort_iterable_cmp_floats(x: float, y: float, /) -> Sign:
|
1386
1401
|
"""Compare two floats."""
|
1387
1402
|
x_nan, y_nan = map(isnan, [x, y])
|
1388
1403
|
match x_nan, y_nan:
|
@@ -1393,7 +1408,7 @@ def _sort_iterable_cmp_floats(x: float, y: float, /) -> Literal[-1, 0, 1]:
|
|
1393
1408
|
case False, True:
|
1394
1409
|
return -1
|
1395
1410
|
case False, False:
|
1396
|
-
return cast("
|
1411
|
+
return cast("Sign", (x > y) - (x < y))
|
1397
1412
|
case _ as never:
|
1398
1413
|
assert_never(never)
|
1399
1414
|
|
@@ -1517,6 +1532,7 @@ __all__ = [
|
|
1517
1532
|
"check_superset",
|
1518
1533
|
"check_unique_modulo_case",
|
1519
1534
|
"chunked",
|
1535
|
+
"cmp_nullable",
|
1520
1536
|
"ensure_hashables",
|
1521
1537
|
"ensure_iterable",
|
1522
1538
|
"ensure_iterable_not_str",
|
utilities/math.py
CHANGED
@@ -10,7 +10,7 @@ from typing import TYPE_CHECKING, Literal, assert_never, overload, override
|
|
10
10
|
from utilities.errors import ImpossibleCaseError
|
11
11
|
|
12
12
|
if TYPE_CHECKING:
|
13
|
-
from utilities.types import Number, RoundMode
|
13
|
+
from utilities.types import Number, RoundMode, Sign
|
14
14
|
|
15
15
|
|
16
16
|
MIN_FLOAT32, MAX_FLOAT32 = -3.4028234663852886e38, 3.4028234663852886e38
|
@@ -860,7 +860,7 @@ class SafeRoundError(Exception):
|
|
860
860
|
|
861
861
|
def sign(
|
862
862
|
x: float, /, *, rel_tol: float | None = None, abs_tol: float | None = None
|
863
|
-
) ->
|
863
|
+
) -> Sign:
|
864
864
|
"""Get the sign of an integer/float."""
|
865
865
|
match x:
|
866
866
|
case int():
|
utilities/polars.py
CHANGED
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
import datetime as dt
|
4
4
|
import enum
|
5
|
-
from collections.abc import Callable,
|
5
|
+
from collections.abc import Callable, Iterator, Sequence
|
6
6
|
from collections.abc import Set as AbstractSet
|
7
7
|
from contextlib import suppress
|
8
8
|
from dataclasses import asdict, dataclass
|
@@ -15,7 +15,6 @@ from typing import (
|
|
15
15
|
Any,
|
16
16
|
Generic,
|
17
17
|
Literal,
|
18
|
-
TypeGuard,
|
19
18
|
TypeVar,
|
20
19
|
assert_never,
|
21
20
|
cast,
|
@@ -109,10 +108,9 @@ from utilities.warnings import suppress_warnings
|
|
109
108
|
from utilities.zoneinfo import UTC, ensure_time_zone, get_time_zone_name
|
110
109
|
|
111
110
|
if TYPE_CHECKING:
|
112
|
-
from collections.abc import Callable, Iterator, Sequence
|
111
|
+
from collections.abc import Callable, Iterable, Iterator, Mapping, Sequence
|
113
112
|
from collections.abc import Set as AbstractSet
|
114
113
|
|
115
|
-
from dacite.data import Data
|
116
114
|
from polars._typing import (
|
117
115
|
IntoExpr, # pyright: ignore[reportPrivateImportUsage]
|
118
116
|
IntoExprColumn, # pyright: ignore[reportPrivateImportUsage]
|
@@ -126,13 +124,7 @@ if TYPE_CHECKING:
|
|
126
124
|
|
127
125
|
from utilities.numpy import NDArrayB, NDArrayF
|
128
126
|
from utilities.statsmodels import ACFMissing
|
129
|
-
from utilities.types import
|
130
|
-
Dataclass,
|
131
|
-
MaybeIterable,
|
132
|
-
StrMapping,
|
133
|
-
TDataclass,
|
134
|
-
TimeZoneLike,
|
135
|
-
)
|
127
|
+
from utilities.types import Dataclass, MaybeIterable, StrMapping, TimeZoneLike
|
136
128
|
|
137
129
|
|
138
130
|
_T = TypeVar("_T")
|
@@ -2134,116 +2126,6 @@ def week_num(column: IntoExprColumn, /, *, start: WeekDay = "mon") -> Expr | Ser
|
|
2134
2126
|
##
|
2135
2127
|
|
2136
2128
|
|
2137
|
-
@overload
|
2138
|
-
def yield_struct_series_elements(
|
2139
|
-
series: Series, /, *, strict: Literal[True]
|
2140
|
-
) -> Iterator[Mapping[str, Any]]: ...
|
2141
|
-
@overload
|
2142
|
-
def yield_struct_series_elements(
|
2143
|
-
series: Series, /, *, strict: Literal[False]
|
2144
|
-
) -> Iterator[Mapping[str, Any] | None]: ...
|
2145
|
-
@overload
|
2146
|
-
def yield_struct_series_elements(
|
2147
|
-
series: Series, /, *, strict: bool = False
|
2148
|
-
) -> Iterator[Mapping[str, Any] | None]: ...
|
2149
|
-
def yield_struct_series_elements(
|
2150
|
-
series: Series, /, *, strict: bool = False
|
2151
|
-
) -> Iterator[Mapping[str, Any] | None]:
|
2152
|
-
"""Yield the elements of a struct-dtype Series as optional mappings."""
|
2153
|
-
if not isinstance(series.dtype, Struct):
|
2154
|
-
raise _YieldStructSeriesElementsDTypeError(series=series)
|
2155
|
-
if strict and series.is_null().any():
|
2156
|
-
raise _YieldStructSeriesElementsNullElementsError(series=series)
|
2157
|
-
for value in series:
|
2158
|
-
yield _yield_struct_series_element_remove_nulls(value)
|
2159
|
-
|
2160
|
-
|
2161
|
-
def _yield_struct_series_element_remove_nulls(obj: Any, /) -> Any:
|
2162
|
-
if not _yield_struct_series_element_is_mapping_of_str(obj):
|
2163
|
-
return obj
|
2164
|
-
if any(_yield_struct_series_element_is_mapping_of_str(v) for v in obj.values()):
|
2165
|
-
result = {
|
2166
|
-
k: _yield_struct_series_element_remove_nulls(v) for k, v in obj.items()
|
2167
|
-
}
|
2168
|
-
if result == obj:
|
2169
|
-
return result
|
2170
|
-
return _yield_struct_series_element_remove_nulls(result)
|
2171
|
-
return None if all(v is None for v in obj.values()) else obj
|
2172
|
-
|
2173
|
-
|
2174
|
-
def _yield_struct_series_element_is_mapping_of_str(
|
2175
|
-
obj: Any, /
|
2176
|
-
) -> TypeGuard[Mapping[str, Any]]:
|
2177
|
-
return isinstance(obj, Mapping) and is_iterable_of(obj, str)
|
2178
|
-
|
2179
|
-
|
2180
|
-
@dataclass(kw_only=True, slots=True)
|
2181
|
-
class YieldStructSeriesElementsError(Exception):
|
2182
|
-
series: Series
|
2183
|
-
|
2184
|
-
|
2185
|
-
@dataclass(kw_only=True, slots=True)
|
2186
|
-
class _YieldStructSeriesElementsDTypeError(YieldStructSeriesElementsError):
|
2187
|
-
@override
|
2188
|
-
def __str__(self) -> str:
|
2189
|
-
return f"Series must have Struct-dtype; got {self.series.dtype}"
|
2190
|
-
|
2191
|
-
|
2192
|
-
@dataclass(kw_only=True, slots=True)
|
2193
|
-
class _YieldStructSeriesElementsNullElementsError(YieldStructSeriesElementsError):
|
2194
|
-
@override
|
2195
|
-
def __str__(self) -> str:
|
2196
|
-
return f"Series must not have nulls; got {self.series}"
|
2197
|
-
|
2198
|
-
|
2199
|
-
##
|
2200
|
-
|
2201
|
-
|
2202
|
-
@overload
|
2203
|
-
def yield_struct_series_dataclasses(
|
2204
|
-
series: Series,
|
2205
|
-
cls: type[TDataclass],
|
2206
|
-
/,
|
2207
|
-
*,
|
2208
|
-
forward_references: dict[str, Any] | None = None,
|
2209
|
-
check_types: bool = True,
|
2210
|
-
strict: Literal[True],
|
2211
|
-
) -> Iterator[TDataclass]: ...
|
2212
|
-
@overload
|
2213
|
-
def yield_struct_series_dataclasses(
|
2214
|
-
series: Series,
|
2215
|
-
cls: type[TDataclass],
|
2216
|
-
/,
|
2217
|
-
*,
|
2218
|
-
forward_references: dict[str, Any] | None = None,
|
2219
|
-
check_types: bool = True,
|
2220
|
-
strict: bool = False,
|
2221
|
-
) -> Iterator[TDataclass | None]: ...
|
2222
|
-
def yield_struct_series_dataclasses(
|
2223
|
-
series: Series,
|
2224
|
-
cls: type[TDataclass],
|
2225
|
-
/,
|
2226
|
-
*,
|
2227
|
-
forward_references: dict[str, Any] | None = None,
|
2228
|
-
check_types: bool = True,
|
2229
|
-
strict: bool = False,
|
2230
|
-
) -> Iterator[TDataclass | None]:
|
2231
|
-
"""Yield the elements of a struct-dtype Series as dataclasses."""
|
2232
|
-
from dacite import Config, from_dict
|
2233
|
-
|
2234
|
-
config = Config(
|
2235
|
-
forward_references=forward_references, check_types=check_types, strict=True
|
2236
|
-
)
|
2237
|
-
for value in yield_struct_series_elements(series, strict=strict):
|
2238
|
-
if value is None:
|
2239
|
-
yield None
|
2240
|
-
else:
|
2241
|
-
yield from_dict(cls, cast("Data", value), config=config)
|
2242
|
-
|
2243
|
-
|
2244
|
-
##
|
2245
|
-
|
2246
|
-
|
2247
2129
|
def zoned_datetime(
|
2248
2130
|
*, time_unit: TimeUnit = "us", time_zone: TimeZoneLike = UTC
|
2249
2131
|
) -> Datetime:
|
@@ -2272,7 +2154,6 @@ __all__ = [
|
|
2272
2154
|
"IsNullStructSeriesError",
|
2273
2155
|
"SetFirstRowAsColumnsError",
|
2274
2156
|
"StructFromDataClassError",
|
2275
|
-
"YieldStructSeriesElementsError",
|
2276
2157
|
"acf",
|
2277
2158
|
"adjust_frequencies",
|
2278
2159
|
"append_dataclass",
|
@@ -2319,7 +2200,5 @@ __all__ = [
|
|
2319
2200
|
"try_reify_expr",
|
2320
2201
|
"uniform",
|
2321
2202
|
"unique_element",
|
2322
|
-
"yield_struct_series_dataclasses",
|
2323
|
-
"yield_struct_series_elements",
|
2324
2203
|
"zoned_datetime",
|
2325
2204
|
]
|
utilities/types.py
CHANGED
@@ -140,6 +140,7 @@ type RoundMode = Literal[
|
|
140
140
|
"standard-tie-toward-zero",
|
141
141
|
"standard-tie-away-zero",
|
142
142
|
]
|
143
|
+
type Sign = Literal[-1, 0, 1]
|
143
144
|
|
144
145
|
|
145
146
|
# operator
|
@@ -291,6 +292,7 @@ __all__ = [
|
|
291
292
|
"RoundMode",
|
292
293
|
"Seed",
|
293
294
|
"SerializeObjectExtra",
|
295
|
+
"Sign",
|
294
296
|
"StrMapping",
|
295
297
|
"StrStrMapping",
|
296
298
|
"SupportsAbs",
|
File without changes
|
File without changes
|