dycw-utilities 0.138.10__py3-none-any.whl → 0.138.12__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.138.10
3
+ Version: 0.138.12
4
4
  Author-email: Derek Wan <d.wan@icloud.com>
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -12,7 +12,7 @@ Provides-Extra: logging
12
12
  Requires-Dist: coloredlogs<15.1,>=15.0.1; extra == 'logging'
13
13
  Provides-Extra: test
14
14
  Requires-Dist: dycw-pytest-only<2.2,>=2.1.1; extra == 'test'
15
- Requires-Dist: hypothesis<6.136,>=6.135.14; extra == 'test'
15
+ Requires-Dist: hypothesis<6.136,>=6.135.16; extra == 'test'
16
16
  Requires-Dist: pudb<2025.2,>=2025.1; extra == 'test'
17
17
  Requires-Dist: pytest-asyncio<1.1,>=1.0.0; extra == 'test'
18
18
  Requires-Dist: pytest-cov<6.2,>=6.1.1; extra == 'test'
@@ -1,4 +1,4 @@
1
- utilities/__init__.py,sha256=KXSG109KauV-mzYqWH_b1979j4n9biCSq0kQFI5m5Z4,61
1
+ utilities/__init__.py,sha256=8Og3Xw4iUhz4bYD_NYUCU8ER2AMFKi6vrYO5Sk_f95M,61
2
2
  utilities/aiolimiter.py,sha256=mD0wEiqMgwpty4XTbawFpnkkmJS6R4JRsVXFUaoitSU,628
3
3
  utilities/altair.py,sha256=HeZBVUocjkrTNwwKrClppsIqgNFF-ykv05HfZSoHYno,9104
4
4
  utilities/asyncio.py,sha256=dcGeKQzjLBXxKzZkVIk5oZsFXEcynVbRB9iNB5XEDZk,38526
@@ -46,7 +46,7 @@ utilities/pathlib.py,sha256=5p9MI8m7iUFksNVGiLavN4MZ3cj1CpBiLBlgaCR0LCs,8334
46
46
  utilities/period.py,sha256=6jEff_qAiE7xdFaQ1DnKgNf10D2wHhzt7hQXCBoKlgc,6842
47
47
  utilities/pickle.py,sha256=MBT2xZCsv0pH868IXLGKnlcqNx2IRVKYNpRcqiQQqxw,653
48
48
  utilities/platform.py,sha256=5uCKRf_ij7ukJDcbnNfhY2ay9fbrpiNLRO1t2QvcwqQ,2825
49
- utilities/polars.py,sha256=xCeB-pLkezOoQJvgxTdz2rNlaehdhek-HmDztXWn2j0,63266
49
+ utilities/polars.py,sha256=Q7eGBZ-P3tg2HXVk-rF7yceodeuPoj-sfPbYWawqyRM,63886
50
50
  utilities/polars_ols.py,sha256=Uc9V5kvlWZ5cU93lKZ-cfAKdVFFw81tqwLW9PxtUvMs,5618
51
51
  utilities/pottery.py,sha256=RN3XwOEsVAPXvEfsRPmn3ZSKgTzK_c182PNrtksq-bg,3429
52
52
  utilities/pqdm.py,sha256=BTsYPtbKQWwX-iXF4qCkfPG7DPxIB54J989n83bXrIo,3092
@@ -85,11 +85,11 @@ utilities/tzlocal.py,sha256=KyCXEgCTjqGFx-389JdTuhMRUaT06U1RCMdWoED-qro,728
85
85
  utilities/uuid.py,sha256=32p7DGHGM2Btx6PcBvCZvERSWbpupMXqx6FppPoSoTU,612
86
86
  utilities/version.py,sha256=ufhJMmI6KPs1-3wBI71aj5wCukd3sP_m11usLe88DNA,5117
87
87
  utilities/warnings.py,sha256=un1LvHv70PU-LLv8RxPVmugTzDJkkGXRMZTE2-fTQHw,1771
88
- utilities/whenever.py,sha256=R5d9UCNCdAOyjwLUmfH2Vn8Ykee8OHQi2skRTFfbZMM,20492
88
+ utilities/whenever.py,sha256=sUAOQ2sJTRGC1kacGTnMbfQdkypuSiqhTZWZVo21OT8,21545
89
89
  utilities/zipfile.py,sha256=24lQc9ATcJxHXBPc_tBDiJk48pWyRrlxO2fIsFxU0A8,699
90
90
  utilities/zoneinfo.py,sha256=oEH-nL3t4h9uawyZqWDtNtDAl6M-CLpLYGI_nI6DulM,1971
