Total Complexity | 4 |
Total Lines | 45 |
Duplicated Lines | 0 % |
Coverage | 100% |
Changes | 0 |
1 | """Retry utilities module.""" |
||
2 | 1 | import logging |
|
3 | 1 | from functools import wraps |
|
4 | 1 | from typing import Callable |
|
5 | |||
6 | 1 | from tenacity import retry |
|
7 | |||
8 | 1 | LOG = logging.getLogger(__name__) |
|
9 | |||
10 | |||
11 | 1 | def before_sleep(state) -> None: |
|
12 | """Before sleep function for tenacity to also logs args and kwargs.""" |
||
13 | 1 | LOG.warning( |
|
14 | f"Retry #{state.attempt_number} for {state.fn.__name__}, " |
||
15 | f"args: {state.args}, kwargs: {state.kwargs}, " |
||
16 | f"seconds since start: {state.seconds_since_start:.2f}", |
||
17 | ) |
||
18 | |||
19 | |||
20 | 1 | def retries(func: Callable, **tenacity_kwargs) -> Callable: |
|
21 | """Retries decorator.""" |
||
22 | 1 | @retry(**tenacity_kwargs) |
|
23 | 1 | @wraps(func) |
|
24 | 1 | def decorated(*args, **kwargs): |
|
25 | 1 | return func(*args, **kwargs) |
|
26 | |||
27 | 1 | return decorated |
|
28 | |||
29 | |||
30 | 1 | def for_all_methods(decorator: Callable, **kwargs) -> Callable: |
|
31 | """Decorator for all methods.""" |
||
32 | |||
33 | 1 | def decorated(cls): |
|
34 | 1 | for attr in [ |
|
35 | name |
||
36 | for name in dir(cls) |
||
37 | if callable(getattr(cls, name)) |
||
38 | and not name.startswith("_") |
||
39 | and not hasattr(getattr(cls, name), "__wrapped__") |
||
40 | ]: |
||
41 | 1 | setattr(cls, attr, decorator(getattr(cls, attr), **kwargs)) |
|
42 | 1 | return cls |
|
43 | |||
44 | return decorated |
||
45 |