dycw-utilities 0.153.1__py3-none-any.whl → 0.153.3__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.153.1
3
+ Version: 0.153.3
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=tLMJ7LzsnMye2vQj1HzCBHT0fuYeBMXUcof9VDP_uyk,60
1
+ utilities/__init__.py,sha256=1GHQrcKaEUZf3pfIY7NBsyrMxgkxqFe8199dJVber6A,60
2
2
  utilities/altair.py,sha256=92E2lCdyHY4Zb-vCw6rEJIsWdKipuu-Tu2ab1ufUfAk,9079
3
3
  utilities/asyncio.py,sha256=QXkTtugXkqtYt7Do23zgYErqzdp6jwzPpV_SP9fJ1gI,16780
4
4
  utilities/atomicwrites.py,sha256=tPo6r-Rypd9u99u66B9z86YBPpnLrlHtwox_8Z7T34Y,5790
@@ -45,7 +45,7 @@ utilities/parse.py,sha256=JcJn5yXKhIWXBCwgBdPsyu7Hvcuw6kyEdqvaebCaI9k,17951
45
45
  utilities/pathlib.py,sha256=qGuU8XPmdgGpy8tOMUgelfXx3kxI8h9IaV3TI_06QGE,8428
46
46
  utilities/pickle.py,sha256=MBT2xZCsv0pH868IXLGKnlcqNx2IRVKYNpRcqiQQqxw,653
47
47
  utilities/platform.py,sha256=pTn7gw6N4T6LdKrf0virwarof_mze9WtoQlrGMzhGVI,2798
48
- utilities/polars.py,sha256=uxV4liIQoCO92aERDO-AMfa8Es_-xCKgwZoyTO3PazQ,74410
48
+ utilities/polars.py,sha256=Ba1XxJZ3Q8i_mHkcNxjo4aGuMKwRsCdh0mIDI-V_HXw,76581
49
49
  utilities/polars_ols.py,sha256=Uc9V5kvlWZ5cU93lKZ-cfAKdVFFw81tqwLW9PxtUvMs,5618
50
50
  utilities/postgres.py,sha256=70BPcb_Na0LqDXJfqu0JwkHkGrwyuKpIVooSm6NlRn8,12467
51
51
  utilities/pottery.py,sha256=HJ96oLRarTP37Vhg0WTyB3yAu2hETeg6HgRmpDIqyUs,6581
@@ -74,7 +74,7 @@ utilities/threading.py,sha256=GvBOp4CyhHfN90wGXZuA2VKe9fGzMaEa7oCl4f3nnPU,1009
74
74
  utilities/timer.py,sha256=oXfTii6ymu57niP0BDGZjFD55LEHi2a19kqZKiTgaFQ,2588
75
75
  utilities/traceback.py,sha256=e0BpxNMybVmELHGsYM5N6LVbfmn0jLhefLoa81NjZBg,9100
76
76
  utilities/typed_settings.py,sha256=SFWqS3lAzV7IfNRwqFcTk0YynTcQ7BmrcW2mr_KUnos,4466
77
- utilities/types.py,sha256=DMHTom46_vSwM4taulNgw6SEzseVggCVxX7e2JZnij8,18404
77
+ utilities/types.py,sha256=SE5UTkI7EVdg_gVehgn9fRQ7TAOi2C1LpEm8qLIhZcs,18455
78
78
  utilities/typing.py,sha256=Z-_XDaWyT_6wIo3qfNK-hvRlzxP2Jxa9PgXzm5rDYRA,13790
79
79
  utilities/tzdata.py,sha256=fgNVj66yUbCSI_-vrRVzSD3gtf-L_8IEJEPjP_Jel5Y,266
80
80
  utilities/tzlocal.py,sha256=KyCXEgCTjqGFx-389JdTuhMRUaT06U1RCMdWoED-qro,728
@@ -87,8 +87,8 @@ utilities/zoneinfo.py,sha256=FBMcUQ4662Aq8SsuCL1OAhDQiyANmVjtb-C30DRrWoE,1966
87
87
  utilities/pytest_plugins/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
88
88
  utilities/pytest_plugins/pytest_randomly.py,sha256=B1qYVlExGOxTywq2r1SMi5o7btHLk2PNdY_b1p98dkE,409
89
89
  utilities/pytest_plugins/pytest_regressions.py,sha256=9v8kAXDM2ycIXJBimoiF4EgrwbUvxTycFWJiGR_GHhM,1466
