dycw-utilities 0.112.1__py3-none-any.whl → 0.112.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.112.1.dist-info → dycw_utilities-0.112.3.dist-info}/METADATA +1 -1
- {dycw_utilities-0.112.1.dist-info → dycw_utilities-0.112.3.dist-info}/RECORD +9 -9
- utilities/__init__.py +1 -1
- utilities/polars.py +7 -6
- utilities/sentinel.py +1 -1
- utilities/text.py +3 -3
- utilities/typing.py +76 -11
- {dycw_utilities-0.112.1.dist-info → dycw_utilities-0.112.3.dist-info}/WHEEL +0 -0
- {dycw_utilities-0.112.1.dist-info → dycw_utilities-0.112.3.dist-info}/licenses/LICENSE +0 -0
@@ -1,4 +1,4 @@
|
|
1
|
-
utilities/__init__.py,sha256=
|
1
|
+
utilities/__init__.py,sha256=z7R-tij8PUsszk8bX9FviCXCNFWurmc0egXzyuNqIdY,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
|
@@ -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=q8a2hTX9tyPxtxUarIm2BxlnckIwF1RCpcJz03OoIoY,58458
|
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
|
@@ -62,7 +62,7 @@ utilities/redis.py,sha256=fAUbfOlCmxcxhh47PXQX63w0CU5iOFKfdUJ7jDn9ntM,22096
|
|
62
62
|
utilities/reprlib.py,sha256=Re9bk3n-kC__9DxQmRlevqFA86pE6TtVfWjUgpbVOv0,1849
|
63
63
|
utilities/rich.py,sha256=t50MwwVBsoOLxzmeVFSVpjno4OW6Ufum32skXbV8-Bs,1911
|
64
64
|
utilities/scipy.py,sha256=X6ROnHwiUhAmPhM0jkfEh0-Fd9iRvwiqtCQMOLmOQF8,945
|
65
|
-
utilities/sentinel.py,sha256=
|
65
|
+
utilities/sentinel.py,sha256=3jIwgpMekWgDAxPDA_hXMP2St43cPhciKN3LWiZ7kv0,1248
|
66
66
|
utilities/shelve.py,sha256=HZsMwK4tcIfg3sh0gApx4-yjQnrY4o3V3ZRimvRhoW0,738
|
67
67
|
utilities/slack_sdk.py,sha256=SeDNMh24IPiEBWoGMdgvrflUaFa9TGlTS03H9-NKaQw,4132
|
68
68
|
utilities/socket.py,sha256=K77vfREvzoVTrpYKo6MZakol0EYu2q1sWJnnZqL0So0,118
|
@@ -73,12 +73,12 @@ utilities/streamlit.py,sha256=U9PJBaKP1IdSykKhPZhIzSPTZsmLsnwbEPZWzNhJPKk,2955
|
|
73
73
|
utilities/sys.py,sha256=h0Xr7Vj86wNalvwJVP1wj5Y0kD_VWm1vzuXZ_jw94mE,2743
|
74
74
|
utilities/tempfile.py,sha256=VqmZJAhTJ1OaVywFzk5eqROV8iJbW9XQ_QYAV0bpdRo,1384
|
75
75
|
utilities/tenacity.py,sha256=1PUvODiBVgeqIh7G5TRt5WWMSqjLYkEqP53itT97WQc,4914
|
76
|
-
utilities/text.py,sha256=
|
76
|
+
utilities/text.py,sha256=c65sonE-vMJtBR8-LIntXUqku7wDQC6p4z69DOSur7o,10947
|
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
80
|
utilities/types.py,sha256=kVY71hZkcnyYNIlYSse0mLm8yeP3OBkzhDPMME6jXxo,18126
|
81
|
-
utilities/typing.py,sha256=
|
81
|
+
utilities/typing.py,sha256=Tppx84LCtZFX8oOzDb2PeUIv9tjNqFWQLuMadN_rAes,13514
|
82
82
|
utilities/tzdata.py,sha256=yCf70NICwAeazN3_JcXhWvRqCy06XJNQ42j7r6gw3HY,1217
|
83
83
|
utilities/tzlocal.py,sha256=3upDNFBvGh1l9njmLR2z2S6K6VxQSb7QizYGUbAH3JU,960
|
84
84
|
utilities/uuid.py,sha256=jJTFxz-CWgltqNuzmythB7iEQ-Q1mCwPevUfKthZT3c,611
|
@@ -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.
|
91
|
-
dycw_utilities-0.112.
|
92
|
-
dycw_utilities-0.112.
|
93
|
-
dycw_utilities-0.112.
|
90
|
+
dycw_utilities-0.112.3.dist-info/METADATA,sha256=t7BNtV2r3OiHx0TWQ9JFxwyrFWjwRWFsAZOMD8HKIDA,13004
|
91
|
+
dycw_utilities-0.112.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
92
|
+
dycw_utilities-0.112.3.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
|
93
|
+
dycw_utilities-0.112.3.dist-info/RECORD,,
|
utilities/__init__.py
CHANGED
utilities/polars.py
CHANGED
@@ -941,10 +941,9 @@ def dataclass_to_schema(
|
|
941
941
|
dtype = struct_dtype(**dtypes)
|
942
942
|
elif field.type_ is dt.datetime:
|
943
943
|
dtype = _dataclass_to_schema_datetime(field)
|
944
|
-
elif is_union_type(field.type_) and set(
|
945
|
-
|
946
|
-
|
947
|
-
}:
|
944
|
+
elif is_union_type(field.type_) and set(
|
945
|
+
get_args(field.type_, optional_drop_none=True)
|
946
|
+
) == {dt.date, dt.datetime}:
|
948
947
|
if is_instance_gen(field.value, dt.date):
|
949
948
|
dtype = Date
|
950
949
|
else:
|
@@ -1002,7 +1001,7 @@ def _dataclass_to_schema_one(
|
|
1002
1001
|
if is_literal_type(obj):
|
1003
1002
|
return pl.Enum(get_args(obj))
|
1004
1003
|
if is_optional_type(obj):
|
1005
|
-
inner_type = one(get_args(obj))
|
1004
|
+
inner_type = one(get_args(obj, optional_drop_none=True))
|
1006
1005
|
return _dataclass_to_schema_one(inner_type, globalns=globalns, localns=localns)
|
1007
1006
|
msg = f"{obj=}"
|
1008
1007
|
raise NotImplementedError(msg)
|
@@ -1732,7 +1731,9 @@ def _struct_from_dataclass_one(
|
|
1732
1731
|
):
|
1733
1732
|
return String
|
1734
1733
|
if is_optional_type(ann):
|
1735
|
-
return _struct_from_dataclass_one(
|
1734
|
+
return _struct_from_dataclass_one(
|
1735
|
+
one(get_args(ann, optional_drop_none=True)), time_zone=time_zone
|
1736
|
+
)
|
1736
1737
|
if is_frozenset_type(ann) or is_list_type(ann) or is_set_type(ann):
|
1737
1738
|
return List(_struct_from_dataclass_one(one(get_args(ann)), time_zone=time_zone))
|
1738
1739
|
raise _StructFromDataClassTypeError(ann=ann)
|
utilities/sentinel.py
CHANGED
@@ -40,7 +40,7 @@ sentinel = Sentinel()
|
|
40
40
|
|
41
41
|
def parse_sentinel(text: str, /) -> Sentinel:
|
42
42
|
"""Parse text into the Sentinel value."""
|
43
|
-
if
|
43
|
+
if search("^(|sentinel|<sentinel>)$", text, flags=IGNORECASE):
|
44
44
|
return sentinel
|
45
45
|
raise ParseSentinelError(text=text)
|
46
46
|
|
utilities/text.py
CHANGED
@@ -25,9 +25,9 @@ DEFAULT_SEPARATOR = ","
|
|
25
25
|
|
26
26
|
def parse_bool(text: str, /) -> bool:
|
27
27
|
"""Parse text into a boolean value."""
|
28
|
-
if
|
28
|
+
if search(r"^(0|False)$", text, flags=IGNORECASE):
|
29
29
|
return False
|
30
|
-
if
|
30
|
+
if search(r"^(1|True)$", text, flags=IGNORECASE):
|
31
31
|
return True
|
32
32
|
raise ParseBoolError(text=text)
|
33
33
|
|
@@ -46,7 +46,7 @@ class ParseBoolError(Exception):
|
|
46
46
|
|
47
47
|
def parse_none(text: str, /) -> None:
|
48
48
|
"""Parse text into the None value."""
|
49
|
-
if
|
49
|
+
if search(r"^(|None)$", text, flags=IGNORECASE):
|
50
50
|
return
|
51
51
|
raise ParseNoneError(text=text)
|
52
52
|
|
utilities/typing.py
CHANGED
@@ -48,14 +48,14 @@ def contains_self(obj: Any, /) -> bool:
|
|
48
48
|
##
|
49
49
|
|
50
50
|
|
51
|
-
def get_args(obj: Any,
|
51
|
+
def get_args(obj: Any, /, *, optional_drop_none: bool = False) -> tuple[Any, ...]:
|
52
52
|
"""Get the arguments of an annotation."""
|
53
53
|
if isinstance(obj, TypeAliasType):
|
54
54
|
return get_args(obj.__value__)
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
return
|
55
|
+
args = _get_args(obj)
|
56
|
+
if is_optional_type(obj) and optional_drop_none:
|
57
|
+
args = tuple(a for a in args if a is not NoneType)
|
58
|
+
return args
|
59
59
|
|
60
60
|
|
61
61
|
##
|
@@ -230,10 +230,26 @@ def is_instance_gen(
|
|
230
230
|
def is_instance_gen(obj: Any, type_: Any, /) -> bool: ...
|
231
231
|
def is_instance_gen(obj: Any, type_: Any, /) -> bool:
|
232
232
|
"""Check if an instance relationship holds, except bool<int."""
|
233
|
-
|
233
|
+
# parent
|
234
|
+
if isinstance(type_, tuple):
|
235
|
+
return any(is_instance_gen(obj, t) for t in type_)
|
236
|
+
if is_literal_type(type_):
|
237
|
+
return obj in get_args(type_)
|
238
|
+
if is_union_type(type_):
|
239
|
+
return any(is_instance_gen(obj, t) for t in get_args(type_))
|
240
|
+
# tuple vs tuple
|
241
|
+
if isinstance(obj, tuple) and is_tuple_type(type_):
|
242
|
+
type_args = get_args(type_)
|
243
|
+
return (len(obj) == len(type_args)) and all(
|
244
|
+
is_instance_gen(o, t) for o, t in zip(obj, type_args, strict=True)
|
245
|
+
)
|
246
|
+
# basic
|
247
|
+
if isinstance(type_, type):
|
248
|
+
return any(_is_instance_gen_type(obj, t) for t in get_type_classes(type_))
|
249
|
+
raise IsInstanceGenError(obj=obj, type_=type_)
|
234
250
|
|
235
251
|
|
236
|
-
def
|
252
|
+
def _is_instance_gen_type(obj: Any, type_: type[_T], /) -> TypeGuard[_T]:
|
237
253
|
return (
|
238
254
|
isinstance(obj, type_)
|
239
255
|
and not (
|
@@ -249,6 +265,16 @@ def _is_instance_gen_one(obj: Any, type_: type[_T], /) -> TypeGuard[_T]:
|
|
249
265
|
)
|
250
266
|
|
251
267
|
|
268
|
+
@dataclass(kw_only=True, slots=True)
|
269
|
+
class IsInstanceGenError(Exception):
|
270
|
+
obj: Any
|
271
|
+
type_: Any
|
272
|
+
|
273
|
+
@override
|
274
|
+
def __str__(self) -> str:
|
275
|
+
return f"Invalid arguments; got {self.obj!r} and {self.type_!r}"
|
276
|
+
|
277
|
+
|
252
278
|
##
|
253
279
|
|
254
280
|
|
@@ -350,13 +376,41 @@ def is_subclass_gen(
|
|
350
376
|
/,
|
351
377
|
) -> TypeGuard[type[_T1 | _T2 | _T3 | _T4 | _T5]]: ...
|
352
378
|
@overload
|
353
|
-
def is_subclass_gen(cls:
|
354
|
-
def is_subclass_gen(cls:
|
379
|
+
def is_subclass_gen(cls: Any, parent: Any, /) -> bool: ...
|
380
|
+
def is_subclass_gen(cls: Any, parent: Any, /) -> bool:
|
355
381
|
"""Generalized `issubclass`."""
|
356
|
-
|
382
|
+
# child
|
383
|
+
if isinstance(cls, tuple):
|
384
|
+
return all(is_subclass_gen(c, parent) for c in cls)
|
385
|
+
if is_literal_type(cls):
|
386
|
+
types = tuple(map(type, get_args(cls)))
|
387
|
+
return (
|
388
|
+
is_literal_type(parent) and set(get_args(cls)).issubset(get_args(parent))
|
389
|
+
) or is_subclass_gen(types, parent)
|
390
|
+
if is_union_type(cls):
|
391
|
+
return all(is_subclass_gen(c, parent) for c in get_args(cls))
|
392
|
+
# parent
|
393
|
+
if isinstance(parent, tuple):
|
394
|
+
return any(is_subclass_gen(cls, p) for p in parent)
|
395
|
+
if is_literal_type(parent):
|
396
|
+
return is_literal_type(cls) and set(get_args(cls)).issubset(get_args(parent))
|
397
|
+
if is_union_type(parent):
|
398
|
+
return any(is_subclass_gen(cls, p) for p in get_args(parent))
|
399
|
+
# tuple vs tuple
|
400
|
+
if is_tuple_type(cls) and is_tuple_type(parent):
|
401
|
+
cls_args, parent_args = get_args(cls), get_args(parent)
|
402
|
+
return (len(cls_args) == len(parent_args)) and all(
|
403
|
+
is_subclass_gen(c, p) for c, p in zip(cls_args, parent_args, strict=True)
|
404
|
+
)
|
405
|
+
if is_tuple_type(cls) is not is_tuple_type(parent):
|
406
|
+
return False
|
407
|
+
# basic
|
408
|
+
if isinstance(cls, type):
|
409
|
+
return any(_is_subclass_gen_type(cls, p) for p in get_type_classes(parent))
|
410
|
+
raise IsSubclassGenError(cls=cls)
|
357
411
|
|
358
412
|
|
359
|
-
def
|
413
|
+
def _is_subclass_gen_type(cls: type[Any], parent: type[_T], /) -> TypeGuard[type[_T]]:
|
360
414
|
return (
|
361
415
|
issubclass(cls, parent)
|
362
416
|
and not (
|
@@ -372,6 +426,15 @@ def _is_subclass_gen_one(cls: type[Any], parent: type[_T], /) -> TypeGuard[type[
|
|
372
426
|
)
|
373
427
|
|
374
428
|
|
429
|
+
@dataclass(kw_only=True, slots=True)
|
430
|
+
class IsSubclassGenError(Exception):
|
431
|
+
cls: Any
|
432
|
+
|
433
|
+
@override
|
434
|
+
def __str__(self) -> str:
|
435
|
+
return f"Argument must be a class; got {self.cls!r}"
|
436
|
+
|
437
|
+
|
375
438
|
##
|
376
439
|
|
377
440
|
|
@@ -402,6 +465,8 @@ def _is_annotation_of_type(obj: Any, origin: Any, /) -> bool:
|
|
402
465
|
__all__ = [
|
403
466
|
"GetTypeClassesError",
|
404
467
|
"GetUnionTypeClassesError",
|
468
|
+
"IsInstanceGenError",
|
469
|
+
"IsSubclassGenError",
|
405
470
|
"contains_self",
|
406
471
|
"get_literal_elements",
|
407
472
|
"get_type_classes",
|
File without changes
|
File without changes
|