dycw-utilities 0.113.3__py3-none-any.whl → 0.113.5__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.113.3.dist-info → dycw_utilities-0.113.5.dist-info}/METADATA +7 -7
- {dycw_utilities-0.113.3.dist-info → dycw_utilities-0.113.5.dist-info}/RECORD +8 -8
- utilities/__init__.py +1 -1
- utilities/asyncio.py +73 -3
- utilities/click.py +6 -5
- utilities/redis.py +5 -5
- {dycw_utilities-0.113.3.dist-info → dycw_utilities-0.113.5.dist-info}/WHEEL +0 -0
- {dycw_utilities-0.113.3.dist-info → dycw_utilities-0.113.5.dist-info}/licenses/LICENSE +0 -0
@@ -1,12 +1,12 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: dycw-utilities
|
3
|
-
Version: 0.113.
|
3
|
+
Version: 0.113.5
|
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.
|
9
|
+
Requires-Dist: hypothesis<6.132,>=6.131.15; extra == 'test'
|
10
10
|
Requires-Dist: pytest-asyncio<0.27,>=0.26.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'
|
@@ -14,7 +14,7 @@ Requires-Dist: pytest-lazy-fixtures<1.2,>=1.1.2; extra == 'test'
|
|
14
14
|
Requires-Dist: pytest-only<2.2,>=2.1.2; extra == 'test'
|
15
15
|
Requires-Dist: pytest-randomly<3.17,>=3.16.0; extra == 'test'
|
16
16
|
Requires-Dist: pytest-regressions<2.8,>=2.7.0; extra == 'test'
|
17
|
-
Requires-Dist: pytest-rerunfailures<16,>=15.
|
17
|
+
Requires-Dist: pytest-rerunfailures<16,>=15.1; extra == 'test'
|
18
18
|
Requires-Dist: pytest-rng<1.1,>=1.0.0; extra == 'test'
|
19
19
|
Requires-Dist: pytest-timeout<2.5,>=2.4.0; extra == 'test'
|
20
20
|
Requires-Dist: pytest-xdist<3.7,>=3.6.1; extra == 'test'
|
@@ -37,7 +37,7 @@ Requires-Dist: atools<0.15,>=0.14.2; extra == 'zzz-test-atools'
|
|
37
37
|
Provides-Extra: zzz-test-cachetools
|
38
38
|
Requires-Dist: cachetools<5.6,>=5.5.2; extra == 'zzz-test-cachetools'
|
39
39
|
Provides-Extra: zzz-test-click
|
40
|
-
Requires-Dist: click<8.
|
40
|
+
Requires-Dist: click<8.3,>=8.2.0; extra == 'zzz-test-click'
|
41
41
|
Requires-Dist: sqlalchemy<2.1,>=2.0.40; extra == 'zzz-test-click'
|
42
42
|
Requires-Dist: whenever<0.8,>=0.7.3; extra == 'zzz-test-click'
|
43
43
|
Provides-Extra: zzz-test-contextlib
|
@@ -80,7 +80,7 @@ Provides-Extra: zzz-test-hypothesis
|
|
80
80
|
Requires-Dist: aiosqlite<0.22,>=0.21.0; extra == 'zzz-test-hypothesis'
|
81
81
|
Requires-Dist: asyncpg<0.31,>=0.30.0; extra == 'zzz-test-hypothesis'
|
82
82
|
Requires-Dist: greenlet<3.3,>=3.2.0; extra == 'zzz-test-hypothesis'
|
83
|
-
Requires-Dist: hypothesis<6.132,>=6.131.
|
83
|
+
Requires-Dist: hypothesis<6.132,>=6.131.15; extra == 'zzz-test-hypothesis'
|
84
84
|
Requires-Dist: luigi<3.7,>=3.6.0; extra == 'zzz-test-hypothesis'
|
85
85
|
Requires-Dist: numpy<2.3,>=2.2.5; extra == 'zzz-test-hypothesis'
|
86
86
|
Requires-Dist: pathvalidate<3.3,>=3.2.3; extra == 'zzz-test-hypothesis'
|
@@ -101,7 +101,7 @@ Requires-Dist: polars-lts-cpu<1.30,>=1.29.0; extra == 'zzz-test-jupyter'
|
|
101
101
|
Provides-Extra: zzz-test-logging
|
102
102
|
Requires-Dist: atomicwrites<1.5,>=1.4.1; extra == 'zzz-test-logging'
|
103
103
|
Requires-Dist: coloredlogs<15.1,>=15.0.1; extra == 'zzz-test-logging'
|
104
|
-
Requires-Dist: concurrent-log-handler<0.10,>=0.9.
|
104
|
+
Requires-Dist: concurrent-log-handler<0.10,>=0.9.26; extra == 'zzz-test-logging'
|
105
105
|
Requires-Dist: rich<14.1,>=14.0.0; extra == 'zzz-test-logging'
|
106
106
|
Requires-Dist: tomlkit<0.14,>=0.13.2; extra == 'zzz-test-logging'
|
107
107
|
Requires-Dist: tzlocal<5.4,>=5.3.1; extra == 'zzz-test-logging'
|
@@ -172,7 +172,7 @@ Requires-Dist: whenever<0.8,>=0.7.3; extra == 'zzz-test-redis'
|
|
172
172
|
Provides-Extra: zzz-test-rich
|
173
173
|
Requires-Dist: rich<14.1,>=14.0.0; extra == 'zzz-test-rich'
|
174
174
|
Provides-Extra: zzz-test-scipy
|
175
|
-
Requires-Dist: scipy<1.16,>=1.15.
|
175
|
+
Requires-Dist: scipy<1.16,>=1.15.3; extra == 'zzz-test-scipy'
|
176
176
|
Provides-Extra: zzz-test-sentinel
|
177
177
|
Provides-Extra: zzz-test-shelve
|
178
178
|
Provides-Extra: zzz-test-slack-sdk
|
@@ -1,11 +1,11 @@
|
|
1
|
-
utilities/__init__.py,sha256=
|
1
|
+
utilities/__init__.py,sha256=ZrPzCX_NTAeiRK-IwTswtKYPrKcHyvHM-9skmFcsa3Q,60
|
2
2
|
utilities/altair.py,sha256=Gpja-flOo-Db0PIPJLJsgzAlXWoKUjPU1qY-DQ829ek,9156
|
3
3
|
utilities/astor.py,sha256=xuDUkjq0-b6fhtwjhbnebzbqQZAjMSHR1IIS5uOodVg,777
|
4
|
-
utilities/asyncio.py,sha256=
|
4
|
+
utilities/asyncio.py,sha256=q6hRkJ8GLJcmbah9ifdkw9LUcXAZlLh0g10aZ8cjZ54,17883
|
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=Jzm7DOI3rH-WLOTh1UHOfxkFhHU4_GJH60seLV0A-OI,14311
|
9
9
|
utilities/concurrent.py,sha256=s2scTEd2AhXVTW4hpASU2qxV_DiVLALfms55cCQzCvM,2886
|
10
10
|
utilities/contextlib.py,sha256=OOIIEa5lXKGzFAnauaul40nlQnQko6Na4ryiMJcHkIg,478
|
11
11
|
utilities/contextvars.py,sha256=RsSGGrbQqqZ67rOydnM7WWIsM2lIE31UHJLejnHJPWY,505
|
@@ -58,7 +58,7 @@ utilities/pytest_regressions.py,sha256=-SVT9647Dg6-JcdsiaDKXe3NdOmmrvGevLKWwGjxq
|
|
58
58
|
utilities/python_dotenv.py,sha256=iWcnpXbH7S6RoXHiLlGgyuH6udCupAcPd_gQ0eAenQ0,3190
|
59
59
|
utilities/random.py,sha256=lYdjgxB7GCfU_fwFVl5U-BIM_HV3q6_urL9byjrwDM8,4157
|
60
60
|
utilities/re.py,sha256=5J4d8VwIPFVrX2Eb8zfoxImDv7IwiN_U7mJ07wR2Wvs,3958
|
61
|
-
utilities/redis.py,sha256=
|
61
|
+
utilities/redis.py,sha256=otrtsfGvU5FBzqDJ7IEMQOJwG5ccFaq4TRKEMteqYk8,25489
|
62
62
|
utilities/reprlib.py,sha256=Re9bk3n-kC__9DxQmRlevqFA86pE6TtVfWjUgpbVOv0,1849
|
63
63
|
utilities/rich.py,sha256=t50MwwVBsoOLxzmeVFSVpjno4OW6Ufum32skXbV8-Bs,1911
|
64
64
|
utilities/scipy.py,sha256=X6ROnHwiUhAmPhM0jkfEh0-Fd9iRvwiqtCQMOLmOQF8,945
|
@@ -87,7 +87,7 @@ utilities/warnings.py,sha256=un1LvHv70PU-LLv8RxPVmugTzDJkkGXRMZTE2-fTQHw,1771
|
|
87
87
|
utilities/whenever.py,sha256=iLRP_-8CZtBpHKbGZGu-kjSMg1ZubJ-VSmgSy7Eudxw,17787
|
88
88
|
utilities/zipfile.py,sha256=24lQc9ATcJxHXBPc_tBDiJk48pWyRrlxO2fIsFxU0A8,699
|
89
89
|
utilities/zoneinfo.py,sha256=-Xm57PMMwDTYpxJdkiJG13wnbwK--I7XItBh5WVhD-o,1874
|
90
|
-
dycw_utilities-0.113.
|
91
|
-
dycw_utilities-0.113.
|
92
|
-
dycw_utilities-0.113.
|
93
|
-
dycw_utilities-0.113.
|
90
|
+
dycw_utilities-0.113.5.dist-info/METADATA,sha256=A14piT2adjIjfWnw8bf7FeFVUDRZfuzcsKkbFdZLrzc,12943
|
91
|
+
dycw_utilities-0.113.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
92
|
+
dycw_utilities-0.113.5.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
|
93
|
+
dycw_utilities-0.113.5.dist-info/RECORD,,
|
utilities/__init__.py
CHANGED
utilities/asyncio.py
CHANGED
@@ -17,7 +17,7 @@ from asyncio import (
|
|
17
17
|
sleep,
|
18
18
|
timeout,
|
19
19
|
)
|
20
|
-
from collections.abc import Callable
|
20
|
+
from collections.abc import Callable, Mapping
|
21
21
|
from contextlib import (
|
22
22
|
AsyncExitStack,
|
23
23
|
_AsyncGeneratorContextManager,
|
@@ -39,11 +39,17 @@ from typing import (
|
|
39
39
|
override,
|
40
40
|
)
|
41
41
|
|
42
|
-
from utilities.datetime import MILLISECOND, datetime_duration_to_float
|
42
|
+
from utilities.datetime import MILLISECOND, MINUTE, SECOND, datetime_duration_to_float
|
43
43
|
from utilities.errors import ImpossibleCaseError
|
44
44
|
from utilities.functions import ensure_int, ensure_not_none
|
45
45
|
from utilities.sentinel import Sentinel, sentinel
|
46
|
-
from utilities.types import
|
46
|
+
from utilities.types import (
|
47
|
+
Coroutine1,
|
48
|
+
MaybeCallableEvent,
|
49
|
+
MaybeType,
|
50
|
+
THashable,
|
51
|
+
TSupportsRichComparison,
|
52
|
+
)
|
47
53
|
|
48
54
|
if TYPE_CHECKING:
|
49
55
|
from asyncio import _CoroutineLike
|
@@ -320,6 +326,70 @@ class ExceptionProcessor(QueueProcessor[Exception | type[Exception]]):
|
|
320
326
|
##
|
321
327
|
|
322
328
|
|
329
|
+
@dataclass(kw_only=True)
|
330
|
+
class InfiniteLooper(ABC, Generic[THashable]):
|
331
|
+
"""An infinite loop which can throw exceptions by setting events."""
|
332
|
+
|
333
|
+
events: Mapping[THashable, Event] = field(
|
334
|
+
default_factory=dict, init=False, repr=False
|
335
|
+
)
|
336
|
+
sleep_core: Duration = SECOND
|
337
|
+
sleep_restart: Duration = MINUTE
|
338
|
+
|
339
|
+
def __post_init__(self) -> None:
|
340
|
+
self._reset_events()
|
341
|
+
|
342
|
+
async def __call__(self) -> Coroutine1[None]:
|
343
|
+
while True:
|
344
|
+
try:
|
345
|
+
self._reset_events()
|
346
|
+
try:
|
347
|
+
await self.initialize()
|
348
|
+
except Exception as error: # noqa: BLE001
|
349
|
+
self.error_upon_initialize(error)
|
350
|
+
await sleep_dur(duration=self.sleep_restart)
|
351
|
+
else:
|
352
|
+
while True:
|
353
|
+
try:
|
354
|
+
event = next(
|
355
|
+
key
|
356
|
+
for (key, value) in self.events.items()
|
357
|
+
if value.is_set()
|
358
|
+
)
|
359
|
+
except StopIteration:
|
360
|
+
await self.core()
|
361
|
+
await sleep_dur(duration=self.sleep_core)
|
362
|
+
else:
|
363
|
+
raise self.events_and_exceptions[event]
|
364
|
+
except Exception as error: # noqa: BLE001
|
365
|
+
self.error_upon_core(error)
|
366
|
+
await sleep_dur(duration=self.sleep_restart)
|
367
|
+
|
368
|
+
@property
|
369
|
+
@abstractmethod
|
370
|
+
def events_and_exceptions(self) -> Mapping[THashable, MaybeType[BaseException]]:
|
371
|
+
"""A mapping of events to exceptions."""
|
372
|
+
|
373
|
+
async def initialize(self) -> None:
|
374
|
+
"""Initialize the loop."""
|
375
|
+
|
376
|
+
async def core(self) -> None:
|
377
|
+
"""Run the core."""
|
378
|
+
|
379
|
+
def error_upon_initialize(self, error: Exception, /) -> None:
|
380
|
+
_ = error
|
381
|
+
|
382
|
+
def error_upon_core(self, error: Exception, /) -> None:
|
383
|
+
_ = error
|
384
|
+
|
385
|
+
def _reset_events(self) -> None:
|
386
|
+
"""Reset the events."""
|
387
|
+
self.events = {event: Event() for event in self.events_and_exceptions}
|
388
|
+
|
389
|
+
|
390
|
+
##
|
391
|
+
|
392
|
+
|
323
393
|
class UniquePriorityQueue(PriorityQueue[tuple[TSupportsRichComparison, THashable]]):
|
324
394
|
"""Priority queue with unique tasks."""
|
325
395
|
|
utilities/click.py
CHANGED
@@ -125,7 +125,8 @@ class Enum(ParamType, Generic[TEnum]):
|
|
125
125
|
self.fail(str(error), param, ctx)
|
126
126
|
|
127
127
|
@override
|
128
|
-
def get_metavar(self, param: Parameter) -> str | None:
|
128
|
+
def get_metavar(self, param: Parameter, ctx: Context) -> str | None:
|
129
|
+
_ = ctx
|
129
130
|
desc = ",".join(e.name for e in self._enum)
|
130
131
|
return _make_metavar(param, desc)
|
131
132
|
|
@@ -273,8 +274,8 @@ class FrozenSetParameter(ParamType, Generic[_TParam, _T]):
|
|
273
274
|
return frozenset(self._param.convert(v, param, ctx) for v in values)
|
274
275
|
|
275
276
|
@override
|
276
|
-
def get_metavar(self, param: Parameter) -> str | None:
|
277
|
-
if (metavar := self._param.get_metavar(param)) is None:
|
277
|
+
def get_metavar(self, param: Parameter, ctx: Context) -> str | None:
|
278
|
+
if (metavar := self._param.get_metavar(param, ctx)) is None:
|
278
279
|
name = self.name.upper()
|
279
280
|
else:
|
280
281
|
name = f"FROZENSET{metavar}"
|
@@ -397,8 +398,8 @@ class ListParameter(ParamType, Generic[_TParam, _T]):
|
|
397
398
|
return [self._param.convert(v, param, ctx) for v in values]
|
398
399
|
|
399
400
|
@override
|
400
|
-
def get_metavar(self, param: Parameter) -> str | None:
|
401
|
-
if (metavar := self._param.get_metavar(param)) is None:
|
401
|
+
def get_metavar(self, param: Parameter, ctx: Context) -> str | None:
|
402
|
+
if (metavar := self._param.get_metavar(param, ctx)) is None:
|
402
403
|
name = self.name.upper()
|
403
404
|
else:
|
404
405
|
name = f"LIST{metavar}"
|
utilities/redis.py
CHANGED
@@ -607,7 +607,7 @@ class Publisher(QueueProcessor[tuple[str, EncodableT]]):
|
|
607
607
|
|
608
608
|
|
609
609
|
_SUBSCRIBE_TIMEOUT: Duration = SECOND
|
610
|
-
_SUBSCRIBE_SLEEP: Duration =
|
610
|
+
_SUBSCRIBE_SLEEP: Duration = MILLISECOND
|
611
611
|
|
612
612
|
|
613
613
|
@overload
|
@@ -617,8 +617,8 @@ def subscribe(
|
|
617
617
|
/,
|
618
618
|
*,
|
619
619
|
deserializer: Callable[[bytes], _T],
|
620
|
-
timeout: Duration | None =
|
621
|
-
sleep: Duration =
|
620
|
+
timeout: Duration | None = _SUBSCRIBE_TIMEOUT,
|
621
|
+
sleep: Duration = _SUBSCRIBE_SLEEP,
|
622
622
|
) -> AsyncIterator[_T]: ...
|
623
623
|
@overload
|
624
624
|
def subscribe(
|
@@ -627,8 +627,8 @@ def subscribe(
|
|
627
627
|
/,
|
628
628
|
*,
|
629
629
|
deserializer: None = None,
|
630
|
-
timeout: Duration | None =
|
631
|
-
sleep: Duration =
|
630
|
+
timeout: Duration | None = _SUBSCRIBE_TIMEOUT,
|
631
|
+
sleep: Duration = _SUBSCRIBE_SLEEP,
|
632
632
|
) -> AsyncIterator[bytes]: ...
|
633
633
|
async def subscribe(
|
634
634
|
pubsub: PubSub,
|
File without changes
|
File without changes
|