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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dycw-utilities
3
- Version: 0.112.14
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=CIhTEeq-pbU3Wh1aAi3xUU9ERIQ-sVu7LwD2EjBeNps,61
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=2BloGVlH85tNZjFQiKXNk00Qwe9aovoV7cwxqFRG2l8,32598
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=2Yy9gZ7BR4LXR4nlX7outFAjd4dpb3lgUo7ji_sdylY,45076
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=TexfvLCI12d9Sw5_W4pKVBZ3nRr3zk2iPkcEU7xdEWU,26771
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=bo2Rhukk2eXxe1RMfu2uvEjTQTd9SmOi8mGW4BRG82c,67288
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=kVY71hZkcnyYNIlYSse0mLm8yeP3OBkzhDPMME6jXxo,18126
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.112.14.dist-info/METADATA,sha256=j1h-dnkoSmxpcQeVqNPWmJynfitGt61YQFT3liw1LuU,13005
91
- dycw_utilities-0.112.14.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
92
- dycw_utilities-0.112.14.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
93
- dycw_utilities-0.112.14.dist-info/RECORD,,
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
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.112.14"
3
+ __version__ = "0.113.1"
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 OneStrEmptyError, OneStrNonUniqueError, one_str
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, /) -> Literal[-1, 0, 1]:
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("Literal[-1, 0, 1]", (x > y) - (x < y))
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[Literal[-1, 0, 1]] = (
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("Literal[-1, 0, 1]", (x > y) - (x < y))
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("Literal[-1, 0, 1]", (x > y) - (x < y))
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("Literal[-1, 0, 1]", (x_utc > y_utc) - (x_utc < y_utc))
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
- "Literal[-1, 0, 1]",
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, /) -> Literal[-1, 0, 1]:
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("Literal[-1, 0, 1]", (x > y) - (x < y))
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
- ) -> Literal[-1, 0, 1]:
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, Iterable, Iterator, Mapping, Sequence
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",