dycw-utilities 0.131.16__py3-none-any.whl → 0.131.17__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.16.dist-info → dycw_utilities-0.131.17.dist-info}/METADATA +1 -1
- {dycw_utilities-0.131.16.dist-info → dycw_utilities-0.131.17.dist-info}/RECORD +12 -13
- utilities/__init__.py +1 -1
- utilities/asyncio.py +47 -60
- utilities/pottery.py +16 -19
- utilities/psutil.py +8 -7
- utilities/redis.py +108 -116
- utilities/slack_sdk.py +17 -18
- utilities/sqlalchemy.py +36 -30
- utilities/sqlalchemy_polars.py +12 -27
- utilities/tenacity.py +0 -145
- {dycw_utilities-0.131.16.dist-info → dycw_utilities-0.131.17.dist-info}/WHEEL +0 -0
- {dycw_utilities-0.131.16.dist-info → dycw_utilities-0.131.17.dist-info}/licenses/LICENSE +0 -0
utilities/slack_sdk.py
CHANGED
@@ -7,21 +7,21 @@ from typing import TYPE_CHECKING, Any, Self, override
|
|
7
7
|
|
8
8
|
from slack_sdk.webhook.async_client import AsyncWebhookClient
|
9
9
|
|
10
|
-
from utilities.asyncio import Looper,
|
11
|
-
from utilities.datetime import MINUTE, SECOND, datetime_duration_to_float
|
10
|
+
from utilities.asyncio import Looper, timeout_td
|
12
11
|
from utilities.functools import cache
|
13
|
-
from utilities.math import safe_round
|
14
12
|
from utilities.sentinel import Sentinel, sentinel
|
13
|
+
from utilities.whenever2 import MINUTE, SECOND
|
15
14
|
|
16
15
|
if TYPE_CHECKING:
|
17
16
|
from collections.abc import Callable
|
18
17
|
|
19
18
|
from slack_sdk.webhook import WebhookResponse
|
19
|
+
from whenever import TimeDelta
|
20
20
|
|
21
|
-
from utilities.types import Coroutine1
|
21
|
+
from utilities.types import Coroutine1
|
22
22
|
|
23
23
|
|
24
|
-
_TIMEOUT:
|
24
|
+
_TIMEOUT: TimeDelta = MINUTE
|
25
25
|
|
26
26
|
|
27
27
|
##
|
@@ -42,14 +42,14 @@ class SlackHandlerService(Handler, Looper[str]):
|
|
42
42
|
url: str,
|
43
43
|
auto_start: bool = False,
|
44
44
|
empty_upon_exit: bool = True,
|
45
|
-
freq:
|
46
|
-
backoff:
|
45
|
+
freq: TimeDelta = SECOND,
|
46
|
+
backoff: TimeDelta = SECOND,
|
47
47
|
logger: str | None = None,
|
48
|
-
timeout:
|
48
|
+
timeout: TimeDelta | None = None,
|
49
49
|
_debug: bool = False,
|
50
50
|
level: int = NOTSET,
|
51
51
|
sender: Callable[[str, str], Coroutine1[None]] = _send_adapter,
|
52
|
-
send_timeout:
|
52
|
+
send_timeout: TimeDelta = SECOND,
|
53
53
|
) -> None:
|
54
54
|
Looper.__init__( # Looper first
|
55
55
|
self,
|
@@ -81,7 +81,7 @@ class SlackHandlerService(Handler, Looper[str]):
|
|
81
81
|
if self.empty():
|
82
82
|
return
|
83
83
|
text = "\n".join(self.get_all_nowait())
|
84
|
-
async with
|
84
|
+
async with timeout_td(self.send_timeout):
|
85
85
|
await self.sender(self.url, text)
|
86
86
|
|
87
87
|
@override
|
@@ -90,10 +90,10 @@ class SlackHandlerService(Handler, Looper[str]):
|
|
90
90
|
*,
|
91
91
|
auto_start: bool | Sentinel = sentinel,
|
92
92
|
empty_upon_exit: bool | Sentinel = sentinel,
|
93
|
-
freq:
|
94
|
-
backoff:
|
93
|
+
freq: TimeDelta | Sentinel = sentinel,
|
94
|
+
backoff: TimeDelta | Sentinel = sentinel,
|
95
95
|
logger: str | None | Sentinel = sentinel,
|
96
|
-
timeout:
|
96
|
+
timeout: TimeDelta | None | Sentinel = sentinel,
|
97
97
|
_debug: bool | Sentinel = sentinel,
|
98
98
|
**kwargs: Any,
|
99
99
|
) -> Self:
|
@@ -115,11 +115,11 @@ class SlackHandlerService(Handler, Looper[str]):
|
|
115
115
|
|
116
116
|
|
117
117
|
async def send_to_slack(
|
118
|
-
url: str, text: str, /, *, timeout:
|
118
|
+
url: str, text: str, /, *, timeout: TimeDelta = _TIMEOUT
|
119
119
|
) -> None:
|
120
120
|
"""Send a message via Slack."""
|
121
121
|
client = _get_client(url, timeout=timeout)
|
122
|
-
async with
|
122
|
+
async with timeout_td(timeout):
|
123
123
|
response = await client.send(text=text)
|
124
124
|
if response.status_code != HTTPStatus.OK: # pragma: no cover
|
125
125
|
raise SendToSlackError(text=text, response=response)
|
@@ -138,10 +138,9 @@ class SendToSlackError(Exception):
|
|
138
138
|
|
139
139
|
|
140
140
|
@cache
|
141
|
-
def _get_client(url: str, /, *, timeout:
|
141
|
+
def _get_client(url: str, /, *, timeout: TimeDelta = _TIMEOUT) -> AsyncWebhookClient:
|
142
142
|
"""Get the Slack client."""
|
143
|
-
|
144
|
-
return AsyncWebhookClient(url, timeout=timeout_use)
|
143
|
+
return AsyncWebhookClient(url, timeout=round(timeout.in_seconds()))
|
145
144
|
|
146
145
|
|
147
146
|
__all__ = ["SendToSlackError", "SlackHandlerService", "send_to_slack"]
|
utilities/sqlalchemy.py
CHANGED
@@ -18,7 +18,16 @@ from itertools import chain
|
|
18
18
|
from math import floor
|
19
19
|
from operator import ge, le
|
20
20
|
from re import search
|
21
|
-
from typing import
|
21
|
+
from typing import (
|
22
|
+
TYPE_CHECKING,
|
23
|
+
Any,
|
24
|
+
Literal,
|
25
|
+
TypeGuard,
|
26
|
+
TypeVar,
|
27
|
+
assert_never,
|
28
|
+
cast,
|
29
|
+
override,
|
30
|
+
)
|
22
31
|
|
23
32
|
from sqlalchemy import (
|
24
33
|
URL,
|
@@ -57,9 +66,8 @@ from sqlalchemy.orm import (
|
|
57
66
|
from sqlalchemy.orm.exc import UnmappedClassError
|
58
67
|
from sqlalchemy.pool import NullPool, Pool
|
59
68
|
|
60
|
-
from utilities.asyncio import Looper,
|
69
|
+
from utilities.asyncio import Looper, timeout_td
|
61
70
|
from utilities.contextlib import suppress_super_object_attribute_error
|
62
|
-
from utilities.datetime import SECOND
|
63
71
|
from utilities.functions import (
|
64
72
|
ensure_str,
|
65
73
|
get_class_name,
|
@@ -82,13 +90,11 @@ from utilities.iterables import (
|
|
82
90
|
)
|
83
91
|
from utilities.reprlib import get_repr
|
84
92
|
from utilities.text import snake_case
|
85
|
-
from utilities.types import
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
TupleOrStrMapping,
|
91
|
-
)
|
93
|
+
from utilities.types import MaybeIterable, MaybeType, StrMapping, TupleOrStrMapping
|
94
|
+
from utilities.whenever2 import SECOND
|
95
|
+
|
96
|
+
if TYPE_CHECKING:
|
97
|
+
from whenever import TimeDelta
|
92
98
|
|
93
99
|
_T = TypeVar("_T")
|
94
100
|
type _EngineOrConnectionOrAsync = Engine | Connection | AsyncEngine | AsyncConnection
|
@@ -105,7 +111,7 @@ async def check_engine(
|
|
105
111
|
engine: AsyncEngine,
|
106
112
|
/,
|
107
113
|
*,
|
108
|
-
timeout:
|
114
|
+
timeout: TimeDelta | None = None,
|
109
115
|
error: type[Exception] = TimeoutError,
|
110
116
|
num_tables: int | tuple[int, float] | None = None,
|
111
117
|
) -> None:
|
@@ -229,7 +235,7 @@ async def ensure_tables_created(
|
|
229
235
|
engine: AsyncEngine,
|
230
236
|
/,
|
231
237
|
*tables_or_orms: TableOrORMInstOrClass,
|
232
|
-
timeout:
|
238
|
+
timeout: TimeDelta | None = None,
|
233
239
|
error: type[Exception] = TimeoutError,
|
234
240
|
) -> None:
|
235
241
|
"""Ensure a table/set of tables is/are created."""
|
@@ -258,7 +264,7 @@ async def ensure_tables_created(
|
|
258
264
|
async def ensure_tables_dropped(
|
259
265
|
engine: AsyncEngine,
|
260
266
|
*tables_or_orms: TableOrORMInstOrClass,
|
261
|
-
timeout:
|
267
|
+
timeout: TimeDelta | None = None,
|
262
268
|
error: type[Exception] = TimeoutError,
|
263
269
|
) -> None:
|
264
270
|
"""Ensure a table/set of tables is/are dropped."""
|
@@ -384,9 +390,9 @@ async def insert_items(
|
|
384
390
|
snake: bool = False,
|
385
391
|
chunk_size_frac: float = CHUNK_SIZE_FRAC,
|
386
392
|
assume_tables_exist: bool = False,
|
387
|
-
timeout_create:
|
393
|
+
timeout_create: TimeDelta | None = None,
|
388
394
|
error_create: type[Exception] = TimeoutError,
|
389
|
-
timeout_insert:
|
395
|
+
timeout_insert: TimeDelta | None = None,
|
390
396
|
error_insert: type[Exception] = TimeoutError,
|
391
397
|
) -> None:
|
392
398
|
"""Insert a set of items into a database.
|
@@ -485,9 +491,9 @@ async def migrate_data(
|
|
485
491
|
table_or_orm_to: TableOrORMInstOrClass | None = None,
|
486
492
|
chunk_size_frac: float = CHUNK_SIZE_FRAC,
|
487
493
|
assume_tables_exist: bool = False,
|
488
|
-
timeout_create:
|
494
|
+
timeout_create: TimeDelta | None = None,
|
489
495
|
error_create: type[Exception] = TimeoutError,
|
490
|
-
timeout_insert:
|
496
|
+
timeout_insert: TimeDelta | None = None,
|
491
497
|
error_insert: type[Exception] = TimeoutError,
|
492
498
|
) -> None:
|
493
499
|
"""Migrate the contents of a table from one database to another."""
|
@@ -615,8 +621,8 @@ class UpsertService(Looper[_InsertItem]):
|
|
615
621
|
"""Service to upsert items to a database."""
|
616
622
|
|
617
623
|
# base
|
618
|
-
freq:
|
619
|
-
backoff:
|
624
|
+
freq: TimeDelta = field(default=SECOND, repr=False)
|
625
|
+
backoff: TimeDelta = field(default=SECOND, repr=False)
|
620
626
|
empty_upon_exit: bool = field(default=True, repr=False)
|
621
627
|
# self
|
622
628
|
engine: AsyncEngine
|
@@ -624,9 +630,9 @@ class UpsertService(Looper[_InsertItem]):
|
|
624
630
|
selected_or_all: _SelectedOrAll = "selected"
|
625
631
|
chunk_size_frac: float = CHUNK_SIZE_FRAC
|
626
632
|
assume_tables_exist: bool = False
|
627
|
-
timeout_create:
|
633
|
+
timeout_create: TimeDelta | None = None
|
628
634
|
error_create: type[Exception] = TimeoutError
|
629
|
-
timeout_insert:
|
635
|
+
timeout_insert: TimeDelta | None = None
|
630
636
|
error_insert: type[Exception] = TimeoutError
|
631
637
|
|
632
638
|
@override
|
@@ -651,11 +657,11 @@ class UpsertServiceMixin:
|
|
651
657
|
"""Mix-in for the upsert service."""
|
652
658
|
|
653
659
|
# base - looper
|
654
|
-
upsert_service_freq:
|
655
|
-
upsert_service_backoff:
|
660
|
+
upsert_service_freq: TimeDelta = field(default=SECOND, repr=False)
|
661
|
+
upsert_service_backoff: TimeDelta = field(default=SECOND, repr=False)
|
656
662
|
upsert_service_empty_upon_exit: bool = field(default=False, repr=False)
|
657
663
|
upsert_service_logger: str | None = field(default=None, repr=False)
|
658
|
-
upsert_service_timeout:
|
664
|
+
upsert_service_timeout: TimeDelta | None = field(default=None, repr=False)
|
659
665
|
upsert_service_debug: bool = field(default=False, repr=False)
|
660
666
|
# base - upsert service
|
661
667
|
upsert_service_database: AsyncEngine
|
@@ -663,9 +669,9 @@ class UpsertServiceMixin:
|
|
663
669
|
upsert_service_selected_or_all: _SelectedOrAll = "selected"
|
664
670
|
upsert_service_chunk_size_frac: float = CHUNK_SIZE_FRAC
|
665
671
|
upsert_service_assume_tables_exist: bool = False
|
666
|
-
upsert_service_timeout_create:
|
672
|
+
upsert_service_timeout_create: TimeDelta | None = None
|
667
673
|
upsert_service_error_create: type[Exception] = TimeoutError
|
668
|
-
upsert_service_timeout_insert:
|
674
|
+
upsert_service_timeout_insert: TimeDelta | None = None
|
669
675
|
upsert_service_error_insert: type[Exception] = TimeoutError
|
670
676
|
# self
|
671
677
|
_upsert_service: UpsertService = field(init=False, repr=False)
|
@@ -713,9 +719,9 @@ async def upsert_items(
|
|
713
719
|
selected_or_all: _SelectedOrAll = "selected",
|
714
720
|
chunk_size_frac: float = CHUNK_SIZE_FRAC,
|
715
721
|
assume_tables_exist: bool = False,
|
716
|
-
timeout_create:
|
722
|
+
timeout_create: TimeDelta | None = None,
|
717
723
|
error_create: type[Exception] = TimeoutError,
|
718
|
-
timeout_insert:
|
724
|
+
timeout_insert: TimeDelta | None = None,
|
719
725
|
error_insert: type[Exception] = TimeoutError,
|
720
726
|
) -> None:
|
721
727
|
"""Upsert a set of items into a database.
|
@@ -835,11 +841,11 @@ async def yield_connection(
|
|
835
841
|
engine: AsyncEngine,
|
836
842
|
/,
|
837
843
|
*,
|
838
|
-
timeout:
|
844
|
+
timeout: TimeDelta | None = None,
|
839
845
|
error: MaybeType[BaseException] = TimeoutError,
|
840
846
|
) -> AsyncIterator[AsyncConnection]:
|
841
847
|
"""Yield an async connection."""
|
842
|
-
async with
|
848
|
+
async with timeout_td(timeout, error=error), engine.begin() as conn:
|
843
849
|
yield conn
|
844
850
|
|
845
851
|
|
utilities/sqlalchemy_polars.py
CHANGED
@@ -26,7 +26,7 @@ from polars import (
|
|
26
26
|
from sqlalchemy import Column, Select, select
|
27
27
|
from sqlalchemy.exc import DuplicateColumnError
|
28
28
|
|
29
|
-
from utilities.asyncio import
|
29
|
+
from utilities.asyncio import timeout_td
|
30
30
|
from utilities.functions import identity
|
31
31
|
from utilities.iterables import (
|
32
32
|
CheckDuplicatesError,
|
@@ -63,11 +63,8 @@ if TYPE_CHECKING:
|
|
63
63
|
from sqlalchemy.ext.asyncio import AsyncEngine
|
64
64
|
from sqlalchemy.sql import ColumnCollection
|
65
65
|
from sqlalchemy.sql.base import ReadOnlyColumnCollection
|
66
|
-
from
|
67
|
-
from tenacity.stop import StopBaseT
|
68
|
-
from tenacity.wait import WaitBaseT
|
66
|
+
from whenever import TimeDelta
|
69
67
|
|
70
|
-
import utilities.types
|
71
68
|
from utilities.types import MaybeType, TimeZoneLike
|
72
69
|
|
73
70
|
|
@@ -81,9 +78,9 @@ async def insert_dataframe(
|
|
81
78
|
chunk_size_frac: float = CHUNK_SIZE_FRAC,
|
82
79
|
assume_tables_exist: bool = False,
|
83
80
|
upsert: Literal["selected", "all"] | None = None,
|
84
|
-
timeout_create:
|
81
|
+
timeout_create: TimeDelta | None = None,
|
85
82
|
error_create: type[Exception] = TimeoutError,
|
86
|
-
timeout_insert:
|
83
|
+
timeout_insert: TimeDelta | None = None,
|
87
84
|
error_insert: type[Exception] = TimeoutError,
|
88
85
|
) -> None:
|
89
86
|
"""Insert/upsert a DataFrame into a database."""
|
@@ -231,10 +228,7 @@ async def select_to_dataframe(
|
|
231
228
|
in_clauses: tuple[Column[Any], Iterable[Any]] | None = None,
|
232
229
|
in_clauses_chunk_size: int | None = None,
|
233
230
|
chunk_size_frac: float = CHUNK_SIZE_FRAC,
|
234
|
-
|
235
|
-
wait: WaitBaseT | None = None,
|
236
|
-
retry: RetryBaseT | None = None,
|
237
|
-
timeout: utilities.types.Duration | None = None,
|
231
|
+
timeout: TimeDelta | None = None,
|
238
232
|
**kwargs: Any,
|
239
233
|
) -> DataFrame: ...
|
240
234
|
@overload
|
@@ -249,10 +243,7 @@ async def select_to_dataframe(
|
|
249
243
|
in_clauses: None = None,
|
250
244
|
in_clauses_chunk_size: int | None = None,
|
251
245
|
chunk_size_frac: float = CHUNK_SIZE_FRAC,
|
252
|
-
|
253
|
-
wait: WaitBaseT | None = None,
|
254
|
-
retry: RetryBaseT | None = None,
|
255
|
-
timeout: utilities.types.Duration | None = None,
|
246
|
+
timeout: TimeDelta | None = None,
|
256
247
|
**kwargs: Any,
|
257
248
|
) -> Iterable[DataFrame]: ...
|
258
249
|
@overload
|
@@ -267,10 +258,7 @@ async def select_to_dataframe(
|
|
267
258
|
in_clauses: tuple[Column[Any], Iterable[Any]],
|
268
259
|
in_clauses_chunk_size: int | None = None,
|
269
260
|
chunk_size_frac: float = CHUNK_SIZE_FRAC,
|
270
|
-
|
271
|
-
wait: WaitBaseT | None = None,
|
272
|
-
retry: RetryBaseT | None = None,
|
273
|
-
timeout: utilities.types.Duration | None = None,
|
261
|
+
timeout: TimeDelta | None = None,
|
274
262
|
**kwargs: Any,
|
275
263
|
) -> AsyncIterable[DataFrame]: ...
|
276
264
|
@overload
|
@@ -285,10 +273,7 @@ async def select_to_dataframe(
|
|
285
273
|
in_clauses: tuple[Column[Any], Iterable[Any]] | None = None,
|
286
274
|
in_clauses_chunk_size: int | None = None,
|
287
275
|
chunk_size_frac: float = CHUNK_SIZE_FRAC,
|
288
|
-
|
289
|
-
wait: WaitBaseT | None = None,
|
290
|
-
retry: RetryBaseT | None = None,
|
291
|
-
timeout: utilities.types.Duration | None = None,
|
276
|
+
timeout: TimeDelta | None = None,
|
292
277
|
**kwargs: Any,
|
293
278
|
) -> DataFrame | Iterable[DataFrame] | AsyncIterable[DataFrame]: ...
|
294
279
|
async def select_to_dataframe(
|
@@ -302,7 +287,7 @@ async def select_to_dataframe(
|
|
302
287
|
in_clauses: tuple[Column[Any], Iterable[Any]] | None = None,
|
303
288
|
in_clauses_chunk_size: int | None = None,
|
304
289
|
chunk_size_frac: float = CHUNK_SIZE_FRAC,
|
305
|
-
timeout:
|
290
|
+
timeout: TimeDelta | None = None,
|
306
291
|
error: MaybeType[BaseException] = TimeoutError,
|
307
292
|
**kwargs: Any,
|
308
293
|
) -> DataFrame | Iterable[DataFrame] | AsyncIterable[DataFrame]:
|
@@ -311,7 +296,7 @@ async def select_to_dataframe(
|
|
311
296
|
sel = _select_to_dataframe_apply_snake(sel)
|
312
297
|
schema = _select_to_dataframe_map_select_to_df_schema(sel, time_zone=time_zone)
|
313
298
|
if in_clauses is None:
|
314
|
-
async with
|
299
|
+
async with timeout_td(timeout, error=error):
|
315
300
|
return read_database(
|
316
301
|
sel,
|
317
302
|
cast("Any", engine),
|
@@ -328,7 +313,7 @@ async def select_to_dataframe(
|
|
328
313
|
chunk_size_frac=chunk_size_frac,
|
329
314
|
)
|
330
315
|
if batch_size is None:
|
331
|
-
async with
|
316
|
+
async with timeout_td(timeout, error=error):
|
332
317
|
dfs = [
|
333
318
|
await select_to_dataframe(
|
334
319
|
sel,
|
@@ -349,7 +334,7 @@ async def select_to_dataframe(
|
|
349
334
|
return DataFrame(schema=schema)
|
350
335
|
|
351
336
|
async def yield_dfs() -> AsyncIterator[DataFrame]:
|
352
|
-
async with
|
337
|
+
async with timeout_td(timeout, error=error):
|
353
338
|
for sel_i in sels:
|
354
339
|
for df in await select_to_dataframe(
|
355
340
|
sel_i,
|
utilities/tenacity.py
DELETED
@@ -1,145 +0,0 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
|
3
|
-
from contextlib import AbstractAsyncContextManager, asynccontextmanager
|
4
|
-
from typing import TYPE_CHECKING, Any, override
|
5
|
-
|
6
|
-
from tenacity import (
|
7
|
-
AsyncRetrying,
|
8
|
-
AttemptManager,
|
9
|
-
RetryCallState,
|
10
|
-
RetryError,
|
11
|
-
after_nothing,
|
12
|
-
before_nothing,
|
13
|
-
retry_if_exception_type,
|
14
|
-
stop_never,
|
15
|
-
wait_none,
|
16
|
-
)
|
17
|
-
from tenacity import wait_exponential_jitter as _wait_exponential_jitter
|
18
|
-
from tenacity._utils import MAX_WAIT
|
19
|
-
from tenacity.asyncio import _portable_async_sleep
|
20
|
-
|
21
|
-
from utilities.asyncio import timeout_dur
|
22
|
-
from utilities.contextlib import NoOpContextManager
|
23
|
-
from utilities.datetime import datetime_duration_to_float
|
24
|
-
|
25
|
-
if TYPE_CHECKING:
|
26
|
-
from collections.abc import AsyncIterator, Callable
|
27
|
-
|
28
|
-
from tenacity.retry import RetryBaseT
|
29
|
-
from tenacity.stop import StopBaseT
|
30
|
-
from tenacity.wait import WaitBaseT
|
31
|
-
|
32
|
-
from utilities.types import Duration, MaybeAwaitable
|
33
|
-
|
34
|
-
|
35
|
-
type MaybeAttemptManager = NoOpContextManager | AttemptManager
|
36
|
-
type MaybeAttemptContextManager = AbstractAsyncContextManager[MaybeAttemptManager]
|
37
|
-
|
38
|
-
|
39
|
-
class wait_exponential_jitter(_wait_exponential_jitter): # noqa: N801
|
40
|
-
"""Subclass of `wait_exponential_jitter` accepting durations."""
|
41
|
-
|
42
|
-
@override
|
43
|
-
def __init__(
|
44
|
-
self,
|
45
|
-
initial: Duration = 1,
|
46
|
-
max: Duration = MAX_WAIT,
|
47
|
-
exp_base: float = 2,
|
48
|
-
jitter: Duration = 1,
|
49
|
-
) -> None:
|
50
|
-
super().__init__(
|
51
|
-
initial=datetime_duration_to_float(initial),
|
52
|
-
max=datetime_duration_to_float(max),
|
53
|
-
exp_base=exp_base,
|
54
|
-
jitter=datetime_duration_to_float(jitter),
|
55
|
-
)
|
56
|
-
|
57
|
-
|
58
|
-
async def yield_attempts(
|
59
|
-
*,
|
60
|
-
sleep: Callable[[int | float], MaybeAwaitable[None]] | None = None,
|
61
|
-
stop: StopBaseT | None = None,
|
62
|
-
wait: WaitBaseT | None = None,
|
63
|
-
retry: RetryBaseT | None = None,
|
64
|
-
before: Callable[[RetryCallState], MaybeAwaitable[None]] | None = None,
|
65
|
-
after: Callable[[RetryCallState], MaybeAwaitable[None]] | None = None,
|
66
|
-
before_sleep: Callable[[RetryCallState], MaybeAwaitable[None]] | None = None,
|
67
|
-
reraise: bool | None = None,
|
68
|
-
retry_error_cls: type[RetryError] | None = None,
|
69
|
-
retry_error_callback: Callable[[RetryCallState], MaybeAwaitable[Any]] | None = None,
|
70
|
-
) -> AsyncIterator[MaybeAttemptManager]:
|
71
|
-
"""Yield the attempts."""
|
72
|
-
if (
|
73
|
-
(sleep is None)
|
74
|
-
and (stop is None)
|
75
|
-
and (wait is None)
|
76
|
-
and (retry is None)
|
77
|
-
and (before is None)
|
78
|
-
and (after is None)
|
79
|
-
and (before_sleep is None)
|
80
|
-
and (reraise is None)
|
81
|
-
and (retry_error_cls is None)
|
82
|
-
):
|
83
|
-
yield NoOpContextManager()
|
84
|
-
else:
|
85
|
-
retrying = AsyncRetrying(
|
86
|
-
sleep=_portable_async_sleep if sleep is None else sleep,
|
87
|
-
stop=stop_never if stop is None else stop,
|
88
|
-
wait=wait_none() if wait is None else wait,
|
89
|
-
retry=retry_if_exception_type() if retry is None else retry,
|
90
|
-
before=before_nothing if before is None else before,
|
91
|
-
after=after_nothing if after is None else after,
|
92
|
-
before_sleep=None if before_sleep is None else before_sleep,
|
93
|
-
reraise=False if reraise is None else reraise,
|
94
|
-
retry_error_cls=RetryError if retry_error_cls is None else retry_error_cls,
|
95
|
-
retry_error_callback=retry_error_callback,
|
96
|
-
)
|
97
|
-
async for attempt in retrying:
|
98
|
-
yield attempt
|
99
|
-
|
100
|
-
|
101
|
-
async def yield_timeout_attempts(
|
102
|
-
*,
|
103
|
-
sleep: Callable[[int | float], MaybeAwaitable[None]] | None = None,
|
104
|
-
stop: StopBaseT | None = None,
|
105
|
-
wait: WaitBaseT | None = None,
|
106
|
-
retry: RetryBaseT | None = None,
|
107
|
-
before: Callable[[RetryCallState], MaybeAwaitable[None]] | None = None,
|
108
|
-
after: Callable[[RetryCallState], MaybeAwaitable[None]] | None = None,
|
109
|
-
before_sleep: Callable[[RetryCallState], MaybeAwaitable[None]] | None = None,
|
110
|
-
reraise: bool | None = None,
|
111
|
-
retry_error_cls: type[RetryError] | None = None,
|
112
|
-
retry_error_callback: Callable[[RetryCallState], MaybeAwaitable[Any]] | None = None,
|
113
|
-
timeout: Duration | None = None,
|
114
|
-
) -> AsyncIterator[MaybeAttemptContextManager]:
|
115
|
-
"""Yield the attempts, with timeout."""
|
116
|
-
async for attempt in yield_attempts(
|
117
|
-
sleep=sleep,
|
118
|
-
stop=stop,
|
119
|
-
wait=wait,
|
120
|
-
retry=retry,
|
121
|
-
before=before,
|
122
|
-
after=after,
|
123
|
-
before_sleep=before_sleep,
|
124
|
-
reraise=reraise,
|
125
|
-
retry_error_cls=retry_error_cls,
|
126
|
-
retry_error_callback=retry_error_callback,
|
127
|
-
):
|
128
|
-
|
129
|
-
@asynccontextmanager
|
130
|
-
async def new(
|
131
|
-
attempt: MaybeAttemptManager, /
|
132
|
-
) -> AsyncIterator[MaybeAttemptManager]:
|
133
|
-
with attempt:
|
134
|
-
async with timeout_dur(duration=timeout):
|
135
|
-
yield attempt
|
136
|
-
|
137
|
-
yield new(attempt)
|
138
|
-
|
139
|
-
|
140
|
-
__all__ = [
|
141
|
-
"MaybeAttemptManager",
|
142
|
-
"wait_exponential_jitter",
|
143
|
-
"yield_attempts",
|
144
|
-
"yield_timeout_attempts",
|
145
|
-
]
|
File without changes
|
File without changes
|