dycw-utilities 0.165.1__py3-none-any.whl → 0.165.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.
- {dycw_utilities-0.165.1.dist-info → dycw_utilities-0.165.3.dist-info}/METADATA +1 -1
- {dycw_utilities-0.165.1.dist-info → dycw_utilities-0.165.3.dist-info}/RECORD +8 -8
- utilities/__init__.py +1 -1
- utilities/polars.py +30 -0
- utilities/typing.py +53 -10
- {dycw_utilities-0.165.1.dist-info → dycw_utilities-0.165.3.dist-info}/WHEEL +0 -0
- {dycw_utilities-0.165.1.dist-info → dycw_utilities-0.165.3.dist-info}/entry_points.txt +0 -0
- {dycw_utilities-0.165.1.dist-info → dycw_utilities-0.165.3.dist-info}/licenses/LICENSE +0 -0
@@ -1,4 +1,4 @@
|
|
1
|
-
utilities/__init__.py,sha256=
|
1
|
+
utilities/__init__.py,sha256=dGyOX1Z3m0mhIPCR1cqAXlybAWUxvEasnTNSAfT9Fh8,60
|
2
2
|
utilities/aeventkit.py,sha256=ddoleSwW9zdc2tjX5Ge0pMKtYwV_JMxhHYOxnWX2AGM,12609
|
3
3
|
utilities/altair.py,sha256=92E2lCdyHY4Zb-vCw6rEJIsWdKipuu-Tu2ab1ufUfAk,9079
|
4
4
|
utilities/asyncio.py,sha256=PUedzQ5deqlSECQ33sam9cRzI9TnygHz3FdOqWJWPTM,15288
|
@@ -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=
|
48
|
+
utilities/polars.py,sha256=6_k8cU7LePQ942Qfqe5l_tR8ND0M0bLlpnaMvDbRCM8,81754
|
49
49
|
utilities/polars_ols.py,sha256=LNTFNLPuYW7fcAHymlbnams_DhitToblYvib3mhKbwI,5615
|
50
50
|
utilities/postgres.py,sha256=ynCTTaF-bVEOSW-KEAR-dlLh_hYjeVVjm__-4pEU8Zk,12269
|
51
51
|
utilities/pottery.py,sha256=ggMN72Y7wx7Js8VN6eyNyodpm8TIYqZHGghkDPXIVWk,3949
|
@@ -76,7 +76,7 @@ utilities/timer.py,sha256=oXfTii6ymu57niP0BDGZjFD55LEHi2a19kqZKiTgaFQ,2588
|
|
76
76
|
utilities/traceback.py,sha256=b1nSvlyrGmI1MyZLkkoLVET3DQBSGt9qqIlAAQbyjEw,9629
|
77
77
|
utilities/typed_settings.py,sha256=SFWqS3lAzV7IfNRwqFcTk0YynTcQ7BmrcW2mr_KUnos,4466
|
78
78
|
utilities/types.py,sha256=oeH-hEC3-67Eja4nLz-Nj9WvK6Z9-3T1zobO_XJpuVg,18735
|
79
|
-
utilities/typing.py,sha256=
|
79
|
+
utilities/typing.py,sha256=QYoCIc71e_u5W-kBeiNzrD-GXxpLtMOGc9PqgZjMXeE,25274
|
80
80
|
utilities/tzdata.py,sha256=fgNVj66yUbCSI_-vrRVzSD3gtf-L_8IEJEPjP_Jel5Y,266
|
81
81
|
utilities/tzlocal.py,sha256=KyCXEgCTjqGFx-389JdTuhMRUaT06U1RCMdWoED-qro,728
|
82
82
|
utilities/uuid.py,sha256=nQZs6tFX4mqtc2Ku3KqjloYCqwpTKeTj8eKwQwh3FQI,1572
|
@@ -88,8 +88,8 @@ utilities/zoneinfo.py,sha256=tdIScrTB2-B-LH0ukb1HUXKooLknOfJNwHk10MuMYvA,3619
|
|
88
88
|
utilities/pytest_plugins/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
|
89
89
|
utilities/pytest_plugins/pytest_randomly.py,sha256=B1qYVlExGOxTywq2r1SMi5o7btHLk2PNdY_b1p98dkE,409
|
90
90
|
utilities/pytest_plugins/pytest_regressions.py,sha256=9v8kAXDM2ycIXJBimoiF4EgrwbUvxTycFWJiGR_GHhM,1466
|
91
|
-
dycw_utilities-0.165.
|
92
|
-
dycw_utilities-0.165.
|
93
|
-
dycw_utilities-0.165.
|
94
|
-
dycw_utilities-0.165.
|
95
|
-
dycw_utilities-0.165.
|
91
|
+
dycw_utilities-0.165.3.dist-info/METADATA,sha256=pkTtRCmg_YK5SUclEGBHKWThH6nFfAdR3vn_EJZjGO8,1696
|
92
|
+
dycw_utilities-0.165.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
93
|
+
dycw_utilities-0.165.3.dist-info/entry_points.txt,sha256=BOD_SoDxwsfJYOLxhrSXhHP_T7iw-HXI9f2WVkzYxvQ,135
|
94
|
+
dycw_utilities-0.165.3.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
|
95
|
+
dycw_utilities-0.165.3.dist-info/RECORD,,
|
utilities/__init__.py
CHANGED
utilities/polars.py
CHANGED
@@ -105,6 +105,7 @@ from utilities.whenever import (
|
|
105
105
|
from utilities.zoneinfo import UTC, to_time_zone_name
|
106
106
|
|
107
107
|
if TYPE_CHECKING:
|
108
|
+
import datetime as dt
|
108
109
|
from collections.abc import Callable, Iterable, Iterator, Mapping, Sequence
|
109
110
|
from collections.abc import Set as AbstractSet
|
110
111
|
|
@@ -2460,6 +2461,34 @@ class RoundToFloatError(Exception):
|
|
2460
2461
|
##
|
2461
2462
|
|
2462
2463
|
|
2464
|
+
def search_period(
|
2465
|
+
series: Series,
|
2466
|
+
date_time: ZonedDateTime,
|
2467
|
+
/,
|
2468
|
+
*,
|
2469
|
+
start_or_end: Literal["start", "end"] = "end",
|
2470
|
+
) -> int | None:
|
2471
|
+
"""Search a series of periods for the one containing a given date-time."""
|
2472
|
+
start, end = [series.struct[k] for k in ["start", "end"]]
|
2473
|
+
py_date_time = date_time.py_datetime()
|
2474
|
+
match start_or_end:
|
2475
|
+
case "start":
|
2476
|
+
index = end.search_sorted(py_date_time, side="right")
|
2477
|
+
if index >= len(series):
|
2478
|
+
return None
|
2479
|
+
item: dt.datetime = series[index]["start"]
|
2480
|
+
return index if py_date_time >= item else None
|
2481
|
+
case "end":
|
2482
|
+
index = end.search_sorted(py_date_time, side="left")
|
2483
|
+
if index >= len(series):
|
2484
|
+
return None
|
2485
|
+
item: dt.datetime = series[index]["start"]
|
2486
|
+
return index if py_date_time > item else None
|
2487
|
+
|
2488
|
+
|
2489
|
+
##
|
2490
|
+
|
2491
|
+
|
2463
2492
|
def select_exact(
|
2464
2493
|
df: DataFrame, /, *columns: IntoExprColumn, drop: MaybeIterable[str] | None = None
|
2465
2494
|
) -> DataFrame:
|
@@ -2750,6 +2779,7 @@ __all__ = [
|
|
2750
2779
|
"read_series",
|
2751
2780
|
"replace_time_zone",
|
2752
2781
|
"round_to_float",
|
2782
|
+
"search_period",
|
2753
2783
|
"select_exact",
|
2754
2784
|
"serialize_dataframe",
|
2755
2785
|
"set_first_row_as_columns",
|
utilities/typing.py
CHANGED
@@ -6,12 +6,14 @@ from dataclasses import dataclass, is_dataclass
|
|
6
6
|
from functools import partial
|
7
7
|
from itertools import chain
|
8
8
|
from pathlib import Path
|
9
|
+
from re import search
|
9
10
|
from types import NoneType, UnionType
|
10
11
|
from typing import (
|
11
12
|
Any,
|
12
13
|
ForwardRef,
|
13
14
|
Literal,
|
14
15
|
NamedTuple,
|
16
|
+
NotRequired,
|
15
17
|
Optional, # pyright: ignore[reportDeprecated]
|
16
18
|
TypeAliasType,
|
17
19
|
TypeGuard,
|
@@ -56,6 +58,18 @@ def get_args(obj: Any, /, *, optional_drop_none: bool = False) -> tuple[Any, ...
|
|
56
58
|
##
|
57
59
|
|
58
60
|
|
61
|
+
def get_forward_ref_args(obj: Any, /) -> Mapping[str, str]:
|
62
|
+
"""Get the forward args."""
|
63
|
+
return {
|
64
|
+
k: v.__forward_arg__
|
65
|
+
for k, v in obj.__annotations__.items()
|
66
|
+
if isinstance(v, ForwardRef)
|
67
|
+
}
|
68
|
+
|
69
|
+
|
70
|
+
##
|
71
|
+
|
72
|
+
|
59
73
|
def get_literal_elements(obj: Any, /) -> list[Any]:
|
60
74
|
"""Get the elements of a literal annotation."""
|
61
75
|
return _get_literal_elements_inner(obj)
|
@@ -151,21 +165,20 @@ def get_type_hints(
|
|
151
165
|
globalns_use = globals() | ({} if globalns is None else dict(globalns))
|
152
166
|
localns_use = {} if localns is None else dict(localns)
|
153
167
|
result: dict[str, Any] = obj.__annotations__
|
154
|
-
result =
|
155
|
-
k: v.__forward_arg__ if isinstance(v, ForwardRef) else v
|
156
|
-
for k, v in result.items()
|
157
|
-
}
|
168
|
+
result = result | dict(get_forward_ref_args(obj))
|
158
169
|
try:
|
159
|
-
hints = _get_type_hints(
|
170
|
+
hints = _get_type_hints(
|
171
|
+
obj, globalns=globalns_use, localns=localns_use, include_extras=True
|
172
|
+
)
|
160
173
|
except NameError as error:
|
161
174
|
if warn_name_errors:
|
162
175
|
warn(f"Error getting type hints for {obj!r}; {error}", stacklevel=2)
|
163
176
|
else:
|
164
|
-
result
|
177
|
+
result = result | {
|
165
178
|
key: value
|
166
179
|
for key, value in hints.items()
|
167
180
|
if (key not in result) or isinstance(result[key], str)
|
168
|
-
}
|
181
|
+
}
|
169
182
|
return result
|
170
183
|
|
171
184
|
|
@@ -393,17 +406,21 @@ def _is_instance_typed_dict[T: _TypedDictMeta](
|
|
393
406
|
hints = get_type_hints(
|
394
407
|
type_, globalns=globalns, localns=localns, warn_name_errors=warn_name_errors
|
395
408
|
)
|
396
|
-
|
409
|
+
optional = {
|
410
|
+
k for k, v in type_.__annotations__.items() if is_not_required_annotation(v)
|
411
|
+
}
|
412
|
+
required = {k: v for k, v in hints.items() if k not in optional}
|
413
|
+
if not set(obj).issuperset(required):
|
397
414
|
return False
|
398
415
|
return all(
|
399
416
|
is_instance_gen(
|
400
417
|
obj[k],
|
401
|
-
|
418
|
+
required[k],
|
402
419
|
globalns=globalns,
|
403
420
|
localns=localns,
|
404
421
|
warn_name_errors=warn_name_errors,
|
405
422
|
)
|
406
|
-
for k in
|
423
|
+
for k in required
|
407
424
|
)
|
408
425
|
|
409
426
|
|
@@ -577,6 +594,30 @@ def _is_namedtuple_core(obj: Any, /) -> bool:
|
|
577
594
|
##
|
578
595
|
|
579
596
|
|
597
|
+
def is_not_required_annotation(obj: Any) -> bool:
|
598
|
+
"""Check if an annotation is not required."""
|
599
|
+
if is_not_required_type(obj):
|
600
|
+
return True
|
601
|
+
match obj:
|
602
|
+
case str() as text:
|
603
|
+
return bool(search("NotRequired", text))
|
604
|
+
case ForwardRef() as fr:
|
605
|
+
return is_not_required_annotation(fr.__forward_arg__)
|
606
|
+
case _:
|
607
|
+
return False
|
608
|
+
|
609
|
+
|
610
|
+
##
|
611
|
+
|
612
|
+
|
613
|
+
def is_not_required_type(obj: Any, /) -> bool:
|
614
|
+
"""Check if an object is a not-required type annotation."""
|
615
|
+
return (obj is NotRequired) or _is_annotation_of_type(obj, NotRequired)
|
616
|
+
|
617
|
+
|
618
|
+
##
|
619
|
+
|
620
|
+
|
580
621
|
def is_optional_type(obj: Any, /) -> bool:
|
581
622
|
"""Check if an object is an optional type annotation."""
|
582
623
|
is_optional = _is_annotation_of_type(obj, Optional) # pyright: ignore[reportDeprecated]
|
@@ -889,6 +930,8 @@ __all__ = [
|
|
889
930
|
"is_mapping_type",
|
890
931
|
"is_namedtuple_class",
|
891
932
|
"is_namedtuple_instance",
|
933
|
+
"is_not_required_annotation",
|
934
|
+
"is_not_required_type",
|
892
935
|
"is_optional_type",
|
893
936
|
"is_sequence_of",
|
894
937
|
"is_sequence_of_tuple_or_str_mapping",
|
File without changes
|
File without changes
|
File without changes
|