dycw-utilities 0.131.10__py3-none-any.whl → 0.131.11__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.131.10.dist-info → dycw_utilities-0.131.11.dist-info}/METADATA +1 -1
- {dycw_utilities-0.131.10.dist-info → dycw_utilities-0.131.11.dist-info}/RECORD +15 -15
- utilities/__init__.py +1 -1
- utilities/click.py +6 -6
- utilities/datetime.py +12 -12
- utilities/hypothesis.py +8 -11
- utilities/logging.py +1 -18
- utilities/math.py +10 -9
- utilities/re.py +12 -13
- utilities/traceback.py +5 -5
- utilities/types.py +49 -10
- utilities/whenever.py +6 -6
- utilities/whenever2.py +56 -2
- {dycw_utilities-0.131.10.dist-info → dycw_utilities-0.131.11.dist-info}/WHEEL +0 -0
- {dycw_utilities-0.131.10.dist-info → dycw_utilities-0.131.11.dist-info}/licenses/LICENSE +0 -0
@@ -1,18 +1,18 @@
|
|
1
|
-
utilities/__init__.py,sha256=
|
1
|
+
utilities/__init__.py,sha256=wP5J8Mq8g6P6zyTVUVaa3X4tWb427OMAAyoOjt4J0qQ,61
|
2
2
|
utilities/aiolimiter.py,sha256=mD0wEiqMgwpty4XTbawFpnkkmJS6R4JRsVXFUaoitSU,628
|
3
3
|
utilities/altair.py,sha256=HeZBVUocjkrTNwwKrClppsIqgNFF-ykv05HfZSoHYno,9104
|
4
4
|
utilities/asyncio.py,sha256=yfKvAIDCRrWdyQMVZMo4DJQx4nVrXoAcqwhNuF95Ryo,38186
|
5
5
|
utilities/atomicwrites.py,sha256=geFjn9Pwn-tTrtoGjDDxWli9NqbYfy3gGL6ZBctiqSo,5393
|
6
6
|
utilities/atools.py,sha256=IYMuFSFGSKyuQmqD6v5IUtDlz8PPw0Sr87Cub_gRU3M,1168
|
7
7
|
utilities/cachetools.py,sha256=C1zqOg7BYz0IfQFK8e3qaDDgEZxDpo47F15RTfJM37Q,2910
|
8
|
-
utilities/click.py,sha256=
|
8
|
+
utilities/click.py,sha256=8gRYeyu9KQ3uim0UpC8VnFnOOKD3DyGwMJ7k0Qns1lM,14659
|
9
9
|
utilities/concurrent.py,sha256=s2scTEd2AhXVTW4hpASU2qxV_DiVLALfms55cCQzCvM,2886
|
10
10
|
utilities/contextlib.py,sha256=lpaLJBy3X0UGLWjM98jkQZZq8so4fRmoK-Bheq0uOW4,1027
|
11
11
|
utilities/contextvars.py,sha256=RsSGGrbQqqZ67rOydnM7WWIsM2lIE31UHJLejnHJPWY,505
|
12
12
|
utilities/cryptography.py,sha256=_CiK_K6c_-uQuUhsUNjNjTL-nqxAh4_1zTfS11Xe120,972
|
13
13
|
utilities/cvxpy.py,sha256=Rv1-fD-XYerosCavRF8Pohop2DBkU3AlFaGTfD8AEAA,13776
|
14
14
|
utilities/dataclasses.py,sha256=iiC1wpGXWhaocIikzwBt8bbLWyImoUlOlcDZJGejaIg,33011
|
15
|
-
utilities/datetime.py,sha256=
|
15
|
+
utilities/datetime.py,sha256=cDb0-fE7rRt3Gwl5vJ1HW0ZWf-wW7PHsQruD6or9hUo,38770
|
16
16
|
utilities/enum.py,sha256=HoRwVCWzsnH0vpO9ZEcAAIZLMv0Sn2vJxxA4sYMQgDs,5793
|
17
17
|
utilities/errors.py,sha256=nC7ZYtxxDBMfrTHtT_MByBfup_wfGQFRo3eDt-0ZPe8,1045
|
18
18
|
utilities/eventkit.py,sha256=6M5Xu1SzN-juk9PqBHwy5dS-ta7T0qA6SMpDsakOJ0E,13039
|
@@ -24,7 +24,7 @@ utilities/getpass.py,sha256=DfN5UgMAtFCqS3dSfFHUfqIMZX2shXvwphOz_6J6f6A,103
|
|
24
24
|
utilities/git.py,sha256=oi7-_l5e9haSANSCvQw25ufYGoNahuUPHAZ6114s3JQ,1191
|
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=spJCB3bKcSMFKuSwi184xfTbom_HEBLB0_-AiPnSR-A,49822
|
28
28
|
utilities/importlib.py,sha256=mV1xT_O_zt_GnZZ36tl3xOmMaN_3jErDWY54fX39F6Y,429
|
29
29
|
utilities/inflect.py,sha256=DbqB5Q9FbRGJ1NbvEiZBirRMxCxgrz91zy5jCO9ZIs0,347
|
30
30
|
utilities/ipython.py,sha256=V2oMYHvEKvlNBzxDXdLvKi48oUq2SclRg5xasjaXStw,763
|
@@ -32,9 +32,9 @@ utilities/iterables.py,sha256=mDqw2_0MUVp-P8FklgcaVTi2TXduH0MxbhTDzzhSBho,44915
|
|
32
32
|
utilities/jupyter.py,sha256=ft5JA7fBxXKzP-L9W8f2-wbF0QeYc_2uLQNFDVk4Z-M,2917
|
33
33
|
utilities/libcst.py,sha256=Jto5ppzRzsxn4AD32IS8n0lbgLYXwsVJB6EY8giNZyY,4974
|
34
34
|
utilities/lightweight_charts.py,sha256=JrkrAZMo6JID2Eoc9QCc05Y_pK4l2zsApIhmii1z2Ig,2764
|
35
|
-
utilities/logging.py,sha256=
|
35
|
+
utilities/logging.py,sha256=GP2BqpUlb9T7v90sdavsweJnOxfSdK7cJKFdgKURJZo,17892
|
36
36
|
utilities/luigi.py,sha256=fpH9MbxJDuo6-k9iCXRayFRtiVbUtibCJKugf7ygpv0,5988
|
37
|
-
utilities/math.py,sha256
|
37
|
+
utilities/math.py,sha256=_6vrDyjtaqE_OFE-F2DNWrDG_J_kMl3nFAJsok9v_bY,26862
|
38
38
|
utilities/memory_profiler.py,sha256=tf2C51P2lCujPGvRt2Rfc7VEw5LDXmVPCG3z_AvBmbU,962
|
39
39
|
utilities/modules.py,sha256=iuvLluJya-hvl1Q25-Jk3dLgx2Es3ck4SjJiEkAlVTs,3195
|
40
40
|
utilities/more_itertools.py,sha256=tBbjjKx8_Uv_TCjxhPwrGfAx_jRHtvLIZqXVWAsjzqA,8842
|
@@ -61,7 +61,7 @@ utilities/pytest.py,sha256=zP4CWKXpRVk4aRDRxolUAvqQwX7wgDO8lzmkQfuZaZo,7832
|
|
61
61
|
utilities/pytest_regressions.py,sha256=YI55B7EtLjhz7zPJZ6NK9bWrxrKCKabWZJe1cwcbA5o,5082
|
62
62
|
utilities/python_dotenv.py,sha256=edXsvHZhZnYeqfMfrsRRpj7_9eJI6uizh3xLx8Q9B3w,3228
|
63
63
|
utilities/random.py,sha256=lYdjgxB7GCfU_fwFVl5U-BIM_HV3q6_urL9byjrwDM8,4157
|
64
|
-
utilities/re.py,sha256=
|
64
|
+
utilities/re.py,sha256=6qxeV0rQZaBDKWcB7apSBmxtg_XzoGY-EdegTkMn-ZY,4578
|
65
65
|
utilities/redis.py,sha256=IceT5EjgrebVkGL8X3M35xlqjI2c7zFbyV1P4dExN4M,36037
|
66
66
|
utilities/reprlib.py,sha256=ssYTcBW-TeRh3fhCJv57sopTZHF5FrPyyUg9yp5XBlo,3953
|
67
67
|
utilities/scipy.py,sha256=wZJM7fEgBAkLSYYvSmsg5ac-QuwAI0BGqHVetw1_Hb0,947
|
@@ -79,19 +79,19 @@ utilities/tenacity.py,sha256=1PUvODiBVgeqIh7G5TRt5WWMSqjLYkEqP53itT97WQc,4914
|
|
79
79
|
utilities/text.py,sha256=ymBFlP_cA8OgNnZRVNs7FAh7OG8HxE6YkiLEMZv5g_A,11297
|
80
80
|
utilities/threading.py,sha256=GvBOp4CyhHfN90wGXZuA2VKe9fGzMaEa7oCl4f3nnPU,1009
|
81
81
|
utilities/timer.py,sha256=VeSl3ot8-f4D1d3HjjSsgKvjxHJGXd_sW4KcTExOR64,2475
|
82
|
-
utilities/traceback.py,sha256=
|
83
|
-
utilities/types.py,sha256=
|
82
|
+
utilities/traceback.py,sha256=U8Du13z0qFo7sntup2x8xLw49KNb-QtEv7-UgziZ_Cw,8769
|
83
|
+
utilities/types.py,sha256=CHQke10ETEpypxppYVhWp1G68S6mvifalrRLolYBcCg,19506
|
84
84
|
utilities/typing.py,sha256=kQWywPcRbFBKmvQBELmgbiqSHsnlo_D0ru53vl6KDeY,13846
|
85
85
|
utilities/tzdata.py,sha256=yCf70NICwAeazN3_JcXhWvRqCy06XJNQ42j7r6gw3HY,1217
|
86
86
|
utilities/tzlocal.py,sha256=P5BjqTiYskeCwjE7i9zycCFXO4MWdZgYCh4jut-LpzA,1042
|
87
87
|
utilities/uuid.py,sha256=jJTFxz-CWgltqNuzmythB7iEQ-Q1mCwPevUfKthZT3c,611
|
88
88
|
utilities/version.py,sha256=ufhJMmI6KPs1-3wBI71aj5wCukd3sP_m11usLe88DNA,5117
|
89
89
|
utilities/warnings.py,sha256=un1LvHv70PU-LLv8RxPVmugTzDJkkGXRMZTE2-fTQHw,1771
|
90
|
-
utilities/whenever.py,sha256=
|
91
|
-
utilities/whenever2.py,sha256=
|
90
|
+
utilities/whenever.py,sha256=2NQ-0SnLNW2kFpefP9dVE8H0RbaeusXYLPmv282Jpto,16755
|
91
|
+
utilities/whenever2.py,sha256=76tFaAVX5CfXOjjMJ1Sg3LW85RoYARNZIALseCLG81k,7047
|
92
92
|
utilities/zipfile.py,sha256=24lQc9ATcJxHXBPc_tBDiJk48pWyRrlxO2fIsFxU0A8,699
|
93
93
|
utilities/zoneinfo.py,sha256=tvcgu3QzDxe2suTexi2QzRGpin7VK1TjHa0JYYxT69I,1862
|
94
|
-
dycw_utilities-0.131.
|
95
|
-
dycw_utilities-0.131.
|
96
|
-
dycw_utilities-0.131.
|
97
|
-
dycw_utilities-0.131.
|
94
|
+
dycw_utilities-0.131.11.dist-info/METADATA,sha256=m2QhrLfCIpPGxtKXK8nVbiyX5ldnlLwNHjQnHy9UWkk,1585
|
95
|
+
dycw_utilities-0.131.11.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
96
|
+
dycw_utilities-0.131.11.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
|
97
|
+
dycw_utilities-0.131.11.dist-info/RECORD,,
|
utilities/__init__.py
CHANGED
utilities/click.py
CHANGED
@@ -23,13 +23,13 @@ from utilities.functions import EnsureStrError, ensure_str, get_class_name
|
|
23
23
|
from utilities.iterables import is_iterable_not_str
|
24
24
|
from utilities.text import split_str
|
25
25
|
from utilities.types import (
|
26
|
-
DateLike,
|
27
26
|
DateTimeLike,
|
28
27
|
EnumLike,
|
29
28
|
MaybeStr,
|
29
|
+
PyDateLike,
|
30
|
+
PyTimeDeltaLike,
|
31
|
+
PyTimeLike,
|
30
32
|
TEnum,
|
31
|
-
TimeDeltaLike,
|
32
|
-
TimeLike,
|
33
33
|
)
|
34
34
|
|
35
35
|
if TYPE_CHECKING:
|
@@ -76,7 +76,7 @@ class Date(ParamType):
|
|
76
76
|
|
77
77
|
@override
|
78
78
|
def convert(
|
79
|
-
self, value:
|
79
|
+
self, value: PyDateLike, param: Parameter | None, ctx: Context | None
|
80
80
|
) -> dt.date:
|
81
81
|
"""Convert a value into the `Date` type."""
|
82
82
|
from utilities.whenever import EnsureDateError, ensure_date
|
@@ -197,7 +197,7 @@ class Time(ParamType):
|
|
197
197
|
|
198
198
|
@override
|
199
199
|
def convert(
|
200
|
-
self, value:
|
200
|
+
self, value: PyTimeLike, param: Parameter | None, ctx: Context | None
|
201
201
|
) -> dt.time:
|
202
202
|
"""Convert a value into the `Time` type."""
|
203
203
|
from utilities.whenever import EnsureTimeError, ensure_time
|
@@ -219,7 +219,7 @@ class Timedelta(ParamType):
|
|
219
219
|
|
220
220
|
@override
|
221
221
|
def convert(
|
222
|
-
self, value:
|
222
|
+
self, value: PyTimeDeltaLike, param: Parameter | None, ctx: Context | None
|
223
223
|
) -> dt.timedelta:
|
224
224
|
"""Convert a value into the `Timedelta` type."""
|
225
225
|
from utilities.whenever import EnsureTimedeltaError, ensure_timedelta
|
utilities/datetime.py
CHANGED
@@ -31,9 +31,9 @@ if TYPE_CHECKING:
|
|
31
31
|
from utilities.types import (
|
32
32
|
DateOrDateTime,
|
33
33
|
Duration,
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
MathRoundMode,
|
35
|
+
MaybeCallablePyDate,
|
36
|
+
MaybeCallablePyDateTime,
|
37
37
|
TimeZoneLike,
|
38
38
|
)
|
39
39
|
|
@@ -476,19 +476,19 @@ def format_datetime_local_and_utc(datetime: dt.datetime, /) -> str:
|
|
476
476
|
|
477
477
|
|
478
478
|
@overload
|
479
|
-
def get_date(*, date:
|
479
|
+
def get_date(*, date: MaybeCallablePyDate) -> dt.date: ...
|
480
480
|
@overload
|
481
481
|
def get_date(*, date: None) -> None: ...
|
482
482
|
@overload
|
483
483
|
def get_date(*, date: Sentinel) -> Sentinel: ...
|
484
484
|
@overload
|
485
|
-
def get_date(*, date:
|
485
|
+
def get_date(*, date: MaybeCallablePyDate | Sentinel) -> dt.date | Sentinel: ...
|
486
486
|
@overload
|
487
487
|
def get_date(
|
488
|
-
*, date:
|
488
|
+
*, date: MaybeCallablePyDate | None | Sentinel = sentinel
|
489
489
|
) -> dt.date | None | Sentinel: ...
|
490
490
|
def get_date(
|
491
|
-
*, date:
|
491
|
+
*, date: MaybeCallablePyDate | None | Sentinel = sentinel
|
492
492
|
) -> dt.date | None | Sentinel:
|
493
493
|
"""Get the date."""
|
494
494
|
match date:
|
@@ -504,13 +504,13 @@ def get_date(
|
|
504
504
|
|
505
505
|
|
506
506
|
@overload
|
507
|
-
def get_datetime(*, datetime:
|
507
|
+
def get_datetime(*, datetime: MaybeCallablePyDateTime) -> dt.datetime: ...
|
508
508
|
@overload
|
509
509
|
def get_datetime(*, datetime: None) -> None: ...
|
510
510
|
@overload
|
511
511
|
def get_datetime(*, datetime: Sentinel) -> Sentinel: ...
|
512
512
|
def get_datetime(
|
513
|
-
*, datetime:
|
513
|
+
*, datetime: MaybeCallablePyDateTime | None | Sentinel = sentinel
|
514
514
|
) -> dt.datetime | None | Sentinel:
|
515
515
|
"""Get the datetime."""
|
516
516
|
match datetime:
|
@@ -755,7 +755,7 @@ def mean_datetime(
|
|
755
755
|
/,
|
756
756
|
*,
|
757
757
|
weights: Iterable[SupportsFloat] | None = None,
|
758
|
-
mode:
|
758
|
+
mode: MathRoundMode = "standard",
|
759
759
|
rel_tol: float | None = None,
|
760
760
|
abs_tol: float | None = None,
|
761
761
|
) -> dt.datetime:
|
@@ -790,7 +790,7 @@ def mean_timedelta(
|
|
790
790
|
/,
|
791
791
|
*,
|
792
792
|
weights: Iterable[SupportsFloat] | None = None,
|
793
|
-
mode:
|
793
|
+
mode: MathRoundMode = "standard",
|
794
794
|
rel_tol: float | None = None,
|
795
795
|
abs_tol: float | None = None,
|
796
796
|
) -> dt.timedelta:
|
@@ -1022,7 +1022,7 @@ def round_datetime(
|
|
1022
1022
|
duration: Duration,
|
1023
1023
|
/,
|
1024
1024
|
*,
|
1025
|
-
mode:
|
1025
|
+
mode: MathRoundMode = "standard",
|
1026
1026
|
rel_tol: float | None = None,
|
1027
1027
|
abs_tol: float | None = None,
|
1028
1028
|
) -> dt.datetime:
|
utilities/hypothesis.py
CHANGED
@@ -48,7 +48,7 @@ from hypothesis.strategies import (
|
|
48
48
|
uuids,
|
49
49
|
)
|
50
50
|
from hypothesis.utils.conventions import not_set
|
51
|
-
from whenever import Date, DateDelta, PlainDateTime, Time, TimeDelta
|
51
|
+
from whenever import Date, DateDelta, PlainDateTime, Time, TimeDelta, ZonedDateTime
|
52
52
|
|
53
53
|
from utilities.datetime import (
|
54
54
|
DATETIME_MAX_NAIVE,
|
@@ -112,10 +112,9 @@ if TYPE_CHECKING:
|
|
112
112
|
|
113
113
|
from hypothesis.database import ExampleDatabase
|
114
114
|
from numpy.random import RandomState
|
115
|
-
from whenever import ZonedDateTime
|
116
115
|
|
117
116
|
from utilities.numpy import NDArrayB, NDArrayF, NDArrayI, NDArrayO
|
118
|
-
from utilities.types import Duration,
|
117
|
+
from utilities.types import Duration, MathRoundMode, Number, TimeZoneLike
|
119
118
|
|
120
119
|
|
121
120
|
_T = TypeVar("_T")
|
@@ -725,7 +724,7 @@ def min_and_max_datetimes(
|
|
725
724
|
min_value: MaybeSearchStrategy[dt.datetime | None] = None,
|
726
725
|
max_value: MaybeSearchStrategy[dt.datetime | None] = None,
|
727
726
|
time_zone: MaybeSearchStrategy[ZoneInfo | timezone] = UTC,
|
728
|
-
round_:
|
727
|
+
round_: MathRoundMode | None = None,
|
729
728
|
timedelta: dt.timedelta | None = None,
|
730
729
|
rel_tol: float | None = None,
|
731
730
|
abs_tol: float | None = None,
|
@@ -804,7 +803,7 @@ def min_and_maybe_max_datetimes(
|
|
804
803
|
min_value: MaybeSearchStrategy[dt.datetime | None] = None,
|
805
804
|
max_value: MaybeSearchStrategy[dt.datetime | None | Sentinel] = sentinel,
|
806
805
|
time_zone: MaybeSearchStrategy[ZoneInfo | timezone] = UTC,
|
807
|
-
round_:
|
806
|
+
round_: MathRoundMode | None = None,
|
808
807
|
timedelta: dt.timedelta | None = None,
|
809
808
|
rel_tol: float | None = None,
|
810
809
|
abs_tol: float | None = None,
|
@@ -1036,7 +1035,7 @@ def plain_datetimes(
|
|
1036
1035
|
*,
|
1037
1036
|
min_value: MaybeSearchStrategy[dt.datetime] = DATETIME_MIN_NAIVE,
|
1038
1037
|
max_value: MaybeSearchStrategy[dt.datetime] = DATETIME_MAX_NAIVE,
|
1039
|
-
round_:
|
1038
|
+
round_: MathRoundMode | None = None,
|
1040
1039
|
timedelta: dt.timedelta | None = None,
|
1041
1040
|
rel_tol: float | None = None,
|
1042
1041
|
abs_tol: float | None = None,
|
@@ -1056,7 +1055,7 @@ def plain_datetimes(
|
|
1056
1055
|
|
1057
1056
|
@dataclass(kw_only=True, slots=True)
|
1058
1057
|
class PlainDateTimesError(Exception):
|
1059
|
-
round_:
|
1058
|
+
round_: MathRoundMode
|
1060
1059
|
|
1061
1060
|
@override
|
1062
1061
|
def __str__(self) -> str:
|
@@ -1577,7 +1576,7 @@ def zoned_datetimes(
|
|
1577
1576
|
min_value: MaybeSearchStrategy[dt.datetime] = DATETIME_MIN_UTC + DAY,
|
1578
1577
|
max_value: MaybeSearchStrategy[dt.datetime] = DATETIME_MAX_UTC - DAY,
|
1579
1578
|
time_zone: MaybeSearchStrategy[ZoneInfo | timezone] = UTC,
|
1580
|
-
round_:
|
1579
|
+
round_: MathRoundMode | None = None,
|
1581
1580
|
timedelta: dt.timedelta | None = None,
|
1582
1581
|
rel_tol: float | None = None,
|
1583
1582
|
abs_tol: float | None = None,
|
@@ -1626,7 +1625,7 @@ def zoned_datetimes(
|
|
1626
1625
|
|
1627
1626
|
@dataclass(kw_only=True, slots=True)
|
1628
1627
|
class ZonedDateTimesError(Exception):
|
1629
|
-
round_:
|
1628
|
+
round_: MathRoundMode
|
1630
1629
|
|
1631
1630
|
@override
|
1632
1631
|
def __str__(self) -> str:
|
@@ -1646,8 +1645,6 @@ def zoned_datetimes_whenever(
|
|
1646
1645
|
time_zone: MaybeSearchStrategy[TimeZoneLike] = UTC,
|
1647
1646
|
) -> ZonedDateTime:
|
1648
1647
|
"""Strategy for generating zoned datetimes."""
|
1649
|
-
from whenever import PlainDateTime, ZonedDateTime
|
1650
|
-
|
1651
1648
|
min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
|
1652
1649
|
time_zone_ = ensure_time_zone(draw2(draw, time_zone))
|
1653
1650
|
match min_value_:
|
utilities/logging.py
CHANGED
@@ -34,12 +34,7 @@ from typing import (
|
|
34
34
|
|
35
35
|
from utilities.atomicwrites import move_many
|
36
36
|
from utilities.dataclasses import replace_non_sentinel
|
37
|
-
from utilities.datetime import
|
38
|
-
SECOND,
|
39
|
-
parse_datetime_compact,
|
40
|
-
round_datetime,
|
41
|
-
serialize_compact,
|
42
|
-
)
|
37
|
+
from utilities.datetime import parse_datetime_compact, serialize_compact
|
43
38
|
from utilities.errors import ImpossibleCaseError
|
44
39
|
from utilities.iterables import OneEmptyError, always_iterable, one
|
45
40
|
from utilities.pathlib import ensure_suffix, get_path
|
@@ -484,12 +479,6 @@ class _RotatingLogFile:
|
|
484
479
|
start: dt.datetime | None = None
|
485
480
|
end: dt.datetime | None = None
|
486
481
|
|
487
|
-
def __post_init__(self) -> None:
|
488
|
-
if self.start is not None:
|
489
|
-
self.start = round_datetime(self.start, SECOND)
|
490
|
-
if self.end is not None:
|
491
|
-
self.end = round_datetime(self.end, SECOND)
|
492
|
-
|
493
482
|
@classmethod
|
494
483
|
def from_path(
|
495
484
|
cls,
|
@@ -582,12 +571,6 @@ class _Rotation:
|
|
582
571
|
start: dt.datetime | None | Sentinel = sentinel
|
583
572
|
end: dt.datetime | Sentinel = sentinel
|
584
573
|
|
585
|
-
def __post_init__(self) -> None:
|
586
|
-
if isinstance(self.start, dt.datetime):
|
587
|
-
self.start = round_datetime(self.start, SECOND)
|
588
|
-
if isinstance(self.end, dt.datetime):
|
589
|
-
self.end = round_datetime(self.end, SECOND)
|
590
|
-
|
591
574
|
@cached_property
|
592
575
|
def destination(self) -> Path:
|
593
576
|
return self.file.replace(index=self.index, start=self.start, end=self.end).path
|
utilities/math.py
CHANGED
@@ -8,9 +8,10 @@ from re import Match, search
|
|
8
8
|
from typing import TYPE_CHECKING, Literal, assert_never, overload, override
|
9
9
|
|
10
10
|
from utilities.errors import ImpossibleCaseError
|
11
|
+
from utilities.re import ExtractGroupsError, extract_groups
|
11
12
|
|
12
13
|
if TYPE_CHECKING:
|
13
|
-
from utilities.types import
|
14
|
+
from utilities.types import MathRoundMode, Number, Sign
|
14
15
|
|
15
16
|
|
16
17
|
MIN_FLOAT32, MAX_FLOAT32 = -3.4028234663852886e38, 3.4028234663852886e38
|
@@ -708,7 +709,7 @@ def round_(
|
|
708
709
|
x: float,
|
709
710
|
/,
|
710
711
|
*,
|
711
|
-
mode:
|
712
|
+
mode: MathRoundMode = "standard",
|
712
713
|
rel_tol: float | None = None,
|
713
714
|
abs_tol: float | None = None,
|
714
715
|
) -> int:
|
@@ -748,7 +749,7 @@ def round_(
|
|
748
749
|
|
749
750
|
def _round_tie_standard(
|
750
751
|
x: float,
|
751
|
-
mode:
|
752
|
+
mode: MathRoundMode,
|
752
753
|
/,
|
753
754
|
*,
|
754
755
|
rel_tol: float | None = None,
|
@@ -757,9 +758,9 @@ def _round_tie_standard(
|
|
757
758
|
"""Round a float to an integer using the standard method."""
|
758
759
|
frac, _ = modf(x)
|
759
760
|
if _is_close(abs(frac), 0.5, rel_tol=rel_tol, abs_tol=abs_tol):
|
760
|
-
mode_use:
|
761
|
+
mode_use: MathRoundMode = mode
|
761
762
|
else:
|
762
|
-
mode_use:
|
763
|
+
mode_use: MathRoundMode = "standard"
|
763
764
|
return round_(x, mode=mode_use)
|
764
765
|
|
765
766
|
|
@@ -775,9 +776,9 @@ def round_float_imprecisions(
|
|
775
776
|
) -> float:
|
776
777
|
"""Round a float, removing binary representation imprecisions."""
|
777
778
|
try:
|
778
|
-
|
779
|
-
except
|
780
|
-
|
779
|
+
head, tail = extract_groups(_ROUND_FLOAT_IMPRECISIONS_PATTERN, str(x))
|
780
|
+
except ExtractGroupsError:
|
781
|
+
head, tail = extract_groups(_ROUND_FLOAT_IMPRECISIONS_PATTERN, f"{x:.20f}")
|
781
782
|
half = ceil(decimals / 2)
|
782
783
|
pattern0 = search(rf"^([0-9]+?)(0{{{half},}})([0-9]+?)$", tail)
|
783
784
|
pattern9 = search(rf"^(0*)([0-9]+?)(9{{{half},}})([0-9]+?)$", tail)
|
@@ -823,7 +824,7 @@ def round_to_float(
|
|
823
824
|
y: float,
|
824
825
|
/,
|
825
826
|
*,
|
826
|
-
mode:
|
827
|
+
mode: MathRoundMode = "standard",
|
827
828
|
rel_tol: float | None = None,
|
828
829
|
abs_tol: float | None = None,
|
829
830
|
) -> float:
|
utilities/re.py
CHANGED
@@ -5,8 +5,6 @@ from dataclasses import dataclass
|
|
5
5
|
from re import Pattern
|
6
6
|
from typing import TYPE_CHECKING, assert_never, override
|
7
7
|
|
8
|
-
from utilities.iterables import OneEmptyError, OneNonUniqueError, one
|
9
|
-
|
10
8
|
if TYPE_CHECKING:
|
11
9
|
from utilities.types import PatternLike
|
12
10
|
|
@@ -36,16 +34,17 @@ def extract_group(pattern: PatternLike, text: str, /, *, flags: int = 0) -> str:
|
|
36
34
|
raise _ExtractGroupNoCaptureGroupsError(pattern=pattern_use, text=text)
|
37
35
|
case 1:
|
38
36
|
matches: list[str] = pattern_use.findall(text)
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
37
|
+
match len(matches):
|
38
|
+
case 0:
|
39
|
+
raise _ExtractGroupNoMatchesError(
|
40
|
+
pattern=pattern_use, text=text
|
41
|
+
) from None
|
42
|
+
case 1:
|
43
|
+
return matches[0]
|
44
|
+
case _:
|
45
|
+
raise _ExtractGroupMultipleMatchesError(
|
46
|
+
pattern=pattern_use, text=text, matches=matches
|
47
|
+
) from None
|
49
48
|
case _:
|
50
49
|
raise _ExtractGroupMultipleCaptureGroupsError(
|
51
50
|
pattern=pattern_use, text=text
|
@@ -109,7 +108,7 @@ def extract_groups(pattern: PatternLike, text: str, /, *, flags: int = 0) -> lis
|
|
109
108
|
case 1, 1:
|
110
109
|
return matches
|
111
110
|
case 1, _:
|
112
|
-
return list(
|
111
|
+
return list(matches[0])
|
113
112
|
case _:
|
114
113
|
raise _ExtractGroupsMultipleMatchesError(
|
115
114
|
pattern=pattern_use, text=text, matches=matches
|
utilities/traceback.py
CHANGED
@@ -36,7 +36,7 @@ if TYPE_CHECKING:
|
|
36
36
|
from traceback import FrameSummary
|
37
37
|
from types import TracebackType
|
38
38
|
|
39
|
-
from utilities.types import
|
39
|
+
from utilities.types import MaybeCallablePathLike, MaybeCallablePyDateTime, PathLike
|
40
40
|
from utilities.version import MaybeCallableVersionLike
|
41
41
|
|
42
42
|
|
@@ -51,7 +51,7 @@ def format_exception_stack(
|
|
51
51
|
/,
|
52
52
|
*,
|
53
53
|
header: bool = False,
|
54
|
-
start:
|
54
|
+
start: MaybeCallablePyDateTime | None = _START,
|
55
55
|
version: MaybeCallableVersionLike | None = None,
|
56
56
|
capture_locals: bool = False,
|
57
57
|
max_width: int = RICH_MAX_WIDTH,
|
@@ -82,7 +82,7 @@ def format_exception_stack(
|
|
82
82
|
|
83
83
|
def _yield_header_lines(
|
84
84
|
*,
|
85
|
-
start:
|
85
|
+
start: MaybeCallablePyDateTime | None = _START,
|
86
86
|
version: MaybeCallableVersionLike | None = None,
|
87
87
|
) -> Iterator[str]:
|
88
88
|
"""Yield the header lines."""
|
@@ -193,7 +193,7 @@ def _trim_path(path: PathLike, pattern: str, /) -> Path | None:
|
|
193
193
|
|
194
194
|
def make_except_hook(
|
195
195
|
*,
|
196
|
-
start:
|
196
|
+
start: MaybeCallablePyDateTime | None = _START,
|
197
197
|
version: MaybeCallableVersionLike | None = None,
|
198
198
|
path: MaybeCallablePathLike | None = None,
|
199
199
|
max_width: int = RICH_MAX_WIDTH,
|
@@ -228,7 +228,7 @@ def _make_except_hook_inner(
|
|
228
228
|
traceback: TracebackType | None,
|
229
229
|
/,
|
230
230
|
*,
|
231
|
-
start:
|
231
|
+
start: MaybeCallablePyDateTime | None = _START,
|
232
232
|
version: MaybeCallableVersionLike | None = None,
|
233
233
|
path: MaybeCallablePathLike | None = None,
|
234
234
|
max_width: int = RICH_MAX_WIDTH,
|
utilities/types.py
CHANGED
@@ -20,6 +20,16 @@ from typing import (
|
|
20
20
|
)
|
21
21
|
from zoneinfo import ZoneInfo
|
22
22
|
|
23
|
+
from whenever import (
|
24
|
+
Date,
|
25
|
+
DateDelta,
|
26
|
+
DateTimeDelta,
|
27
|
+
PlainDateTime,
|
28
|
+
Time,
|
29
|
+
TimeDelta,
|
30
|
+
ZonedDateTime,
|
31
|
+
)
|
32
|
+
|
23
33
|
_T_co = TypeVar("_T_co", covariant=True)
|
24
34
|
_T_contra = TypeVar("_T_contra", contravariant=True)
|
25
35
|
|
@@ -88,17 +98,16 @@ TDataclass = TypeVar("TDataclass", bound=Dataclass)
|
|
88
98
|
|
89
99
|
|
90
100
|
# datetime
|
91
|
-
type DateLike = MaybeStr[dt.date]
|
92
|
-
type DateTimeLike = MaybeStr[dt.datetime]
|
93
101
|
type DateOrDateTime = dt.date | dt.datetime
|
102
|
+
type DateTimeLike = MaybeStr[dt.datetime]
|
94
103
|
type Duration = Number | dt.timedelta
|
95
104
|
type DurationLike = MaybeStr[Duration]
|
96
105
|
type DurationOrEveryDuration = Duration | tuple[Literal["every"], Duration]
|
97
|
-
type
|
98
|
-
type
|
99
|
-
type
|
100
|
-
type
|
101
|
-
type
|
106
|
+
type MaybeCallablePyDate = MaybeCallable[dt.date]
|
107
|
+
type MaybeCallablePyDateTime = MaybeCallable[dt.datetime]
|
108
|
+
type PyDateLike = MaybeStr[dt.date]
|
109
|
+
type PyTimeDeltaLike = MaybeStr[dt.timedelta]
|
110
|
+
type PyTimeLike = MaybeStr[dt.time]
|
102
111
|
|
103
112
|
|
104
113
|
# enum
|
@@ -133,7 +142,7 @@ type LoggerOrName = MaybeStr[Logger]
|
|
133
142
|
|
134
143
|
# math
|
135
144
|
type Number = int | float
|
136
|
-
type
|
145
|
+
type MathRoundMode = Literal[
|
137
146
|
"standard",
|
138
147
|
"floor",
|
139
148
|
"ceil",
|
@@ -259,6 +268,25 @@ type ExcInfo = tuple[type[BaseException], BaseException, TracebackType]
|
|
259
268
|
type OptExcInfo = ExcInfo | tuple[None, None, None]
|
260
269
|
|
261
270
|
|
271
|
+
# whenever
|
272
|
+
type DateDeltaLike = MaybeStr[DateDelta]
|
273
|
+
type DateLike = MaybeStr[Date]
|
274
|
+
type DateTimeDeltaLike = MaybeStr[DateTimeDelta]
|
275
|
+
type MaybeCallableDate = MaybeCallable[Date]
|
276
|
+
type MaybeCallableZonedDateTime = MaybeCallable[ZonedDateTime]
|
277
|
+
type PlainDateTimeLike = MaybeStr[PlainDateTime]
|
278
|
+
type TimeDeltaLike = MaybeStr[TimeDelta]
|
279
|
+
type TimeLike = MaybeStr[Time]
|
280
|
+
type ZonedDateTimeLike = MaybeStr[ZonedDateTime]
|
281
|
+
type DateTimeRoundUnit = Literal[
|
282
|
+
"day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"
|
283
|
+
]
|
284
|
+
type DateTimeRoundMode = Literal[
|
285
|
+
"ceil", "floor", "half_ceil", "half_floor", "half_even"
|
286
|
+
]
|
287
|
+
type WeekDay = Literal["mon", "tue", "wed", "thu", "fri", "sat", "sun"]
|
288
|
+
|
289
|
+
|
262
290
|
# zoneinfo
|
263
291
|
# fmt: off
|
264
292
|
type TimeZone = Literal[
|
@@ -271,9 +299,13 @@ type TimeZoneLike = ZoneInfo | Literal["local"] | TimeZone | dt.tzinfo | dt.date
|
|
271
299
|
__all__ = [
|
272
300
|
"Coroutine1",
|
273
301
|
"Dataclass",
|
302
|
+
"DateDeltaLike",
|
274
303
|
"DateLike",
|
275
304
|
"DateOrDateTime",
|
305
|
+
"DateTimeDeltaLike",
|
276
306
|
"DateTimeLike",
|
307
|
+
"DateTimeRoundMode",
|
308
|
+
"DateTimeRoundUnit",
|
277
309
|
"Duration",
|
278
310
|
"DurationLike",
|
279
311
|
"DurationOrEveryDuration",
|
@@ -282,12 +314,15 @@ __all__ = [
|
|
282
314
|
"IterableHashable",
|
283
315
|
"LogLevel",
|
284
316
|
"LoggerOrName",
|
317
|
+
"MathRoundMode",
|
285
318
|
"MaybeAwaitable",
|
286
319
|
"MaybeCallable",
|
287
320
|
"MaybeCallableDate",
|
288
|
-
"MaybeCallableDateTime",
|
289
321
|
"MaybeCallableEvent",
|
290
322
|
"MaybeCallablePathLike",
|
323
|
+
"MaybeCallablePyDate",
|
324
|
+
"MaybeCallablePyDateTime",
|
325
|
+
"MaybeCallableZonedDateTime",
|
291
326
|
"MaybeCoroutine1",
|
292
327
|
"MaybeIterable",
|
293
328
|
"MaybeIterableHashable",
|
@@ -300,7 +335,10 @@ __all__ = [
|
|
300
335
|
"ParseObjectExtra",
|
301
336
|
"PathLike",
|
302
337
|
"PatternLike",
|
303
|
-
"
|
338
|
+
"PlainDateTimeLike",
|
339
|
+
"PyDateLike",
|
340
|
+
"PyTimeDeltaLike",
|
341
|
+
"PyTimeLike",
|
304
342
|
"Seed",
|
305
343
|
"SerializeObjectExtra",
|
306
344
|
"Sign",
|
@@ -343,4 +381,5 @@ __all__ = [
|
|
343
381
|
"TupleOrStrMapping",
|
344
382
|
"TypeLike",
|
345
383
|
"WeekDay",
|
384
|
+
"ZonedDateTimeLike",
|
346
385
|
]
|
utilities/whenever.py
CHANGED
@@ -34,12 +34,12 @@ from utilities.zoneinfo import UTC, ensure_time_zone, get_time_zone_name
|
|
34
34
|
|
35
35
|
if TYPE_CHECKING:
|
36
36
|
from utilities.types import (
|
37
|
-
DateLike,
|
38
37
|
DateTimeLike,
|
39
38
|
Duration,
|
40
39
|
DurationLike,
|
41
|
-
|
42
|
-
|
40
|
+
PyDateLike,
|
41
|
+
PyTimeDeltaLike,
|
42
|
+
PyTimeLike,
|
43
43
|
)
|
44
44
|
|
45
45
|
|
@@ -91,7 +91,7 @@ class _CheckValidZonedDateTimeUnequalError(CheckValidZonedDateTimeError):
|
|
91
91
|
##
|
92
92
|
|
93
93
|
|
94
|
-
def ensure_date(date:
|
94
|
+
def ensure_date(date: PyDateLike, /) -> dt.date:
|
95
95
|
"""Ensure the object is a date."""
|
96
96
|
if isinstance(date, dt.date):
|
97
97
|
check_date_not_datetime(date)
|
@@ -180,7 +180,7 @@ class EnsurePlainDateTimeError(Exception):
|
|
180
180
|
##
|
181
181
|
|
182
182
|
|
183
|
-
def ensure_time(time:
|
183
|
+
def ensure_time(time: PyTimeLike, /) -> dt.time:
|
184
184
|
"""Ensure the object is a time."""
|
185
185
|
if isinstance(time, dt.time):
|
186
186
|
return time
|
@@ -202,7 +202,7 @@ class EnsureTimeError(Exception):
|
|
202
202
|
##
|
203
203
|
|
204
204
|
|
205
|
-
def ensure_timedelta(timedelta:
|
205
|
+
def ensure_timedelta(timedelta: PyTimeDeltaLike, /) -> dt.timedelta:
|
206
206
|
"""Ensure the object is a timedelta."""
|
207
207
|
if isinstance(timedelta, dt.timedelta):
|
208
208
|
return timedelta
|
utilities/whenever2.py
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import datetime as dt
|
4
|
+
from collections.abc import Callable
|
4
5
|
from functools import cache
|
5
6
|
from logging import LogRecord
|
6
|
-
from typing import TYPE_CHECKING, Any, override
|
7
|
+
from typing import TYPE_CHECKING, Any, assert_never, overload, override
|
7
8
|
|
8
9
|
from whenever import (
|
9
10
|
Date,
|
@@ -15,12 +16,17 @@ from whenever import (
|
|
15
16
|
ZonedDateTime,
|
16
17
|
)
|
17
18
|
|
19
|
+
from utilities.sentinel import Sentinel, sentinel
|
18
20
|
from utilities.zoneinfo import UTC, get_time_zone_name
|
19
21
|
|
20
22
|
if TYPE_CHECKING:
|
21
23
|
from zoneinfo import ZoneInfo
|
22
24
|
|
23
|
-
from utilities.types import
|
25
|
+
from utilities.types import (
|
26
|
+
MaybeCallableDate,
|
27
|
+
MaybeCallableZonedDateTime,
|
28
|
+
TimeZoneLike,
|
29
|
+
)
|
24
30
|
|
25
31
|
|
26
32
|
## bounds
|
@@ -118,6 +124,52 @@ def get_today_local() -> Date:
|
|
118
124
|
|
119
125
|
TODAY_LOCAL = get_today_local()
|
120
126
|
|
127
|
+
##
|
128
|
+
|
129
|
+
|
130
|
+
@overload
|
131
|
+
def to_date(*, date: MaybeCallableDate) -> Date: ...
|
132
|
+
@overload
|
133
|
+
def to_date(*, date: None) -> None: ...
|
134
|
+
@overload
|
135
|
+
def to_date(*, date: Sentinel) -> Sentinel: ...
|
136
|
+
@overload
|
137
|
+
def to_date(*, date: MaybeCallableDate | Sentinel) -> Date | Sentinel: ...
|
138
|
+
@overload
|
139
|
+
def to_date(
|
140
|
+
*, date: MaybeCallableDate | None | Sentinel = sentinel
|
141
|
+
) -> Date | None | Sentinel: ...
|
142
|
+
def to_date(
|
143
|
+
*, date: MaybeCallableDate | None | Sentinel = sentinel
|
144
|
+
) -> Date | None | Sentinel:
|
145
|
+
"""Get the date."""
|
146
|
+
match date:
|
147
|
+
case Date() | None | Sentinel():
|
148
|
+
return date
|
149
|
+
case Callable() as func:
|
150
|
+
return to_date(date=func())
|
151
|
+
case _ as never:
|
152
|
+
assert_never(never)
|
153
|
+
|
154
|
+
|
155
|
+
@overload
|
156
|
+
def to_zoned_date_time(*, date_time: MaybeCallableZonedDateTime) -> ZonedDateTime: ...
|
157
|
+
@overload
|
158
|
+
def to_zoned_date_time(*, date_time: None) -> None: ...
|
159
|
+
@overload
|
160
|
+
def to_zoned_date_time(*, date_time: Sentinel) -> Sentinel: ...
|
161
|
+
def to_zoned_date_time(
|
162
|
+
*, date_time: MaybeCallableZonedDateTime | None | Sentinel = sentinel
|
163
|
+
) -> ZonedDateTime | None | Sentinel:
|
164
|
+
"""Resolve into a zoned date_time."""
|
165
|
+
match date_time:
|
166
|
+
case ZonedDateTime() | None | Sentinel():
|
167
|
+
return date_time
|
168
|
+
case Callable() as func:
|
169
|
+
return to_zoned_date_time(date_time=func())
|
170
|
+
case _ as never:
|
171
|
+
assert_never(never)
|
172
|
+
|
121
173
|
|
122
174
|
##
|
123
175
|
|
@@ -210,4 +262,6 @@ __all__ = [
|
|
210
262
|
"get_now_local",
|
211
263
|
"get_today",
|
212
264
|
"get_today_local",
|
265
|
+
"to_date",
|
266
|
+
"to_zoned_date_time",
|
213
267
|
]
|
File without changes
|
File without changes
|