dycw-utilities 0.125.19__py3-none-any.whl → 0.125.21__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.
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dycw-utilities
3
- Version: 0.125.19
3
+ Version: 0.125.21
4
4
  Author-email: Derek Wan <d.wan@icloud.com>
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
7
7
  Requires-Dist: typing-extensions<4.14,>=4.13.1
8
8
  Provides-Extra: test
9
- Requires-Dist: hypothesis<6.132,>=6.131.30; extra == 'test'
9
+ Requires-Dist: hypothesis<6.132,>=6.131.32; extra == 'test'
10
10
  Requires-Dist: pytest-asyncio<1.1,>=1.0.0; extra == 'test'
11
11
  Requires-Dist: pytest-cov<6.2,>=6.1.1; extra == 'test'
12
12
  Requires-Dist: pytest-instafail<0.6,>=0.5.0; extra == 'test'
@@ -78,7 +78,7 @@ Provides-Extra: zzz-test-hypothesis
78
78
  Requires-Dist: aiosqlite<0.22,>=0.21.0; extra == 'zzz-test-hypothesis'
79
79
  Requires-Dist: asyncpg<0.31,>=0.30.0; extra == 'zzz-test-hypothesis'
80
80
  Requires-Dist: greenlet<3.3,>=3.2.0; extra == 'zzz-test-hypothesis'
81
- Requires-Dist: hypothesis<6.132,>=6.131.30; extra == 'zzz-test-hypothesis'
81
+ Requires-Dist: hypothesis<6.132,>=6.131.32; extra == 'zzz-test-hypothesis'
82
82
  Requires-Dist: luigi<3.7,>=3.6.0; extra == 'zzz-test-hypothesis'
83
83
  Requires-Dist: numpy<2.3,>=2.2.6; extra == 'zzz-test-hypothesis'
84
84
  Requires-Dist: pathvalidate<3.3,>=3.2.3; extra == 'zzz-test-hypothesis'
@@ -1,19 +1,19 @@
1
- utilities/__init__.py,sha256=xbWByimnNYAwGR2H45VzrhSnh2lnyKX0gBtEq-G4W3w,61
1
+ utilities/__init__.py,sha256=w16go3vHbb763oQxxUHlPrGNReaPnuMsxxD4YRz2JeE,61
2
2
  utilities/altair.py,sha256=Gpja-flOo-Db0PIPJLJsgzAlXWoKUjPU1qY-DQ829ek,9156
3
- utilities/asyncio.py,sha256=D1o5dwq1y17Nk5tzeDyw5vAwxzqdy9WMY5u-uA6NMPw,50716
3
+ utilities/asyncio.py,sha256=pQ5GRcNyBqmDyeAeSarYugrjSNxmX3E0G9pye-kkPt4,51085
4
4
  utilities/atomicwrites.py,sha256=geFjn9Pwn-tTrtoGjDDxWli9NqbYfy3gGL6ZBctiqSo,5393
5
5
  utilities/atools.py,sha256=IYMuFSFGSKyuQmqD6v5IUtDlz8PPw0Sr87Cub_gRU3M,1168
6
6
  utilities/cachetools.py,sha256=C1zqOg7BYz0IfQFK8e3qaDDgEZxDpo47F15RTfJM37Q,2910
7
7
  utilities/click.py,sha256=SRVkUkWxyO_7AaYvvDl0hNCzdpneX04lf1O97i9MfPw,14311
8
8
  utilities/concurrent.py,sha256=s2scTEd2AhXVTW4hpASU2qxV_DiVLALfms55cCQzCvM,2886
9
- utilities/contextlib.py,sha256=OOIIEa5lXKGzFAnauaul40nlQnQko6Na4ryiMJcHkIg,478
9
+ utilities/contextlib.py,sha256=lpaLJBy3X0UGLWjM98jkQZZq8so4fRmoK-Bheq0uOW4,1027
10
10
  utilities/contextvars.py,sha256=RsSGGrbQqqZ67rOydnM7WWIsM2lIE31UHJLejnHJPWY,505
11
11
  utilities/cryptography.py,sha256=_CiK_K6c_-uQuUhsUNjNjTL-nqxAh4_1zTfS11Xe120,972
12
12
  utilities/cvxpy.py,sha256=Rv1-fD-XYerosCavRF8Pohop2DBkU3AlFaGTfD8AEAA,13776
13
13
  utilities/dataclasses.py,sha256=iiC1wpGXWhaocIikzwBt8bbLWyImoUlOlcDZJGejaIg,33011
14
14
  utilities/datetime.py,sha256=uYoaOi_C1YtNXGfTN9xlTrW62Re2b1_4Skuv14_MeYQ,38985
15
15
  utilities/enum.py,sha256=HoRwVCWzsnH0vpO9ZEcAAIZLMv0Sn2vJxxA4sYMQgDs,5793
16
- utilities/errors.py,sha256=C89Xm-DHUjfqJKROo1pW-RGat8zDvTzZuy6zBNMkj_s,837
16
+ utilities/errors.py,sha256=wg6Jrgz5T_KbmG_PXF6pbDFSFso9CG93RGz1Om6Q0Lk,848
17
17
  utilities/eventkit.py,sha256=6M5Xu1SzN-juk9PqBHwy5dS-ta7T0qA6SMpDsakOJ0E,13039