91
- dycw_utilities-0.138.10.dist-info/METADATA,sha256=5_CxObrlGLTgwHzV1c8558AlnuS2yZx8skO-M6OisCM,1639
92
- dycw_utilities-0.138.10.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
93
- dycw_utilities-0.138.10.dist-info/entry_points.txt,sha256=uLj5QWWVXv8tnMaRX3ZGYpt7w1xzLWU6LxbFhELEpkc,68
94
- dycw_utilities-0.138.10.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
95
- dycw_utilities-0.138.10.dist-info/RECORD,,
91
+ dycw_utilities-0.138.12.dist-info/METADATA,sha256=1DfnY3KS8qcT0z9ClK0-Ew_aXn0d5-SIsApG2pminew,1639
92
+ dycw_utilities-0.138.12.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
93
+ dycw_utilities-0.138.12.dist-info/entry_points.txt,sha256=uLj5QWWVXv8tnMaRX3ZGYpt7w1xzLWU6LxbFhELEpkc,68
94
+ dycw_utilities-0.138.12.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
95
+ dycw_utilities-0.138.12.dist-info/RECORD,,
utilities/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.138.10"
3
+ __version__ = "0.138.12"
utilities/polars.py CHANGED
@@ -1833,6 +1833,26 @@ def normal(
1833
1833
  ##
1834
1834
 
1835
1835
 
1836
+ @overload
1837
+ def order_of_magnitude(column: ExprLike, /, *, round_: bool = False) -> Expr: ...
1838
+ @overload
1839
+ def order_of_magnitude(column: Series, /, *, round_: bool = False) -> Series: ...
1840
+ @overload
1841
+ def order_of_magnitude(
1842
+ column: IntoExprColumn, /, *, round_: bool = False
1843
+ ) -> Expr | Series: ...
1844
+ def order_of_magnitude(
1845
+ column: IntoExprColumn, /, *, round_: bool = False
1846
+ ) -> Expr | Series:
1847
+ """Compute the order of magnitude of a column."""
1848
+ column = ensure_expr_or_series(column)
1849
+ result = column.abs().log10()
1850
+ return result.round().cast(Int64) if round_ else result
1851
+
1852
+
1853
+ ##
1854
+
1855
+
1836
1856
  def reify_exprs(
1837
1857
  *exprs: IntoExprColumn, **named_exprs: IntoExprColumn
1838
1858
  ) -> Expr | Series | DataFrame:
@@ -2184,6 +2204,7 @@ __all__ = [
2184
2204
  "nan_sum_agg",
2185
2205
  "nan_sum_cols",
2186
2206
  "normal",
2207
+ "order_of_magnitude",
2187
2208
  "replace_time_zone",
2188
2209
  "set_first_row_as_columns",
2189
2210
  "struct_dtype",
utilities/whenever.py CHANGED
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import datetime as dt
3
4
  from collections.abc import Callable, Iterable, Mapping
4
5
  from dataclasses import dataclass
5
6
  from functools import cache
@@ -553,9 +554,10 @@ def to_local_plain(date_time: ZonedDateTime, /) -> PlainDateTime:
553
554
 
554
555
  def to_nanos(delta: DateTimeDelta, /) -> int:
555
556
  """Compute the number of nanoseconds in a date-time delta."""
556
- months, days, _, _ = delta.in_months_days_secs_nanos()
557
- if months != 0:
558
- raise ToNanosError(months=months)
557
+ try:
558
+ days = to_days(delta.date_part())
559
+ except ToDaysError as error:
560
+ raise ToNanosError(months=error.months) from None
559
561
  return 24 * 60 * 60 * int(1e9) * days + delta.time_part().in_nanoseconds()
560
562
 
561
563
 
@@ -571,6 +573,37 @@ class ToNanosError(Exception):
571
573
  ##
572
574
 
573
575
 
576
+ def to_py_time_delta(delta: DateDelta | TimeDelta | DateTimeDelta, /) -> dt.timedelta:
577
+ """Try convert a DateDelta to a standard library timedelta."""
578
+ match delta:
579
+ case DateDelta():
580
+ return dt.timedelta(days=to_days(delta))
581
+ case TimeDelta():
582
+ nanos = delta.in_nanoseconds()
583
+ micros, remainder = divmod(nanos, 1000)
584
+ if remainder != 0:
585
+ raise ToPyTimeDeltaError(nanoseconds=remainder)
586
+ return dt.timedelta(microseconds=micros)
587
+ case DateTimeDelta():
588
+ return to_py_time_delta(delta.date_part()) + to_py_time_delta(
589
+ delta.time_part()
590
+ )
591
+ case _ as never:
592
+ assert_never(never)
593
+
594
+
595
+ @dataclass(kw_only=True, slots=True)
596
+ class ToPyTimeDeltaError(Exception):
597
+ nanoseconds: int
598
+
599
+ @override
600
+ def __str__(self) -> str:
601
+ return f"Time delta must not contain nanoseconds; got {self.nanoseconds}"
602
+
603
+
604
+ ##
605
+
606
+
574
607
  def to_time_delta(nanos: int, /) -> TimeDelta:
575
608
  """Construct a time delta."""
576
609
  components = _to_time_delta_components(nanos)
@@ -769,6 +802,7 @@ __all__ = [
769
802
  "MinMaxDateError",
770
803
  "ToDaysError",
771
804
  "ToNanosError",
805
+ "ToPyTimeDeltaError",
772
806
  "WheneverLogRecord",
773
807
  "datetime_utc",
774
808
  "format_compact",
@@ -786,6 +820,7 @@ __all__ = [
786
820
  "to_days",
787
821
  "to_local_plain",
788
822
  "to_nanos",
823
+ "to_py_time_delta",
789
824
  "to_zoned_date_time",
790
825
  "two_digit_year_month",
791
826
  ]