dycw-utilities 0.113.4__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dycw-utilities
3
- Version: 0.113.4
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
@@ -1,7 +1,7 @@
1
- utilities/__init__.py,sha256=f-gfMxj416K6fDUn3GBZ_ctE4iCAIW3yKwMD5u5-rOw,60
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=6Pv0xK2jP55iF6EYjY1g6_rFGOeJyihxRNxXnOsWv14,15691
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
@@ -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.4.dist-info/METADATA,sha256=ErT951cvoqudHh2P5_G-_Jhl0SziHUJZ8O8lJV4cGi8,12943
91
- dycw_utilities-0.113.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
92
- dycw_utilities-0.113.4.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
93
- dycw_utilities-0.113.4.dist-info/RECORD,,
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
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.113.4"
3
+ __version__ = "0.113.5"
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 MaybeCallableEvent, THashable, TSupportsRichComparison
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