dycw-utilities 0.111.0__py3-none-any.whl → 0.112.0__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.111.0.dist-info → dycw_utilities-0.112.0.dist-info}/METADATA +1 -1
- {dycw_utilities-0.111.0.dist-info → dycw_utilities-0.112.0.dist-info}/RECORD +17 -17
- utilities/__init__.py +1 -1
- utilities/datetime.py +1 -60
- utilities/fastapi.py +2 -1
- utilities/fpdf2.py +2 -2
- utilities/hypothesis.py +1 -1
- utilities/logging.py +7 -2
- utilities/parse.py +25 -37
- utilities/pyinstrument.py +2 -1
- utilities/traceback.py +7 -3
- utilities/tzdata.py +55 -1
- utilities/tzlocal.py +24 -1
- utilities/whenever.py +1 -0
- utilities/zoneinfo.py +3 -10
- {dycw_utilities-0.111.0.dist-info → dycw_utilities-0.112.0.dist-info}/WHEEL +0 -0
- {dycw_utilities-0.111.0.dist-info → dycw_utilities-0.112.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,4 +1,4 @@
|
|
1
|
-
utilities/__init__.py,sha256=
|
1
|
+
utilities/__init__.py,sha256=Xs6R-k_70_fB8zwc0DeYfdK4J8vyyL3G76ApWiuWPGo,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
|
@@ -12,24 +12,24 @@ 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
14
|
utilities/dataclasses.py,sha256=Q197PVnE_vUMn_SNnqJBCo4eRy4bdHtgMHWRbSJPtFk,26670
|
15
|
-
utilities/datetime.py,sha256=
|
15
|
+
utilities/datetime.py,sha256=OF7jZE702UecnwAbq9D3N-GINpp9gSGoidki1RhimCE,35752
|
16
16
|
utilities/enum.py,sha256=HoRwVCWzsnH0vpO9ZEcAAIZLMv0Sn2vJxxA4sYMQgDs,5793
|
17
17
|
utilities/errors.py,sha256=BtSNP0JC3ik536ddPyTerLomCRJV9f6kdMe6POz0QHM,361
|
18
18
|
utilities/eventkit.py,sha256=6M5Xu1SzN-juk9PqBHwy5dS-ta7T0qA6SMpDsakOJ0E,13039
|
19
|
-
utilities/fastapi.py,sha256=
|
20
|
-
utilities/fpdf2.py,sha256=
|
19
|
+
utilities/fastapi.py,sha256=y-35at3005jzlNx2wJoiSvB1Ch5bMo30wgU_so3IDdI,2467
|
20
|
+
utilities/fpdf2.py,sha256=y1NGXR5chWqLXWpewGV3hlRGMr_5yV1lVRkPBhPEgJI,1843
|
21
21
|
utilities/functions.py,sha256=jgt592voaHNtX56qX0SRvFveVCRmSIxCZmqvpLZCnY8,27305
|
22
22
|
utilities/functools.py,sha256=WrpHt7NLNWSUn9A1Q_ZIWlNaYZOEI4IFKyBG9HO3BC4,1643
|
23
23
|
utilities/getpass.py,sha256=DfN5UgMAtFCqS3dSfFHUfqIMZX2shXvwphOz_6J6f6A,103
|
24
24
|
utilities/git.py,sha256=wpt5dZ5Oi5931pN24_VLZYaQOvmR0OcQuVtgHzFUN1k,2359
|
25
25
|
utilities/hashlib.py,sha256=SVTgtguur0P4elppvzOBbLEjVM3Pea0eWB61yg2ilxo,309
|
26
26
|
utilities/http.py,sha256=WcahTcKYRtZ04WXQoWt5EGCgFPcyHD3EJdlMfxvDt-0,946
|
27
|
-
utilities/hypothesis.py,sha256=
|
27
|
+
utilities/hypothesis.py,sha256=OpZhPdPmsYWvqMytFDc-G196eODosUzxQSuo-LfMYmM,46262
|
28
28
|
utilities/ipython.py,sha256=V2oMYHvEKvlNBzxDXdLvKi48oUq2SclRg5xasjaXStw,763
|
29
29
|
utilities/iterables.py,sha256=2Yy9gZ7BR4LXR4nlX7outFAjd4dpb3lgUo7ji_sdylY,45076
|
30
30
|
utilities/jupyter.py,sha256=ft5JA7fBxXKzP-L9W8f2-wbF0QeYc_2uLQNFDVk4Z-M,2917
|
31
31
|
utilities/lightweight_charts.py,sha256=vyVOzarYhBIOZj2xDhqdbP85qbSKUjdc6Au91rc1W4M,2814
|
32
|
-
utilities/logging.py,sha256=
|
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
35
|
utilities/math.py,sha256=TexfvLCI12d9Sw5_W4pKVBZ3nRr3zk2iPkcEU7xdEWU,26771
|
@@ -41,7 +41,7 @@ utilities/operator.py,sha256=0M2yZJ0PODH47ogFEnkGMBe_cfxwZR02T_92LZVZvHo,3715
|
|
41
41
|
utilities/optuna.py,sha256=loyJGWTzljgdJaoLhP09PT8Jz6o_pwBOwehY33lHkhw,1923
|
42
42
|
utilities/orjson.py,sha256=DBm2zPP04kcHpY3l1etL24ksNynu-R3duFyx3U-RjqQ,36948
|
43
43
|
utilities/os.py,sha256=D_FyyT-6TtqiN9KSS7c9g1fnUtgxmyMtzAjmYLkk46A,3587
|
44
|
-
utilities/parse.py,sha256
|
44
|
+
utilities/parse.py,sha256=hG-y8WAzpATakA61UOF6UlhfuJQ9XbMN-Uub1ZaiBRU,18780
|
45
45
|
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
|
@@ -51,7 +51,7 @@ 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
|
53
53
|
utilities/pydantic.py,sha256=f6qtR5mO2YMuyvNmbaEj5YeD9eGA4YYfb7Bjzh9jUs0,1845
|
54
|
-
utilities/pyinstrument.py,sha256=
|
54
|
+
utilities/pyinstrument.py,sha256=OJFDh4o1CWIa4aYPYURdQjgap_nvP45KUsCEe94rQHY,829
|
55
55
|
utilities/pyrsistent.py,sha256=MoDcAqQGlSNkmlS32DCJLw-cZFAfHB6K9kpox_iyI4k,2512
|
56
56
|
utilities/pytest.py,sha256=85QUax4g2VBBAqAHtM9wekcSLB7_9O8AKFTaCshztL8,7989
|
57
57
|
utilities/pytest_regressions.py,sha256=-SVT9647Dg6-JcdsiaDKXe3NdOmmrvGevLKWwGjxq3c,5088
|
@@ -76,18 +76,18 @@ utilities/tenacity.py,sha256=1PUvODiBVgeqIh7G5TRt5WWMSqjLYkEqP53itT97WQc,4914
|
|
76
76
|
utilities/text.py,sha256=hfcBKF22fKT6s_U-ZdP-g5TjFQ0-NrIrQdvIwERWT80,10971
|
77
77
|
utilities/threading.py,sha256=GvBOp4CyhHfN90wGXZuA2VKe9fGzMaEa7oCl4f3nnPU,1009
|
78
78
|
utilities/timer.py,sha256=Rkc49KSpHuC8s7vUxGO9DU55U9I6yDKnchsQqrUCVBs,4075
|
79
|
-
utilities/traceback.py,sha256=
|
79
|
+
utilities/traceback.py,sha256=secexUnBsecfWV4ZuqP1W4pGF3prOeO1CRyJK-8zQDU,27402
|
80
80
|
utilities/types.py,sha256=kVY71hZkcnyYNIlYSse0mLm8yeP3OBkzhDPMME6jXxo,18126
|
81
81
|
utilities/typing.py,sha256=jtc6EiGZGG0E745jo3NeLqo_HdHt7Zdaco3kCAEWIYU,11177
|
82
|
-
utilities/tzdata.py,sha256=
|
83
|
-
utilities/tzlocal.py,sha256=
|
82
|
+
utilities/tzdata.py,sha256=yCf70NICwAeazN3_JcXhWvRqCy06XJNQ42j7r6gw3HY,1217
|
83
|
+
utilities/tzlocal.py,sha256=3upDNFBvGh1l9njmLR2z2S6K6VxQSb7QizYGUbAH3JU,960
|
84
84
|
utilities/uuid.py,sha256=jJTFxz-CWgltqNuzmythB7iEQ-Q1mCwPevUfKthZT3c,611
|
85
85
|
utilities/version.py,sha256=QFuyEeQA6jI0ruBEcmhqG36f-etg1AEiD1drBBqhQrs,5358
|
86
86
|
utilities/warnings.py,sha256=un1LvHv70PU-LLv8RxPVmugTzDJkkGXRMZTE2-fTQHw,1771
|
87
|
-
utilities/whenever.py,sha256=
|
87
|
+
utilities/whenever.py,sha256=iLRP_-8CZtBpHKbGZGu-kjSMg1ZubJ-VSmgSy7Eudxw,17787
|
88
88
|
utilities/zipfile.py,sha256=24lQc9ATcJxHXBPc_tBDiJk48pWyRrlxO2fIsFxU0A8,699
|
89
|
-
utilities/zoneinfo.py,sha256=-
|
90
|
-
dycw_utilities-0.
|
91
|
-
dycw_utilities-0.
|
92
|
-
dycw_utilities-0.
|
93
|
-
dycw_utilities-0.
|
89
|
+
utilities/zoneinfo.py,sha256=-Xm57PMMwDTYpxJdkiJG13wnbwK--I7XItBh5WVhD-o,1874
|
90
|
+
dycw_utilities-0.112.0.dist-info/METADATA,sha256=GWKYE-rIVvmMBNyTnfCxMJNqV6PHKYsmLVs-6YJadKw,13004
|
91
|
+
dycw_utilities-0.112.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
92
|
+
dycw_utilities-0.112.0.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
|
93
|
+
dycw_utilities-0.112.0.dist-info/RECORD,,
|
utilities/__init__.py
CHANGED
utilities/datetime.py
CHANGED
@@ -23,13 +23,7 @@ from utilities.platform import SYSTEM
|
|
23
23
|
from utilities.sentinel import Sentinel, sentinel
|
24
24
|
from utilities.types import MaybeStr
|
25
25
|
from utilities.typing import is_instance_gen
|
26
|
-
from utilities.zoneinfo import
|
27
|
-
UTC,
|
28
|
-
HongKong,
|
29
|
-
Tokyo,
|
30
|
-
ensure_time_zone,
|
31
|
-
get_time_zone_name,
|
32
|
-
)
|
26
|
+
from utilities.zoneinfo import UTC, ensure_time_zone, get_time_zone_name
|
33
27
|
|
34
28
|
if TYPE_CHECKING:
|
35
29
|
from collections.abc import Iterator
|
@@ -525,28 +519,6 @@ def get_now(*, time_zone: TimeZoneLike = UTC) -> dt.datetime:
|
|
525
519
|
NOW_UTC = get_now(time_zone=UTC)
|
526
520
|
|
527
521
|
|
528
|
-
def get_now_hk() -> dt.datetime:
|
529
|
-
"""Get the current time in Hong Kong."""
|
530
|
-
return dt.datetime.now(tz=HongKong)
|
531
|
-
|
532
|
-
|
533
|
-
NOW_HK = get_now_hk()
|
534
|
-
|
535
|
-
|
536
|
-
def get_now_local() -> dt.datetime:
|
537
|
-
"""Get the current time in local."""
|
538
|
-
return get_now(time_zone="local")
|
539
|
-
# don't define `NOW_LOCAL` as this would require `tzlocal`
|
540
|
-
|
541
|
-
|
542
|
-
def get_now_tokyo() -> dt.datetime:
|
543
|
-
"""Get the current time in Tokyo."""
|
544
|
-
return dt.datetime.now(tz=Tokyo)
|
545
|
-
|
546
|
-
|
547
|
-
NOW_TOKYO = get_now_tokyo()
|
548
|
-
|
549
|
-
|
550
522
|
##
|
551
523
|
|
552
524
|
|
@@ -570,27 +542,6 @@ def get_today(*, time_zone: TimeZoneLike = UTC) -> dt.date:
|
|
570
542
|
TODAY_UTC = get_today(time_zone=UTC)
|
571
543
|
|
572
544
|
|
573
|
-
def get_today_hk() -> dt.date:
|
574
|
-
"""Get the current date in Hong Kong."""
|
575
|
-
return get_now_hk().date()
|
576
|
-
|
577
|
-
|
578
|
-
TODAY_HK = get_today_hk()
|
579
|
-
|
580
|
-
|
581
|
-
def get_today_local() -> dt.date:
|
582
|
-
"""Get the current, timezone-aware local date."""
|
583
|
-
return get_now_local().date()
|
584
|
-
|
585
|
-
|
586
|
-
def get_today_tokyo() -> dt.date:
|
587
|
-
"""Get the current date in Tokyo."""
|
588
|
-
return get_now_tokyo().date()
|
589
|
-
|
590
|
-
|
591
|
-
TODAY_TOKYO = get_today_tokyo()
|
592
|
-
|
593
|
-
|
594
545
|
##
|
595
546
|
|
596
547
|
|
@@ -1279,13 +1230,9 @@ __all__ = [
|
|
1279
1230
|
"MIN_DATE_TWO_DIGIT_YEAR",
|
1280
1231
|
"MIN_MONTH",
|
1281
1232
|
"MONTH",
|
1282
|
-
"NOW_HK",
|
1283
|
-
"NOW_TOKYO",
|
1284
1233
|
"NOW_UTC",
|
1285
1234
|
"QUARTER",
|
1286
1235
|
"SECOND",
|
1287
|
-
"TODAY_HK",
|
1288
|
-
"TODAY_TOKYO",
|
1289
1236
|
"TODAY_UTC",
|
1290
1237
|
"WEEK",
|
1291
1238
|
"YEAR",
|
@@ -1335,14 +1282,8 @@ __all__ = [
|
|
1335
1282
|
"get_half_years",
|
1336
1283
|
"get_months",
|
1337
1284
|
"get_now",
|
1338
|
-
"get_now_hk",
|
1339
|
-
"get_now_local",
|
1340
|
-
"get_now_tokyo",
|
1341
1285
|
"get_quarters",
|
1342
1286
|
"get_today",
|
1343
|
-
"get_today_hk",
|
1344
|
-
"get_today_local",
|
1345
|
-
"get_today_tokyo",
|
1346
1287
|
"get_years",
|
1347
1288
|
"is_integral_timedelta",
|
1348
1289
|
"is_local_datetime",
|
utilities/fastapi.py
CHANGED
@@ -7,7 +7,7 @@ from fastapi import FastAPI
|
|
7
7
|
from uvicorn import Config, Server
|
8
8
|
|
9
9
|
from utilities.asyncio import AsyncService
|
10
|
-
from utilities.datetime import SECOND, datetime_duration_to_float
|
10
|
+
from utilities.datetime import SECOND, datetime_duration_to_float
|
11
11
|
|
12
12
|
if TYPE_CHECKING:
|
13
13
|
from utilities.types import Duration
|
@@ -26,6 +26,7 @@ class _PingerReceiverApp(FastAPI):
|
|
26
26
|
|
27
27
|
@self.get("/ping") # skipif-ci
|
28
28
|
def ping() -> str:
|
29
|
+
from utilities.tzlocal import get_now_local # skipif-ci
|
29
30
|
from utilities.whenever import serialize_zoned_datetime # skipif-ci
|
30
31
|
|
31
32
|
now = serialize_zoned_datetime(get_now_local()) # skipif-ci
|
utilities/fpdf2.py
CHANGED
@@ -6,8 +6,6 @@ from typing import TYPE_CHECKING, override
|
|
6
6
|
from fpdf import FPDF
|
7
7
|
from fpdf.enums import XPos, YPos
|
8
8
|
|
9
|
-
from utilities.datetime import get_now_local
|
10
|
-
|
11
9
|
if TYPE_CHECKING:
|
12
10
|
from collections.abc import Iterator
|
13
11
|
|
@@ -45,6 +43,8 @@ def yield_pdf(*, header: str | None = None) -> Iterator[_BasePDF]:
|
|
45
43
|
|
46
44
|
@override
|
47
45
|
def footer(self) -> None:
|
46
|
+
from utilities.tzlocal import get_now_local
|
47
|
+
|
48
48
|
self.set_y(-15)
|
49
49
|
self.set_font(family="Helvetica", style="I", size=8)
|
50
50
|
page_no, now = self.page_no(), get_now_local()
|
utilities/hypothesis.py
CHANGED
@@ -69,7 +69,6 @@ from utilities.datetime import (
|
|
69
69
|
date_to_month,
|
70
70
|
datetime_duration_to_float,
|
71
71
|
datetime_duration_to_timedelta,
|
72
|
-
get_now_local,
|
73
72
|
round_datetime,
|
74
73
|
)
|
75
74
|
from utilities.functions import ensure_int, ensure_str, max_nullable, min_nullable
|
@@ -1440,6 +1439,7 @@ def yield_test_redis(data: DataObject, /) -> AbstractAsyncContextManager[_TestRe
|
|
1440
1439
|
from redis.exceptions import ResponseError # skipif-ci-and-not-linux
|
1441
1440
|
|
1442
1441
|
from utilities.redis import _TestRedis, yield_redis # skipif-ci-and-not-linux
|
1442
|
+
from utilities.tzlocal import get_now_local # skipif-ci-and-not-linux
|
1443
1443
|
|
1444
1444
|
now = get_now_local() # skipif-ci-and-not-linux
|
1445
1445
|
uuid = data.draw(uuids()) # skipif-ci-and-not-linux
|
utilities/logging.py
CHANGED
@@ -37,11 +37,9 @@ from typing import (
|
|
37
37
|
override,
|
38
38
|
)
|
39
39
|
|
40
|
-
from utilities.atomicwrites import move_many, writer
|
41
40
|
from utilities.dataclasses import replace_non_sentinel
|
42
41
|
from utilities.datetime import (
|
43
42
|
SECOND,
|
44
|
-
get_now_local,
|
45
43
|
maybe_sub_pct_y,
|
46
44
|
parse_datetime_compact,
|
47
45
|
round_datetime,
|
@@ -200,6 +198,8 @@ def _compute_rollover_actions(
|
|
200
198
|
patterns: _RolloverPatterns | None = None,
|
201
199
|
backup_count: int = 1,
|
202
200
|
) -> _RolloverActions:
|
201
|
+
from utilities.tzlocal import get_now_local # skipif-ci-and-windows
|
202
|
+
|
203
203
|
patterns = ( # skipif-ci-and-windows
|
204
204
|
_compute_rollover_patterns(stem, suffix) if patterns is None else patterns
|
205
205
|
)
|
@@ -244,6 +244,8 @@ class _RolloverActions:
|
|
244
244
|
rotations: set[_Rotation] = field(default_factory=set)
|
245
245
|
|
246
246
|
def do(self) -> None:
|
247
|
+
from utilities.atomicwrites import move_many # skipif-ci-and-windows
|
248
|
+
|
247
249
|
for deletion in self.deletions: # skipif-ci-and-windows
|
248
250
|
deletion.delete()
|
249
251
|
move_many( # skipif-ci-and-windows
|
@@ -388,6 +390,9 @@ class StandaloneFileHandler(Handler):
|
|
388
390
|
|
389
391
|
@override
|
390
392
|
def emit(self, record: LogRecord) -> None:
|
393
|
+
from utilities.atomicwrites import writer
|
394
|
+
from utilities.tzlocal import get_now_local
|
395
|
+
|
391
396
|
try:
|
392
397
|
path = (
|
393
398
|
resolve_path(path=self._path)
|
utilities/parse.py
CHANGED
@@ -60,15 +60,15 @@ def parse_object(
|
|
60
60
|
extra: ParseObjectExtra | None = None,
|
61
61
|
) -> Any:
|
62
62
|
"""Parse text."""
|
63
|
+
if extra is not None:
|
64
|
+
return _parse_object_extra(type_, text, extra)
|
63
65
|
if type_ is None:
|
64
66
|
try:
|
65
67
|
return parse_none(text)
|
66
68
|
except ParseNoneError:
|
67
69
|
raise _ParseObjectParseError(type_=type_, text=text) from None
|
68
70
|
if isinstance(type_, type):
|
69
|
-
return _parse_object_type(
|
70
|
-
type_, text, case_sensitive=case_sensitive, extra=extra
|
71
|
-
)
|
71
|
+
return _parse_object_type(type_, text, case_sensitive=case_sensitive)
|
72
72
|
if is_dict_type(type_):
|
73
73
|
return _parse_object_dict_type(
|
74
74
|
type_,
|
@@ -146,17 +146,12 @@ def parse_object(
|
|
146
146
|
extra=extra,
|
147
147
|
)
|
148
148
|
if is_union_type(type_):
|
149
|
-
return _parse_object_union_type(type_, text
|
149
|
+
return _parse_object_union_type(type_, text)
|
150
150
|
raise _ParseObjectParseError(type_=type_, text=text) from None
|
151
151
|
|
152
152
|
|
153
153
|
def _parse_object_type(
|
154
|
-
cls: type[Any],
|
155
|
-
text: str,
|
156
|
-
/,
|
157
|
-
*,
|
158
|
-
case_sensitive: bool = False,
|
159
|
-
extra: ParseObjectExtra | None = None,
|
154
|
+
cls: type[Any], text: str, /, *, case_sensitive: bool = False
|
160
155
|
) -> Any:
|
161
156
|
"""Parse text."""
|
162
157
|
if issubclass(cls, NoneType):
|
@@ -226,17 +221,6 @@ def _parse_object_type(
|
|
226
221
|
return parse_timedelta(text)
|
227
222
|
except ParseTimedeltaError:
|
228
223
|
raise _ParseObjectParseError(type_=cls, text=text) from None
|
229
|
-
if extra is not None:
|
230
|
-
try:
|
231
|
-
parser = one(p for c, p in extra.items() if issubclass(cls, c))
|
232
|
-
except OneEmptyError:
|
233
|
-
pass
|
234
|
-
except OneNonUniqueError as error:
|
235
|
-
raise _ParseObjectExtraNonUniqueError(
|
236
|
-
type_=cls, text=text, first=error.first, second=error.second
|
237
|
-
) from None
|
238
|
-
else:
|
239
|
-
return parser(text)
|
240
224
|
raise _ParseObjectParseError(type_=cls, text=text)
|
241
225
|
|
242
226
|
|
@@ -296,6 +280,21 @@ def _parse_object_dict_type(
|
|
296
280
|
raise _ParseObjectParseError(type_=type_, text=text) from None
|
297
281
|
|
298
282
|
|
283
|
+
def _parse_object_extra(cls: Any, text: str, extra: ParseObjectExtra, /) -> Any:
|
284
|
+
try:
|
285
|
+
parser = one(
|
286
|
+
p for c, p in extra.items() if (cls is c) or is_subclass_gen(cls, c)
|
287
|
+
)
|
288
|
+
except OneEmptyError:
|
289
|
+
raise _ParseObjectParseError(type_=cls, text=text) from None
|
290
|
+
except OneNonUniqueError as error:
|
291
|
+
raise _ParseObjectExtraNonUniqueError(
|
292
|
+
type_=cls, text=text, first=error.first, second=error.second
|
293
|
+
) from None
|
294
|
+
else:
|
295
|
+
return parser(text)
|
296
|
+
|
297
|
+
|
299
298
|
def _parse_object_list_type(
|
300
299
|
type_: Any,
|
301
300
|
text: str,
|
@@ -368,9 +367,7 @@ def _parse_object_set_type(
|
|
368
367
|
raise _ParseObjectParseError(type_=type_, text=text) from None
|
369
368
|
|
370
369
|
|
371
|
-
def _parse_object_union_type(
|
372
|
-
type_: Any, text: str, /, *, extra: ParseObjectExtra | None = None
|
373
|
-
) -> Any:
|
370
|
+
def _parse_object_union_type(type_: Any, text: str, /) -> Any:
|
374
371
|
if type_ is Number:
|
375
372
|
try:
|
376
373
|
return parse_number(text)
|
@@ -383,13 +380,6 @@ def _parse_object_union_type(
|
|
383
380
|
return parse_duration(text)
|
384
381
|
except ParseDurationError:
|
385
382
|
raise _ParseObjectParseError(type_=type_, text=text) from None
|
386
|
-
if extra is not None:
|
387
|
-
try:
|
388
|
-
parser = one(p for c, p in extra.items() if c is type_)
|
389
|
-
except OneEmptyError:
|
390
|
-
pass
|
391
|
-
else:
|
392
|
-
return parser(text)
|
393
383
|
raise _ParseObjectParseError(type_=type_, text=text) from None
|
394
384
|
|
395
385
|
|
@@ -466,6 +456,9 @@ def serialize_object(
|
|
466
456
|
extra: SerializeObjectExtra | None = None,
|
467
457
|
) -> str:
|
468
458
|
"""Convert an object to text."""
|
459
|
+
if extra is not None:
|
460
|
+
with suppress(_SerializeObjectSerializeError):
|
461
|
+
return _serialize_object_extra(obj, extra)
|
469
462
|
if (obj is None) or isinstance(
|
470
463
|
obj, bool | int | float | str | Path | Sentinel | Version
|
471
464
|
):
|
@@ -504,8 +497,6 @@ def serialize_object(
|
|
504
497
|
return _serialize_object_set(
|
505
498
|
obj, list_separator=list_separator, pair_separator=pair_separator
|
506
499
|
)
|
507
|
-
if extra is not None:
|
508
|
-
return _serialize_object_extra(obj, extra)
|
509
500
|
raise _SerializeObjectSerializeError(obj=obj)
|
510
501
|
|
511
502
|
|
@@ -537,10 +528,7 @@ def _serialize_object_dict(
|
|
537
528
|
def _serialize_object_extra(obj: Any, extra: SerializeObjectExtra, /) -> str:
|
538
529
|
try:
|
539
530
|
serializer = one(
|
540
|
-
s
|
541
|
-
for c, s in extra.items()
|
542
|
-
if (isinstance(c, type) and isinstance(obj, c))
|
543
|
-
or isinstance(obj, get_args(c))
|
531
|
+
s for c, s in extra.items() if (obj is c) or is_instance_gen(obj, c)
|
544
532
|
)
|
545
533
|
except OneEmptyError:
|
546
534
|
raise _SerializeObjectSerializeError(obj=obj) from None
|
utilities/pyinstrument.py
CHANGED
@@ -6,8 +6,9 @@ from typing import TYPE_CHECKING
|
|
6
6
|
|
7
7
|
from pyinstrument.profiler import Profiler
|
8
8
|
|
9
|
-
from utilities.datetime import
|
9
|
+
from utilities.datetime import serialize_compact
|
10
10
|
from utilities.pathlib import PWD
|
11
|
+
from utilities.tzlocal import get_now_local
|
11
12
|
|
12
13
|
if TYPE_CHECKING:
|
13
14
|
from collections.abc import Iterator
|
utilities/traceback.py
CHANGED
@@ -26,7 +26,6 @@ from typing import (
|
|
26
26
|
runtime_checkable,
|
27
27
|
)
|
28
28
|
|
29
|
-
from utilities.datetime import get_now_local
|
30
29
|
from utilities.errors import ImpossibleCaseError
|
31
30
|
from utilities.functions import (
|
32
31
|
ensure_not_none,
|
@@ -44,10 +43,8 @@ from utilities.reprlib import (
|
|
44
43
|
RICH_MAX_STRING,
|
45
44
|
RICH_MAX_WIDTH,
|
46
45
|
)
|
47
|
-
from utilities.rich import yield_call_args_repr, yield_mapping_repr
|
48
46
|
from utilities.types import TBaseException, TCallable
|
49
47
|
from utilities.version import get_version
|
50
|
-
from utilities.whenever import serialize_zoned_datetime
|
51
48
|
|
52
49
|
if TYPE_CHECKING:
|
53
50
|
from collections.abc import Callable, Iterable, Iterator
|
@@ -192,6 +189,8 @@ class _CallArgs:
|
|
192
189
|
@classmethod
|
193
190
|
def create(cls, func: Callable[..., Any], *args: Any, **kwargs: Any) -> Self:
|
194
191
|
"""Make the initial trace data."""
|
192
|
+
from utilities.rich import yield_call_args_repr
|
193
|
+
|
195
194
|
sig = signature(func)
|
196
195
|
try:
|
197
196
|
bound_args = sig.bind(*args, **kwargs)
|
@@ -428,6 +427,8 @@ class _Frame:
|
|
428
427
|
depth: int = 0,
|
429
428
|
) -> str:
|
430
429
|
"""Format the traceback."""
|
430
|
+
from utilities.rich import yield_call_args_repr, yield_mapping_repr
|
431
|
+
|
431
432
|
lines: list[str] = [f"Frame {index + 1}/{total}: {self.name} ({self.module})"]
|
432
433
|
if detail:
|
433
434
|
lines.append(indent("Inputs:", _INDENT))
|
@@ -784,6 +785,9 @@ def _yield_header_lines(
|
|
784
785
|
*, version: MaybeCallableVersionLike | None = None
|
785
786
|
) -> Iterator[str]:
|
786
787
|
"""Yield the header lines."""
|
788
|
+
from utilities.tzlocal import get_now_local
|
789
|
+
from utilities.whenever import serialize_zoned_datetime
|
790
|
+
|
787
791
|
yield f"Date/time | {serialize_zoned_datetime(get_now_local())}"
|
788
792
|
yield f"User | {getuser()}"
|
789
793
|
yield f"Host | {gethostname()}"
|
utilities/tzdata.py
CHANGED
@@ -1,9 +1,63 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
+
from typing import TYPE_CHECKING
|
3
4
|
from zoneinfo import ZoneInfo
|
4
5
|
|
6
|
+
from utilities.datetime import get_now, get_today
|
7
|
+
|
8
|
+
if TYPE_CHECKING:
|
9
|
+
import datetime as dt
|
10
|
+
|
11
|
+
|
12
|
+
HongKong = ZoneInfo("Asia/Hong_Kong")
|
13
|
+
Tokyo = ZoneInfo("Asia/Tokyo")
|
5
14
|
USCentral = ZoneInfo("US/Central")
|
6
15
|
USEastern = ZoneInfo("US/Eastern")
|
7
16
|
|
8
17
|
|
9
|
-
|
18
|
+
def get_now_hong_kong() -> dt.datetime:
|
19
|
+
"""Get the current time in Hong Kong."""
|
20
|
+
return get_now(time_zone=HongKong)
|
21
|
+
|
22
|
+
|
23
|
+
NOW_HONG_KONG = get_now_hong_kong()
|
24
|
+
|
25
|
+
|
26
|
+
def get_now_tokyo() -> dt.datetime:
|
27
|
+
"""Get the current time in Tokyo."""
|
28
|
+
return get_now(time_zone=Tokyo)
|
29
|
+
|
30
|
+
|
31
|
+
NOW_TOKYO = get_now_tokyo()
|
32
|
+
|
33
|
+
|
34
|
+
def get_today_hong_kong() -> dt.date:
|
35
|
+
"""Get the current date in Hong Kong."""
|
36
|
+
return get_today(time_zone=HongKong)
|
37
|
+
|
38
|
+
|
39
|
+
TODAY_HONG_KONG = get_today_hong_kong()
|
40
|
+
|
41
|
+
|
42
|
+
def get_today_tokyo() -> dt.date:
|
43
|
+
"""Get the current date in Tokyo."""
|
44
|
+
return get_today(time_zone=Tokyo)
|
45
|
+
|
46
|
+
|
47
|
+
TODAY_TOKYO = get_today_tokyo()
|
48
|
+
|
49
|
+
|
50
|
+
__all__ = [
|
51
|
+
"NOW_HONG_KONG",
|
52
|
+
"NOW_TOKYO",
|
53
|
+
"TODAY_HONG_KONG",
|
54
|
+
"TODAY_TOKYO",
|
55
|
+
"HongKong",
|
56
|
+
"Tokyo",
|
57
|
+
"USCentral",
|
58
|
+
"USEastern",
|
59
|
+
"get_now_hong_kong",
|
60
|
+
"get_now_tokyo",
|
61
|
+
"get_today_hong_kong",
|
62
|
+
"get_today_tokyo",
|
63
|
+
]
|
utilities/tzlocal.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
+
import datetime as dt
|
3
4
|
from logging import getLogger
|
4
5
|
from typing import TYPE_CHECKING
|
5
6
|
|
@@ -19,4 +20,26 @@ def get_local_time_zone() -> ZoneInfo:
|
|
19
20
|
return time_zone
|
20
21
|
|
21
22
|
|
22
|
-
|
23
|
+
def get_now_local() -> dt.datetime:
|
24
|
+
"""Get the current local time."""
|
25
|
+
return dt.datetime.now(tz=get_local_time_zone())
|
26
|
+
|
27
|
+
|
28
|
+
NOW_LOCAL = get_now_local()
|
29
|
+
|
30
|
+
|
31
|
+
def get_today_local() -> dt.date:
|
32
|
+
"""Get the current, timezone-aware local date."""
|
33
|
+
return get_now_local().date()
|
34
|
+
|
35
|
+
|
36
|
+
TODAY_LOCAL = get_today_local()
|
37
|
+
|
38
|
+
|
39
|
+
__all__ = [
|
40
|
+
"NOW_LOCAL",
|
41
|
+
"TODAY_LOCAL",
|
42
|
+
"get_local_time_zone",
|
43
|
+
"get_now_local",
|
44
|
+
"get_today_local",
|
45
|
+
]
|
utilities/whenever.py
CHANGED
utilities/zoneinfo.py
CHANGED
@@ -8,10 +8,10 @@ from zoneinfo import ZoneInfo
|
|
8
8
|
if TYPE_CHECKING:
|
9
9
|
from utilities.types import TimeZone, TimeZoneLike
|
10
10
|
|
11
|
-
|
12
|
-
Tokyo = ZoneInfo("Asia/Tokyo")
|
11
|
+
|
13
12
|
UTC = ZoneInfo("UTC")
|
14
13
|
|
14
|
+
|
15
15
|
##
|
16
16
|
|
17
17
|
|
@@ -68,11 +68,4 @@ def get_time_zone_name(time_zone: TimeZoneLike, /) -> TimeZone:
|
|
68
68
|
return cast("TimeZone", ensure_time_zone(time_zone).key)
|
69
69
|
|
70
70
|
|
71
|
-
__all__ = [
|
72
|
-
"UTC",
|
73
|
-
"EnsureTimeZoneError",
|
74
|
-
"HongKong",
|
75
|
-
"Tokyo",
|
76
|
-
"ensure_time_zone",
|
77
|
-
"get_time_zone_name",
|
78
|
-
]
|
71
|
+
__all__ = ["UTC", "EnsureTimeZoneError", "ensure_time_zone", "get_time_zone_name"]
|
File without changes
|
File without changes
|