90
- dycw_utilities-0.153.1.dist-info/METADATA,sha256=5qPYBod9hSVQarpW6SVN-iqMQgPfp9YYT6u5wPGAAVk,1696
91
- dycw_utilities-0.153.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
92
- dycw_utilities-0.153.1.dist-info/entry_points.txt,sha256=BOD_SoDxwsfJYOLxhrSXhHP_T7iw-HXI9f2WVkzYxvQ,135
93
- dycw_utilities-0.153.1.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
94
- dycw_utilities-0.153.1.dist-info/RECORD,,
90
+ dycw_utilities-0.153.3.dist-info/METADATA,sha256=xSL1sIennAtafYoihcSuowIbjg7Wywuh9l5u3kLM7qg,1696
91
+ dycw_utilities-0.153.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
92
+ dycw_utilities-0.153.3.dist-info/entry_points.txt,sha256=BOD_SoDxwsfJYOLxhrSXhHP_T7iw-HXI9f2WVkzYxvQ,135
93
+ dycw_utilities-0.153.3.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
94
+ dycw_utilities-0.153.3.dist-info/RECORD,,
utilities/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.153.1"
3
+ __version__ = "0.153.3"
utilities/polars.py CHANGED
@@ -33,6 +33,7 @@ from polars import (
33
33
  any_horizontal,
34
34
  col,
35
35
  concat,
36
+ datetime_range,
36
37
  int_range,
37
38
  lit,
38
39
  struct,
@@ -49,6 +50,7 @@ from polars.exceptions import (
49
50
  )
50
51
  from polars.schema import Schema
51
52
  from polars.testing import assert_frame_equal, assert_series_equal
53
+ from whenever import ZonedDateTime
52
54
 
53
55
  from utilities.dataclasses import _YieldFieldsInstance, yield_fields
54
56
  from utilities.errors import ImpossibleCaseError
@@ -129,6 +131,7 @@ DatetimeUSEastern = Datetime(time_zone="US/Eastern")
129
131
  DatetimeUTC = Datetime(time_zone="UTC")
130
132
  _FINITE_EWM_MIN_WEIGHT = 0.9999
131
133
 
134
+
132
135
  ##
133
136
 
134
137
 
@@ -2021,6 +2024,19 @@ def normal(
2021
2024
  ##
2022
2025
 
2023
2026
 
2027
+ def offset_datetime(
2028
+ datetime: ZonedDateTime, offset: str, /, *, n: int = 1
2029
+ ) -> ZonedDateTime:
2030
+ """Offset a datetime as `polars` would."""
2031
+ sr = Series(values=[datetime.py_datetime()])
2032
+ for _ in range(n):
2033
+ sr = sr.dt.offset_by(offset)
2034
+ return ZonedDateTime.from_py_datetime(sr.item())
2035
+
2036
+
2037
+ ##
2038
+
2039
+
2024
2040
  @overload
2025
2041
  def order_of_magnitude(column: ExprLike, /, *, round_: bool = False) -> Expr: ...
2026
2042
  @overload
@@ -2041,6 +2057,75 @@ def order_of_magnitude(
2041
2057
  ##
2042
2058
 
2043
2059
 
2060
+ @overload
2061
+ def period_range(
2062
+ start: ZonedDateTime,
2063
+ end_or_length: ZonedDateTime | int,
2064
+ /,
2065
+ *,
2066
+ interval: str = "1d",
2067
+ time_unit: TimeUnit | None = None,
2068
+ time_zone: TimeZoneLike | None = None,
2069
+ eager: Literal[True],
2070
+ ) -> Series: ...
2071
+ @overload
2072
+ def period_range(
2073
+ start: ZonedDateTime,
2074
+ end_or_length: ZonedDateTime | int,
2075
+ /,
2076
+ *,
2077
+ interval: str = "1d",
2078
+ time_unit: TimeUnit | None = None,
2079
+ time_zone: TimeZoneLike | None = None,
2080
+ eager: Literal[False] = False,
2081
+ ) -> Expr: ...
2082
+ @overload
2083
+ def period_range(
2084
+ start: ZonedDateTime,
2085
+ end_or_length: ZonedDateTime | int,
2086
+ /,
2087
+ *,
2088
+ interval: str = "1d",
2089
+ time_unit: TimeUnit | None = None,
2090
+ time_zone: TimeZoneLike | None = None,
2091
+ eager: bool = False,
2092
+ ) -> Series | Expr: ...
2093
+ def period_range(
2094
+ start: ZonedDateTime,
2095
+ end_or_length: ZonedDateTime | int,
2096
+ /,
2097
+ *,
2098
+ interval: str = "1d",
2099
+ time_unit: TimeUnit | None = None,
2100
+ time_zone: TimeZoneLike | None = None,
2101
+ eager: bool = False,
2102
+ ) -> Series | Expr:
2103
+ """Construct a period range."""
2104
+ time_zone_use = None if time_zone is None else ensure_time_zone(time_zone).key
2105
+ match end_or_length:
2106
+ case ZonedDateTime() as end:
2107
+ ...
2108
+ case int() as length:
2109
+ end = offset_datetime(start, interval, n=length)
2110
+ case never:
2111
+ assert_never(never)
2112
+ starts = datetime_range(
2113
+ start.py_datetime(),
2114
+ end.py_datetime(),
2115
+ interval,
2116
+ closed="left",
2117
+ time_unit=time_unit,
2118
+ time_zone=time_zone_use,
2119
+ eager=eager,
2120
+ ).alias("start")
2121
+ ends = (starts.dt.offset_by(interval)).alias("end")
2122
+ period = struct(starts, ends)
2123
+ return try_reify_expr(period, starts, ends)
2124
+
2125
+
2126
+ ##
2127
+
2128
+
2044
2129
  def reify_exprs(
2045
2130
  *exprs: IntoExprColumn, **named_exprs: IntoExprColumn
2046
2131
  ) -> Expr | Series | DataFrame:
@@ -2529,7 +2614,9 @@ __all__ = [
2529
2614
  "nan_sum_agg",
2530
2615
  "nan_sum_cols",
2531
2616
  "normal",
2617
+ "offset_datetime",
2532
2618
  "order_of_magnitude",
2619
+ "period_range",
2533
2620
  "read_dataframe",
2534
2621
  "read_series",
2535
2622
  "replace_time_zone",
utilities/types.py CHANGED
@@ -39,7 +39,6 @@ _T_contra = TypeVar("_T_contra", contravariant=True)
39
39
 
40
40
 
41
41
  # basic
42
- type BoolLike = MaybeStr[bool]
43
42
  type OpenMode = Literal[
44
43
  "r",
45
44
  "w",
@@ -63,13 +62,15 @@ type OpenMode = Literal[
63
62
  "a+b",
64
63
  ]
65
64
  type MaybeCallable[T] = T | Callable[[], T]
66
- type MaybeCallableBoolLike = MaybeCallable[BoolLike]
67
65
  type MaybeStr[T] = T | str
68
66
  type MaybeType[T] = T | type[T]
69
67
  type StrMapping = Mapping[str, Any]
70
68
  type StrStrMapping = Mapping[str, str]
71
- type TypeLike[T] = type[T] | tuple[type[T], ...]
72
69
  type TupleOrStrMapping = tuple[Any, ...] | StrMapping
70
+ type TypeLike[T] = type[T] | tuple[type[T], ...]
71
+ # basic - derived
72
+ type MaybeCallableBoolLike = MaybeCallable[BoolLike]
73
+ type BoolLike = MaybeStr[bool]
73
74
 
74
75
 
75
76
  # asyncio
@@ -114,12 +115,12 @@ IPv6AddressLike = MaybeStr[IPv6Address]
114
115
 
115
116
 
116
117
  # iterables
117
- type SequenceLT[T] = list[T] | tuple[T, ...]
118
- # iterables - maybe
119
118
  type MaybeCollection[T] = T | Collection[T]
120
119
  type MaybeIterable[T] = T | Iterable[T]
120
+ type MaybeList[T] = T | list[T]
121
+ type SequenceLT[T] = list[T] | tuple[T, ...]
122
+ # iterables - dervied
121
123
  type MaybeSequence[T] = T | SequenceLT[T]
122
- # iterables - str
123
124
  type SequenceStr = SequenceLT[str]
124
125
  type CollectionStr = dict[str, Any] | frozenset[str] | set[str] | SequenceStr
125
126
  # iterables - maybe str
@@ -299,6 +300,7 @@ __all__ = [
299
300
  "MaybeCollectionStr",
300
301
  "MaybeCoro",
301
302
  "MaybeIterable",
303
+ "MaybeList",
302
304
  "MaybeSequence",
303
305
  "MaybeSequenceStr",
304
306
  "MaybeStr",