dycw-utilities 0.154.0__py3-none-any.whl → 0.155.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.154.0.dist-info → dycw_utilities-0.155.0.dist-info}/METADATA +2 -2
- {dycw_utilities-0.154.0.dist-info → dycw_utilities-0.155.0.dist-info}/RECORD +10 -10
- utilities/__init__.py +1 -1
- utilities/hypothesis.py +143 -41
- utilities/orjson.py +45 -12
- utilities/polars.py +2 -2
- utilities/pytest_regressions.py +3 -1
- {dycw_utilities-0.154.0.dist-info → dycw_utilities-0.155.0.dist-info}/WHEEL +0 -0
- {dycw_utilities-0.154.0.dist-info → dycw_utilities-0.155.0.dist-info}/entry_points.txt +0 -0
- {dycw_utilities-0.154.0.dist-info → dycw_utilities-0.155.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: dycw-utilities
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.155.0
|
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.
|
15
|
+
Requires-Dist: hypothesis<6.138,>=6.137.1; extra == 'test'
|
16
16
|
Requires-Dist: pudb<2025.2,>=2025.1; extra == 'test'
|
17
17
|
Requires-Dist: pytest-asyncio<1.2,>=1.1.0; extra == 'test'
|
18
18
|
Requires-Dist: pytest-cov<6.3,>=6.2.1; extra == 'test'
|
@@ -1,4 +1,4 @@
|
|
1
|
-
utilities/__init__.py,sha256=
|
1
|
+
utilities/__init__.py,sha256=OFslnM101fl40brwBMTE9hAplv30EfT_NmRkbGPfu-g,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
|
@@ -22,7 +22,7 @@ utilities/getpass.py,sha256=DfN5UgMAtFCqS3dSfFHUfqIMZX2shXvwphOz_6J6f6A,103
|
|
22
22
|
utilities/gzip.py,sha256=fkGP3KdsBfXlstodT4wtlp-PwNyUsogpbDCVVVGdsm4,781
|
23
23
|
utilities/hashlib.py,sha256=SVTgtguur0P4elppvzOBbLEjVM3Pea0eWB61yg2ilxo,309
|
24
24
|
utilities/http.py,sha256=TsavEfHlRtlLaeV21Z6KZh0qbPw-kvD1zsQdZ7Kep5Q,977
|
25
|
-
utilities/hypothesis.py,sha256=
|
25
|
+
utilities/hypothesis.py,sha256=hoa1Szk3oLa07W4nl6Uhy2vsToIxx8AYjJg9PLc9JvQ,43516
|
26
26
|
utilities/importlib.py,sha256=mV1xT_O_zt_GnZZ36tl3xOmMaN_3jErDWY54fX39F6Y,429
|
27
27
|
utilities/inflect.py,sha256=v7YkOWSu8NAmVghPcf4F3YBZQoJCS47_DLf9jbfWIs0,581
|
28
28
|
utilities/ipython.py,sha256=V2oMYHvEKvlNBzxDXdLvKi48oUq2SclRg5xasjaXStw,763
|
@@ -39,13 +39,13 @@ utilities/more_itertools.py,sha256=rklJ5vpvXr_H5pAGpWmwVpqtBVehoJ0-jBGYsZbux3M,1
|
|
39
39
|
utilities/numpy.py,sha256=Xn23sA2ZbVNqwUYEgNJD3XBYH6IbCri_WkHSNhg3NkY,26122
|
40
40
|
utilities/operator.py,sha256=nhxn5q6CFNzUm1wpTwWPCu9JGCqVHSlaJf0o1-efoII,3616
|
41
41
|
utilities/optuna.py,sha256=C-fhWYiXHVPo1l8QctYkFJ4DyhbSrGorzP1dJb_qvd8,1933
|
42
|
-
utilities/orjson.py,sha256=
|
42
|
+
utilities/orjson.py,sha256=Ll0U172ITMqOJc3kjV90C0eI-EWzSXlMHSdUBaUSe80,41499
|
43
43
|
utilities/os.py,sha256=mFvjydySvjtSXpk7tLStUJcndauAoujxUUmj_CO7LWY,3778
|
44
44
|
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=DxGDEw3KRxQJkuJ1S0fduXfCiyXJ-9mul0kYj3lFt_Q,78530
|
49
49
|
utilities/polars_ols.py,sha256=Uc9V5kvlWZ5cU93lKZ-cfAKdVFFw81tqwLW9PxtUvMs,5618
|
50
50
|
utilities/postgres.py,sha256=ynCTTaF-bVEOSW-KEAR-dlLh_hYjeVVjm__-4pEU8Zk,12269
|
51
51
|
utilities/pottery.py,sha256=HJ96oLRarTP37Vhg0WTyB3yAu2hETeg6HgRmpDIqyUs,6581
|
@@ -54,7 +54,7 @@ utilities/psutil.py,sha256=KUlu4lrUw9Zg1V7ZGetpWpGb9DB8l_SSDWGbANFNCPU,2104
|
|
54
54
|
utilities/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
55
55
|
utilities/pyinstrument.py,sha256=NZCZz2nBo0BLJ9DTf7H_Q_KGxvsf2S2M3h0qYoYh2kw,804
|
56
56
|
utilities/pytest.py,sha256=2HHfAWkzZeK2OAzL2F49EDKooMkfDoGqg8Ev4cHC_N8,7869
|
57
|
-
utilities/pytest_regressions.py,sha256=
|
57
|
+
utilities/pytest_regressions.py,sha256=8by5DWEL89Y469TI5AzX1pMy3NJWVtjEg2xQdOOdYuM,4169
|
58
58
|
utilities/random.py,sha256=hZlH4gnAtoaofWswuJYjcygejrY8db4CzP-z_adO2Mo,4165
|
59
59
|
utilities/re.py,sha256=S4h-DLL6ScMPqjboZ_uQ1BVTJajrqV06r_81D--_HCE,4573
|
60
60
|
utilities/redis.py,sha256=2fdveFbqL2pEAeyiVuN_Je8nSM_IZHeahPduMHhFRzY,28381
|
@@ -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.
|
91
|
-
dycw_utilities-0.
|
92
|
-
dycw_utilities-0.
|
93
|
-
dycw_utilities-0.
|
94
|
-
dycw_utilities-0.
|
90
|
+
dycw_utilities-0.155.0.dist-info/METADATA,sha256=AFafkgKG-CWYCGGKjJxAXn1dYS1wM_OkjeV2m7ZnaQs,1696
|
91
|
+
dycw_utilities-0.155.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
92
|
+
dycw_utilities-0.155.0.dist-info/entry_points.txt,sha256=BOD_SoDxwsfJYOLxhrSXhHP_T7iw-HXI9f2WVkzYxvQ,135
|
93
|
+
dycw_utilities-0.155.0.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
|
94
|
+
dycw_utilities-0.155.0.dist-info/RECORD,,
|
utilities/__init__.py
CHANGED
utilities/hypothesis.py
CHANGED
@@ -50,10 +50,12 @@ from whenever import (
|
|
50
50
|
ZonedDateTime,
|
51
51
|
)
|
52
52
|
|
53
|
-
from utilities.functions import ensure_int, ensure_str
|
53
|
+
from utilities.functions import ensure_int, ensure_str, max_nullable, min_nullable
|
54
54
|
from utilities.math import (
|
55
55
|
MAX_FLOAT32,
|
56
56
|
MAX_FLOAT64,
|
57
|
+
MAX_INT8,
|
58
|
+
MAX_INT16,
|
57
59
|
MAX_INT32,
|
58
60
|
MAX_INT64,
|
59
61
|
MAX_UINT8,
|
@@ -62,6 +64,8 @@ from utilities.math import (
|
|
62
64
|
MAX_UINT64,
|
63
65
|
MIN_FLOAT32,
|
64
66
|
MIN_FLOAT64,
|
67
|
+
MIN_INT8,
|
68
|
+
MIN_INT16,
|
65
69
|
MIN_INT32,
|
66
70
|
MIN_INT64,
|
67
71
|
MIN_UINT8,
|
@@ -90,6 +94,9 @@ from utilities.whenever import (
|
|
90
94
|
DAY,
|
91
95
|
TIME_DELTA_MAX,
|
92
96
|
TIME_DELTA_MIN,
|
97
|
+
DatePeriod,
|
98
|
+
TimePeriod,
|
99
|
+
ZonedDateTimePeriod,
|
93
100
|
to_date_time_delta,
|
94
101
|
to_days,
|
95
102
|
to_nanoseconds,
|
@@ -201,6 +208,26 @@ def date_deltas(
|
|
201
208
|
##
|
202
209
|
|
203
210
|
|
211
|
+
@composite
|
212
|
+
def date_periods(
|
213
|
+
draw: DrawFn,
|
214
|
+
/,
|
215
|
+
*,
|
216
|
+
min_value: MaybeSearchStrategy[Date | None] = None,
|
217
|
+
max_value: MaybeSearchStrategy[Date | None] = None,
|
218
|
+
two_digit: MaybeSearchStrategy[bool] = False,
|
219
|
+
) -> DatePeriod:
|
220
|
+
"""Strategy for generating date periods."""
|
221
|
+
min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
|
222
|
+
two_digit_ = draw2(draw, two_digit)
|
223
|
+
strategy = dates(min_value=min_value_, max_value=max_value_, two_digit=two_digit_)
|
224
|
+
start, end = draw(pairs(strategy, sorted=True))
|
225
|
+
return DatePeriod(start, end)
|
226
|
+
|
227
|
+
|
228
|
+
##
|
229
|
+
|
230
|
+
|
204
231
|
@composite
|
205
232
|
def date_time_deltas(
|
206
233
|
draw: DrawFn,
|
@@ -373,13 +400,13 @@ def float32s(
|
|
373
400
|
draw: DrawFn,
|
374
401
|
/,
|
375
402
|
*,
|
376
|
-
min_value: MaybeSearchStrategy[float] =
|
377
|
-
max_value: MaybeSearchStrategy[float] =
|
403
|
+
min_value: MaybeSearchStrategy[float | None] = None,
|
404
|
+
max_value: MaybeSearchStrategy[float | None] = None,
|
378
405
|
) -> float:
|
379
406
|
"""Strategy for generating float32s."""
|
380
407
|
min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
|
381
|
-
min_value_ =
|
382
|
-
max_value_ =
|
408
|
+
min_value_ = max_nullable([min_value_, MIN_FLOAT32])
|
409
|
+
max_value_ = min_nullable([max_value_, MAX_FLOAT32])
|
383
410
|
if is_zero(min_value_) and is_zero(max_value_):
|
384
411
|
min_value_ = max_value_ = 0.0
|
385
412
|
return draw(floats(min_value_, max_value_, width=32))
|
@@ -390,13 +417,13 @@ def float64s(
|
|
390
417
|
draw: DrawFn,
|
391
418
|
/,
|
392
419
|
*,
|
393
|
-
min_value: MaybeSearchStrategy[float] =
|
394
|
-
max_value: MaybeSearchStrategy[float] =
|
420
|
+
min_value: MaybeSearchStrategy[float | None] = None,
|
421
|
+
max_value: MaybeSearchStrategy[float | None] = None,
|
395
422
|
) -> float:
|
396
423
|
"""Strategy for generating float64s."""
|
397
424
|
min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
|
398
|
-
min_value_ =
|
399
|
-
max_value_ =
|
425
|
+
min_value_ = max_nullable([min_value_, MIN_FLOAT64])
|
426
|
+
max_value_ = min_nullable([max_value_, MAX_FLOAT64])
|
400
427
|
if is_zero(min_value_) and is_zero(max_value_):
|
401
428
|
min_value_ = max_value_ = 0.0
|
402
429
|
return draw(floats(min_value_, max_value_, width=64))
|
@@ -601,18 +628,48 @@ def int_arrays(
|
|
601
628
|
##
|
602
629
|
|
603
630
|
|
631
|
+
@composite
|
632
|
+
def int8s(
|
633
|
+
draw: DrawFn,
|
634
|
+
/,
|
635
|
+
*,
|
636
|
+
min_value: MaybeSearchStrategy[int | None] = None,
|
637
|
+
max_value: MaybeSearchStrategy[int | None] = None,
|
638
|
+
) -> int:
|
639
|
+
"""Strategy for generating int8s."""
|
640
|
+
min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
|
641
|
+
min_value_ = max_nullable([min_value_, MIN_INT8])
|
642
|
+
max_value_ = min_nullable([max_value_, MAX_INT8])
|
643
|
+
return draw(integers(min_value=min_value_, max_value=max_value_))
|
644
|
+
|
645
|
+
|
646
|
+
@composite
|
647
|
+
def int16s(
|
648
|
+
draw: DrawFn,
|
649
|
+
/,
|
650
|
+
*,
|
651
|
+
min_value: MaybeSearchStrategy[int | None] = None,
|
652
|
+
max_value: MaybeSearchStrategy[int | None] = None,
|
653
|
+
) -> int:
|
654
|
+
"""Strategy for generating int16s."""
|
655
|
+
min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
|
656
|
+
min_value_ = max_nullable([min_value_, MIN_INT16])
|
657
|
+
max_value_ = min_nullable([max_value_, MAX_INT16])
|
658
|
+
return draw(integers(min_value=min_value_, max_value=max_value_))
|
659
|
+
|
660
|
+
|
604
661
|
@composite
|
605
662
|
def int32s(
|
606
663
|
draw: DrawFn,
|
607
664
|
/,
|
608
665
|
*,
|
609
|
-
min_value: MaybeSearchStrategy[int] =
|
610
|
-
max_value: MaybeSearchStrategy[int] =
|
666
|
+
min_value: MaybeSearchStrategy[int | None] = None,
|
667
|
+
max_value: MaybeSearchStrategy[int | None] = None,
|
611
668
|
) -> int:
|
612
669
|
"""Strategy for generating int32s."""
|
613
670
|
min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
|
614
|
-
min_value_ =
|
615
|
-
max_value_ =
|
671
|
+
min_value_ = max_nullable([min_value_, MIN_INT32])
|
672
|
+
max_value_ = min_nullable([max_value_, MAX_INT32])
|
616
673
|
return draw(integers(min_value_, max_value_))
|
617
674
|
|
618
675
|
|
@@ -621,13 +678,13 @@ def int64s(
|
|
621
678
|
draw: DrawFn,
|
622
679
|
/,
|
623
680
|
*,
|
624
|
-
min_value: MaybeSearchStrategy[int] =
|
625
|
-
max_value: MaybeSearchStrategy[int] =
|
681
|
+
min_value: MaybeSearchStrategy[int | None] = None,
|
682
|
+
max_value: MaybeSearchStrategy[int | None] = None,
|
626
683
|
) -> int:
|
627
684
|
"""Strategy for generating int64s."""
|
628
685
|
min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
|
629
|
-
min_value_ =
|
630
|
-
max_value_ =
|
686
|
+
min_value_ = max_nullable([min_value_, MIN_INT64])
|
687
|
+
max_value_ = min_nullable([max_value_, MAX_INT64])
|
631
688
|
return draw(integers(min_value_, max_value_))
|
632
689
|
|
633
690
|
|
@@ -780,7 +837,7 @@ def _path_parts(draw: DrawFn, /) -> str:
|
|
780
837
|
|
781
838
|
|
782
839
|
@composite
|
783
|
-
def
|
840
|
+
def plain_date_times(
|
784
841
|
draw: DrawFn,
|
785
842
|
/,
|
786
843
|
*,
|
@@ -1174,6 +1231,24 @@ def time_deltas(
|
|
1174
1231
|
##
|
1175
1232
|
|
1176
1233
|
|
1234
|
+
@composite
|
1235
|
+
def time_periods(
|
1236
|
+
draw: DrawFn,
|
1237
|
+
/,
|
1238
|
+
*,
|
1239
|
+
min_value: MaybeSearchStrategy[Time | None] = None,
|
1240
|
+
max_value: MaybeSearchStrategy[Time | None] = None,
|
1241
|
+
) -> TimePeriod:
|
1242
|
+
"""Strategy for generating time periods."""
|
1243
|
+
min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
|
1244
|
+
strategy = times(min_value=min_value_, max_value=max_value_)
|
1245
|
+
start, end = draw(pairs(strategy, sorted=True))
|
1246
|
+
return TimePeriod(start, end)
|
1247
|
+
|
1248
|
+
|
1249
|
+
##
|
1250
|
+
|
1251
|
+
|
1177
1252
|
@composite
|
1178
1253
|
def times(
|
1179
1254
|
draw: DrawFn,
|
@@ -1235,13 +1310,13 @@ def uint8s(
|
|
1235
1310
|
draw: DrawFn,
|
1236
1311
|
/,
|
1237
1312
|
*,
|
1238
|
-
min_value: MaybeSearchStrategy[int] =
|
1239
|
-
max_value: MaybeSearchStrategy[int] =
|
1313
|
+
min_value: MaybeSearchStrategy[int | None] = None,
|
1314
|
+
max_value: MaybeSearchStrategy[int | None] = None,
|
1240
1315
|
) -> int:
|
1241
1316
|
"""Strategy for generating uint8s."""
|
1242
1317
|
min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
|
1243
|
-
min_value_ =
|
1244
|
-
max_value_ =
|
1318
|
+
min_value_ = max_nullable([min_value_, MIN_UINT8])
|
1319
|
+
max_value_ = min_nullable([max_value_, MAX_UINT8])
|
1245
1320
|
return draw(integers(min_value=min_value_, max_value=max_value_))
|
1246
1321
|
|
1247
1322
|
|
@@ -1250,13 +1325,13 @@ def uint16s(
|
|
1250
1325
|
draw: DrawFn,
|
1251
1326
|
/,
|
1252
1327
|
*,
|
1253
|
-
min_value: MaybeSearchStrategy[int] =
|
1254
|
-
max_value: MaybeSearchStrategy[int] =
|
1328
|
+
min_value: MaybeSearchStrategy[int | None] = None,
|
1329
|
+
max_value: MaybeSearchStrategy[int | None] = None,
|
1255
1330
|
) -> int:
|
1256
1331
|
"""Strategy for generating uint16s."""
|
1257
1332
|
min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
|
1258
|
-
min_value_ =
|
1259
|
-
max_value_ =
|
1333
|
+
min_value_ = max_nullable([min_value_, MIN_UINT16])
|
1334
|
+
max_value_ = min_nullable([max_value_, MAX_UINT16])
|
1260
1335
|
return draw(integers(min_value=min_value_, max_value=max_value_))
|
1261
1336
|
|
1262
1337
|
|
@@ -1265,13 +1340,13 @@ def uint32s(
|
|
1265
1340
|
draw: DrawFn,
|
1266
1341
|
/,
|
1267
1342
|
*,
|
1268
|
-
min_value: MaybeSearchStrategy[int] =
|
1269
|
-
max_value: MaybeSearchStrategy[int] =
|
1343
|
+
min_value: MaybeSearchStrategy[int | None] = None,
|
1344
|
+
max_value: MaybeSearchStrategy[int | None] = None,
|
1270
1345
|
) -> int:
|
1271
1346
|
"""Strategy for generating uint32s."""
|
1272
1347
|
min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
|
1273
|
-
min_value_ =
|
1274
|
-
max_value_ =
|
1348
|
+
min_value_ = max_nullable([min_value_, MIN_UINT32])
|
1349
|
+
max_value_ = min_nullable([max_value_, MAX_UINT32])
|
1275
1350
|
return draw(integers(min_value=min_value_, max_value=max_value_))
|
1276
1351
|
|
1277
1352
|
|
@@ -1280,13 +1355,13 @@ def uint64s(
|
|
1280
1355
|
draw: DrawFn,
|
1281
1356
|
/,
|
1282
1357
|
*,
|
1283
|
-
min_value: MaybeSearchStrategy[int] =
|
1284
|
-
max_value: MaybeSearchStrategy[int] =
|
1358
|
+
min_value: MaybeSearchStrategy[int | None] = None,
|
1359
|
+
max_value: MaybeSearchStrategy[int | None] = None,
|
1285
1360
|
) -> int:
|
1286
1361
|
"""Strategy for generating uint64s."""
|
1287
1362
|
min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
|
1288
|
-
min_value_ =
|
1289
|
-
max_value_ =
|
1363
|
+
min_value_ = max_nullable([min_value_, MIN_UINT64])
|
1364
|
+
max_value_ = min_nullable([max_value_, MAX_UINT64])
|
1290
1365
|
return draw(integers(min_value=min_value_, max_value=max_value_))
|
1291
1366
|
|
1292
1367
|
|
@@ -1374,7 +1449,29 @@ def year_months(
|
|
1374
1449
|
|
1375
1450
|
|
1376
1451
|
@composite
|
1377
|
-
def
|
1452
|
+
def zoned_date_time_periods(
|
1453
|
+
draw: DrawFn,
|
1454
|
+
/,
|
1455
|
+
*,
|
1456
|
+
min_value: MaybeSearchStrategy[PlainDateTime | ZonedDateTime | None] = None,
|
1457
|
+
max_value: MaybeSearchStrategy[PlainDateTime | ZonedDateTime | None] = None,
|
1458
|
+
time_zone: MaybeSearchStrategy[TimeZoneLike] = UTC,
|
1459
|
+
) -> ZonedDateTimePeriod:
|
1460
|
+
"""Strategy for generating zoned date-time periods."""
|
1461
|
+
min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
|
1462
|
+
time_zone_: TimeZoneLike = draw2(draw, time_zone)
|
1463
|
+
strategy = zoned_date_times(
|
1464
|
+
min_value=min_value_, max_value=max_value_, time_zone=time_zone_
|
1465
|
+
)
|
1466
|
+
start, end = draw(pairs(strategy, sorted=True))
|
1467
|
+
return ZonedDateTimePeriod(start, end)
|
1468
|
+
|
1469
|
+
|
1470
|
+
##
|
1471
|
+
|
1472
|
+
|
1473
|
+
@composite
|
1474
|
+
def zoned_date_times(
|
1378
1475
|
draw: DrawFn,
|
1379
1476
|
/,
|
1380
1477
|
*,
|
@@ -1382,7 +1479,7 @@ def zoned_datetimes(
|
|
1382
1479
|
max_value: MaybeSearchStrategy[PlainDateTime | ZonedDateTime | None] = None,
|
1383
1480
|
time_zone: MaybeSearchStrategy[TimeZoneLike] = UTC,
|
1384
1481
|
) -> ZonedDateTime:
|
1385
|
-
"""Strategy for generating zoned
|
1482
|
+
"""Strategy for generating zoned date-times."""
|
1386
1483
|
min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
|
1387
1484
|
time_zone_ = ensure_time_zone(draw2(draw, time_zone))
|
1388
1485
|
match min_value_:
|
@@ -1401,7 +1498,7 @@ def zoned_datetimes(
|
|
1401
1498
|
max_value_ = max_value_.to_tz(time_zone_.key).to_plain()
|
1402
1499
|
case never:
|
1403
1500
|
assert_never(never)
|
1404
|
-
plain = draw(
|
1501
|
+
plain = draw(plain_date_times(min_value=min_value_, max_value=max_value_))
|
1405
1502
|
with (
|
1406
1503
|
assume_does_not_raise(RepeatedTime),
|
1407
1504
|
assume_does_not_raise(SkippedTime),
|
@@ -1415,7 +1512,7 @@ def zoned_datetimes(
|
|
1415
1512
|
return zoned
|
1416
1513
|
|
1417
1514
|
|
1418
|
-
|
1515
|
+
zoned_date_times_2000 = zoned_date_times(
|
1419
1516
|
min_value=ZonedDateTime(2000, 1, 1, tz=UTC.key),
|
1420
1517
|
max_value=ZonedDateTime(2000, 12, 31, tz=UTC.key),
|
1421
1518
|
)
|
@@ -1427,6 +1524,7 @@ __all__ = [
|
|
1427
1524
|
"assume_does_not_raise",
|
1428
1525
|
"bool_arrays",
|
1429
1526
|
"date_deltas",
|
1527
|
+
"date_periods",
|
1430
1528
|
"date_time_deltas",
|
1431
1529
|
"dates",
|
1432
1530
|
"draw2",
|
@@ -1438,6 +1536,8 @@ __all__ = [
|
|
1438
1536
|
"hashables",
|
1439
1537
|
"import_froms",
|
1440
1538
|
"imports",
|
1539
|
+
"int8s",
|
1540
|
+
"int16s",
|
1441
1541
|
"int32s",
|
1442
1542
|
"int64s",
|
1443
1543
|
"int_arrays",
|
@@ -1446,7 +1546,7 @@ __all__ = [
|
|
1446
1546
|
"numbers",
|
1447
1547
|
"pairs",
|
1448
1548
|
"paths",
|
1449
|
-
"
|
1549
|
+
"plain_date_times",
|
1450
1550
|
"py_datetimes",
|
1451
1551
|
"random_states",
|
1452
1552
|
"sentinels",
|
@@ -1463,6 +1563,7 @@ __all__ = [
|
|
1463
1563
|
"text_digits",
|
1464
1564
|
"text_printable",
|
1465
1565
|
"time_deltas",
|
1566
|
+
"time_periods",
|
1466
1567
|
"times",
|
1467
1568
|
"triples",
|
1468
1569
|
"uint8s",
|
@@ -1472,6 +1573,7 @@ __all__ = [
|
|
1472
1573
|
"urls",
|
1473
1574
|
"versions",
|
1474
1575
|
"year_months",
|
1475
|
-
"
|
1476
|
-
"
|
1576
|
+
"zoned_date_time_periods",
|
1577
|
+
"zoned_date_times",
|
1578
|
+
"zoned_date_times_2000",
|
1477
1579
|
]
|
utilities/orjson.py
CHANGED
@@ -5,7 +5,7 @@ import re
|
|
5
5
|
from collections.abc import Callable, Iterable, Mapping, Sequence
|
6
6
|
from contextlib import suppress
|
7
7
|
from dataclasses import dataclass, field, replace
|
8
|
-
from enum import Enum, unique
|
8
|
+
from enum import Enum, StrEnum, unique
|
9
9
|
from functools import cached_property, partial
|
10
10
|
from itertools import chain
|
11
11
|
from logging import Formatter, LogRecord
|
@@ -52,7 +52,12 @@ from utilities.math import MAX_INT64, MIN_INT64
|
|
52
52
|
from utilities.types import Dataclass, LogLevel, MaybeIterable, PathLike, StrMapping
|
53
53
|
from utilities.tzlocal import LOCAL_TIME_ZONE
|
54
54
|
from utilities.version import Version, parse_version
|
55
|
-
from utilities.whenever import
|
55
|
+
from utilities.whenever import (
|
56
|
+
DatePeriod,
|
57
|
+
TimePeriod,
|
58
|
+
ZonedDateTimePeriod,
|
59
|
+
from_timestamp,
|
60
|
+
)
|
56
61
|
|
57
62
|
if TYPE_CHECKING:
|
58
63
|
from collections.abc import Set as AbstractSet
|
@@ -65,10 +70,11 @@ if TYPE_CHECKING:
|
|
65
70
|
|
66
71
|
|
67
72
|
@unique
|
68
|
-
class _Prefixes(
|
73
|
+
class _Prefixes(StrEnum):
|
69
74
|
dataclass = "dc"
|
70
75
|
date = "d"
|
71
76
|
date_delta = "dd"
|
77
|
+
date_period = "dp"
|
72
78
|
date_time_delta = "D"
|
73
79
|
enum = "e"
|
74
80
|
exception_class = "Ex"
|
@@ -77,7 +83,7 @@ class _Prefixes(Enum):
|
|
77
83
|
frozenset_ = "fr"
|
78
84
|
list_ = "l"
|
79
85
|
month_day = "md"
|
80
|
-
none = "
|
86
|
+
none = "0"
|
81
87
|
path = "p"
|
82
88
|
plain_date_time = "pd"
|
83
89
|
py_date = "!d"
|
@@ -87,12 +93,14 @@ class _Prefixes(Enum):
|
|
87
93
|
set_ = "s"
|
88
94
|
time = "ti"
|
89
95
|
time_delta = "td"
|
96
|
+
time_period = "tp"
|
90
97
|
tuple_ = "tu"
|
91
98
|
unserializable = "un"
|
92
99
|
uuid = "uu"
|
93
100
|
version = "v"
|
94
101
|
year_month = "ym"
|
95
102
|
zoned_date_time = "zd"
|
103
|
+
zoned_date_time_period = "zp"
|
96
104
|
|
97
105
|
|
98
106
|
type _DataclassHook = Callable[[type[Dataclass], StrMapping], StrMapping]
|
@@ -167,8 +175,10 @@ def _pre_process(
|
|
167
175
|
return f"[{_Prefixes.date.value}]{date}"
|
168
176
|
case DateDelta() as date:
|
169
177
|
return f"[{_Prefixes.date_delta.value}]{date}"
|
170
|
-
case
|
171
|
-
return f"[{_Prefixes.
|
178
|
+
case DatePeriod() as period:
|
179
|
+
return f"[{_Prefixes.date_period.value}]{period.start},{period.end}"
|
180
|
+
case DateTimeDelta() as date_time_delta:
|
181
|
+
return f"[{_Prefixes.date_time_delta.value}]{date_time_delta}"
|
172
182
|
case Exception() as error_:
|
173
183
|
return {
|
174
184
|
f"[{_Prefixes.exception_instance.value}|{type(error_).__qualname__}]": pre(
|
@@ -187,14 +197,16 @@ def _pre_process(
|
|
187
197
|
return f"[{_Prefixes.month_day.value}]{month_day!s}"
|
188
198
|
case Path() as path:
|
189
199
|
return f"[{_Prefixes.path.value}]{path!s}"
|
190
|
-
case PlainDateTime() as
|
191
|
-
return f"[{_Prefixes.plain_date_time.value}]{
|
192
|
-
case str() as
|
193
|
-
return
|
200
|
+
case PlainDateTime() as date_time:
|
201
|
+
return f"[{_Prefixes.plain_date_time.value}]{date_time}"
|
202
|
+
case str() as text:
|
203
|
+
return text
|
194
204
|
case Time() as time:
|
195
205
|
return f"[{_Prefixes.time.value}]{time}"
|
196
206
|
case TimeDelta() as time_delta:
|
197
207
|
return f"[{_Prefixes.time_delta.value}]{time_delta}"
|
208
|
+
case TimePeriod() as period:
|
209
|
+
return f"[{_Prefixes.time_period.value}]{period.start},{period.end}"
|
198
210
|
case type() as error_cls if issubclass(error_cls, Exception):
|
199
211
|
return f"[{_Prefixes.exception_class.value}|{error_cls.__qualname__}]"
|
200
212
|
case UUID() as uuid:
|
@@ -203,8 +215,12 @@ def _pre_process(
|
|
203
215
|
return f"[{_Prefixes.version.value}]{version}"
|
204
216
|
case YearMonth() as year_month:
|
205
217
|
return f"[{_Prefixes.year_month.value}]{year_month}"
|
206
|
-
case ZonedDateTime() as
|
207
|
-
return f"[{_Prefixes.zoned_date_time.value}]{
|
218
|
+
case ZonedDateTime() as date_time:
|
219
|
+
return f"[{_Prefixes.zoned_date_time.value}]{date_time}"
|
220
|
+
case ZonedDateTimePeriod() as period:
|
221
|
+
return (
|
222
|
+
f"[{_Prefixes.zoned_date_time_period.value}]{period.start},{period.end}"
|
223
|
+
)
|
208
224
|
case dt.datetime() as py_datetime:
|
209
225
|
match py_datetime.tzinfo:
|
210
226
|
case None:
|
@@ -369,6 +385,7 @@ def deserialize(
|
|
369
385
|
(
|
370
386
|
_DATE_PATTERN,
|
371
387
|
_DATE_DELTA_PATTERN,
|
388
|
+
_DATE_PERIOD_PATTERN,
|
372
389
|
_DATE_TIME_DELTA_PATTERN,
|
373
390
|
_FLOAT_PATTERN,
|
374
391
|
_MONTH_DAY_PATTERN,
|
@@ -381,15 +398,18 @@ def deserialize(
|
|
381
398
|
_PY_ZONED_DATE_TIME_PATTERN,
|
382
399
|
_TIME_PATTERN,
|
383
400
|
_TIME_DELTA_PATTERN,
|
401
|
+
_TIME_PERIOD_PATTERN,
|
384
402
|
_UUID_PATTERN,
|
385
403
|
_VERSION_PATTERN,
|
386
404
|
_YEAR_MONTH_PATTERN,
|
387
405
|
_ZONED_DATE_TIME_PATTERN,
|
406
|
+
_ZONED_DATE_TIME_PERIOD_PATTERN,
|
388
407
|
) = [
|
389
408
|
re.compile(r"^\[" + p.value + r"\](" + ".*" + ")$")
|
390
409
|
for p in [
|
391
410
|
_Prefixes.date,
|
392
411
|
_Prefixes.date_delta,
|
412
|
+
_Prefixes.date_period,
|
393
413
|
_Prefixes.date_time_delta,
|
394
414
|
_Prefixes.float_,
|
395
415
|
_Prefixes.month_day,
|
@@ -402,10 +422,12 @@ def deserialize(
|
|
402
422
|
_Prefixes.py_zoned_date_time,
|
403
423
|
_Prefixes.time,
|
404
424
|
_Prefixes.time_delta,
|
425
|
+
_Prefixes.time_period,
|
405
426
|
_Prefixes.uuid,
|
406
427
|
_Prefixes.version,
|
407
428
|
_Prefixes.year_month,
|
408
429
|
_Prefixes.zoned_date_time,
|
430
|
+
_Prefixes.zoned_date_time_period,
|
409
431
|
]
|
410
432
|
]
|
411
433
|
|
@@ -453,6 +475,9 @@ def _object_hook(
|
|
453
475
|
return Date.parse_common_iso(match.group(1))
|
454
476
|
if match := _DATE_DELTA_PATTERN.search(text):
|
455
477
|
return DateDelta.parse_common_iso(match.group(1))
|
478
|
+
if match := _DATE_PERIOD_PATTERN.search(text):
|
479
|
+
start, end = map(Date.parse_common_iso, match.group(1).split(","))
|
480
|
+
return DatePeriod(start, end)
|
456
481
|
if match := _DATE_TIME_DELTA_PATTERN.search(text):
|
457
482
|
return DateTimeDelta.parse_common_iso(match.group(1))
|
458
483
|
if match := _FLOAT_PATTERN.search(text):
|
@@ -475,6 +500,9 @@ def _object_hook(
|
|
475
500
|
return Time.parse_common_iso(match.group(1))
|
476
501
|
if match := _TIME_DELTA_PATTERN.search(text):
|
477
502
|
return TimeDelta.parse_common_iso(match.group(1))
|
503
|
+
if match := _TIME_PERIOD_PATTERN.search(text):
|
504
|
+
start, end = map(Time.parse_common_iso, match.group(1).split(","))
|
505
|
+
return TimePeriod(start, end)
|
478
506
|
if match := _UUID_PATTERN.search(text):
|
479
507
|
return UUID(match.group(1))
|
480
508
|
if match := _VERSION_PATTERN.search(text):
|
@@ -483,6 +511,11 @@ def _object_hook(
|
|
483
511
|
return YearMonth.parse_common_iso(match.group(1))
|
484
512
|
if match := _ZONED_DATE_TIME_PATTERN.search(text):
|
485
513
|
return ZonedDateTime.parse_common_iso(match.group(1))
|
514
|
+
if match := _ZONED_DATE_TIME_PERIOD_PATTERN.search(text):
|
515
|
+
start, end = map(
|
516
|
+
ZonedDateTime.parse_common_iso, match.group(1).split(",")
|
517
|
+
)
|
518
|
+
return ZonedDateTimePeriod(start, end)
|
486
519
|
if (
|
487
520
|
exc_class := _object_hook_exception_class(
|
488
521
|
text, data=data, objects=objects, redirects=redirects
|
utilities/polars.py
CHANGED
@@ -43,9 +43,9 @@ from polars import (
|
|
43
43
|
from polars._typing import PolarsDataType
|
44
44
|
from polars.datatypes import DataType, DataTypeClass
|
45
45
|
from polars.exceptions import (
|
46
|
-
ColumnNotFoundError,
|
46
|
+
ColumnNotFoundError, # pyright: ignore[reportAttributeAccessIssue]
|
47
47
|
NoRowsReturnedError,
|
48
|
-
OutOfBoundsError,
|
48
|
+
OutOfBoundsError, # pyright: ignore[reportAttributeAccessIssue]
|
49
49
|
PolarsInefficientMapWarning,
|
50
50
|
)
|
51
51
|
from polars.schema import Schema
|
utilities/pytest_regressions.py
CHANGED
@@ -91,7 +91,9 @@ class PolarsRegressionFixture:
|
|
91
91
|
def check(self, obj: Series | DataFrame, /, *, suffix: str | None = None) -> None:
|
92
92
|
"""Check the Series/DataFrame summary against the baseline."""
|
93
93
|
from polars import DataFrame, Series, col
|
94
|
-
from polars.exceptions import
|
94
|
+
from polars.exceptions import (
|
95
|
+
InvalidOperationError, # pyright: ignore[reportAttributeAccessIssue]
|
96
|
+
)
|
95
97
|
|
96
98
|
data: StrMapping = {
|
97
99
|
"describe": obj.describe(percentiles=[i / 10 for i in range(1, 10)]).rows(
|
File without changes
|
File without changes
|
File without changes
|