18
18
  utilities/fastapi.py,sha256=LG1-Q8RDi7wsyVN6v74qptPYX8WGXPkFOQFniMvtzjc,2439
19
19
  utilities/fpdf2.py,sha256=y1NGXR5chWqLXWpewGV3hlRGMr_5yV1lVRkPBhPEgJI,1843
@@ -89,7 +89,7 @@ utilities/warnings.py,sha256=un1LvHv70PU-LLv8RxPVmugTzDJkkGXRMZTE2-fTQHw,1771
89
89
  utilities/whenever.py,sha256=jS31ZAY5OMxFxLja_Yo5Fidi87Pd-GoVZ7Vi_teqVDA,16743
90
90
  utilities/zipfile.py,sha256=24lQc9ATcJxHXBPc_tBDiJk48pWyRrlxO2fIsFxU0A8,699
91
91
  utilities/zoneinfo.py,sha256=-5j7IQ9nb7gR43rdgA7ms05im-XuqhAk9EJnQBXxCoQ,1874
92
- dycw_utilities-0.125.19.dist-info/METADATA,sha256=Ec61c2aoYg19djvl2RrwPPtCXtqIVxSkLTTH6_Fz1o8,12852
93
- dycw_utilities-0.125.19.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
94
- dycw_utilities-0.125.19.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
95
- dycw_utilities-0.125.19.dist-info/RECORD,,
92
+ dycw_utilities-0.125.21.dist-info/METADATA,sha256=Jq0hDSrXzEM1SXuG6bYbXjJb3dVNQaACnhjTHT_4yhA,12852
93
+ dycw_utilities-0.125.21.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
94
+ dycw_utilities-0.125.21.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
95
+ dycw_utilities-0.125.21.dist-info/RECORD,,
utilities/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.125.19"
3
+ __version__ = "0.125.21"
utilities/asyncio.py CHANGED
@@ -59,6 +59,7 @@ from utilities.datetime import (
59
59
  )
60
60
  from utilities.errors import ImpossibleCaseError, repr_error
61
61
  from utilities.functions import ensure_int, ensure_not_none, get_class_name
62
+ from utilities.random import SYSTEM_RANDOM
62
63
  from utilities.sentinel import Sentinel, sentinel
63
64
  from utilities.types import (
64
65
  Coroutine1,
@@ -75,6 +76,7 @@ if TYPE_CHECKING:
75
76
  from collections import deque
76
77
  from collections.abc import AsyncIterator, Sequence
77
78
  from contextvars import Context
79
+ from random import Random
78
80
  from types import TracebackType
79
81
 
80
82
  from utilities.types import Duration
@@ -1305,6 +1307,18 @@ async def sleep_dur(*, duration: Duration | None = None) -> None:
1305
1307
  ##
1306
1308
 
1307
1309
 
1310
+ async def sleep_max_dur(
1311
+ *, duration: Duration | None = None, random: Random = SYSTEM_RANDOM
1312
+ ) -> None:
1313
+ """Sleep which accepts max durations."""
1314
+ if duration is None:
1315
+ return
1316
+ await sleep(random.uniform(0.0, datetime_duration_to_float(duration)))
1317
+
1318
+
1319
+ ##
1320
+
1321
+
1308
1322
  async def sleep_until(datetime: dt.datetime, /) -> None:
1309
1323
  """Sleep until a given time."""
1310
1324
  await sleep_dur(duration=datetime - get_now())
@@ -1407,6 +1421,7 @@ __all__ = [
1407
1421
  "put_items",
1408
1422
  "put_items_nowait",
1409
1423
  "sleep_dur",
1424
+ "sleep_max_dur",
1410
1425
  "sleep_until",
1411
1426
  "sleep_until_rounded",
1412
1427
  "stream_command",
utilities/contextlib.py CHANGED
@@ -1,12 +1,17 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import re
4
+ from contextlib import contextmanager
3
5
  from typing import TYPE_CHECKING
4
6
 
5
7
  if TYPE_CHECKING:
8
+ from collections.abc import Iterator
6
9
  from types import TracebackType
7
10
 
8
11
 
9
12
  class NoOpContextManager:
13
+ """Context-manager for no-op."""
14
+
10
15
  def __enter__(self) -> None:
11
16
  return None
12
17
 
@@ -20,4 +25,20 @@ class NoOpContextManager:
20
25
  return False
21
26
 
22
27
 
23
- __all__ = ["NoOpContextManager"]
28
+ ##
29
+
30
+
31
+ _SUPER_OBJECT_HAS_NO_ATTRIBUTE = re.compile(r"'super' object has no attribute '\w+'")
32
+
33
+
34
+ @contextmanager
35
+ def suppress_super_object_attribute_error() -> Iterator[None]:
36
+ """Suppress the super() attribute error, for mix-ins."""
37
+ try:
38
+ yield
39
+ except AttributeError as error:
40
+ if not _SUPER_OBJECT_HAS_NO_ATTRIBUTE.search(error.args[0]):
41
+ raise
42
+
43
+
44
+ __all__ = ["NoOpContextManager", "suppress_super_object_attribute_error"]
utilities/errors.py CHANGED
@@ -15,6 +15,7 @@ class ImpossibleCaseError(Exception):
15
15
  def __str__(self) -> str:
16
16
  desc = ", ".join(self.case)
17
17
  return f"Case must be possible: {desc}."
18
+ ##
18
19
 
19
20
 
20
21
  ##