@@ -31,16 +31,17 @@ <h1 class="title">Module <code>pedantic.decorators.fn_deco_retry</code></h1>
3131from datetime import timedelta
3232from functools import wraps
3333from logging import Logger
34- from typing import Callable, TypeVar, TypeVarTuple, Any
34+ from typing import Callable, TypeVar, Any, ParamSpec
3535
3636C = TypeVar('C', bound=Callable)
37- Ts = TypeVarTuple('Ts')
37+ P = ParamSpec('P')
38+ R = TypeVar('R')
3839
3940
4041def retry(
4142 *,
4243 attempts: int,
43- exceptions: type[Exception] | tuple[type[Exception], ...] = None ,
44+ exceptions: type[Exception] | tuple[type[Exception], ...] = Exception ,
4445 sleep_time: timedelta = timedelta(seconds=0),
4546 logger: Logger = None,
4647) -> Callable[[C], C]:
@@ -61,28 +62,46 @@ <h1 class="title">Module <code>pedantic.decorators.fn_deco_retry</code></h1>
6162 >>> foo()
6263 """
6364
64- if exceptions is None:
65- exceptions = Exception
65+ def decorator(func: C) -> C:
66+ @wraps(func)
67+ def wrapper(*args, **kwargs) -> Any:
68+ return retry_func(
69+ func,
70+ *args,
71+ attempts=attempts,
72+ exceptions=exceptions,
73+ sleep_time=sleep_time,
74+ logger=logger,
75+ **kwargs,
76+ )
77+ return wrapper
78+ return decorator
79+
80+
81+ def retry_func(
82+ func: Callable[P, R],
83+ *args: P.args,
84+ attempts: int,
85+ exceptions: type[Exception] | tuple[type[Exception], ...] = Exception,
86+ sleep_time: timedelta = timedelta(seconds=0),
87+ logger: Logger = None,
88+ **kwargs: P.kwargs,
89+ ) -> R:
90+ attempt = 1
6691
6792 if logger is None:
6893 logger = logging.getLogger()
6994
70- def decorator(func: C) -> C:
71- @wraps(func)
72- def wrapper(*args, **kwargs) -> Any:
73- attempt = 1
74-
75- while attempt < attempts:
76- try:
77- return func(*args, **kwargs)
78- except exceptions:
79- logger.warning(f'Exception thrown when attempting to run {func.__name__}, '
80- f'attempt {attempt} of {attempts}')
81- attempt += 1
82- time.sleep(sleep_time.total_seconds())
95+ while attempt < attempts:
96+ try:
8397 return func(*args, **kwargs)
84- return wrapper
85- return decorator</ code > </ pre >
98+ except exceptions:
99+ logger.warning(f'Exception thrown when attempting to run {func.__name__}, '
100+ f'attempt {attempt} of {attempts}')
101+ attempt += 1
102+ time.sleep(sleep_time.total_seconds())
103+
104+ return func(*args, **kwargs)</ code > </ pre >
86105</ details >
87106</ section >
88107< section >
@@ -93,7 +112,7 @@ <h1 class="title">Module <code>pedantic.decorators.fn_deco_retry</code></h1>
93112< h2 class ="section-title " id ="header-functions "> Functions</ h2 >
94113< dl >
95114< dt id ="pedantic.decorators.fn_deco_retry.retry "> < code class ="name flex ">
96- < span > def < span class ="ident "> retry</ span > </ span > (< span > *, attempts: int, exceptions: type[Exception] | tuple[type[Exception], ...] = None , sleep_time: datetime.timedelta = datetime.timedelta(0), logger: logging.Logger = None) ‑> Callable[[~C], ~C]</ span >
115+ < span > def < span class ="ident "> retry</ span > </ span > (< span > *, attempts: int, exceptions: type[Exception] | tuple[type[Exception], ...] = builtins.Exception , sleep_time: datetime.timedelta = datetime.timedelta(0), logger: logging.Logger = None) ‑> Callable[[~C], ~C]</ span >
97116</ code > </ dt >
98117< dd >
99118< div class ="desc "> < p > Retries the wrapped function/method < code > attempts</ code > times if the exceptions listed
@@ -116,7 +135,7 @@ <h2 id="example">Example</h2>
116135< pre > < code class ="python "> def retry(
117136 *,
118137 attempts: int,
119- exceptions: type[Exception] | tuple[type[Exception], ...] = None ,
138+ exceptions: type[Exception] | tuple[type[Exception], ...] = Exception ,
120139 sleep_time: timedelta = timedelta(seconds=0),
121140 logger: Logger = None,
122141) -> Callable[[C], C]:
@@ -137,30 +156,57 @@ <h2 id="example">Example</h2>
137156 >>> foo()
138157 """
139158
140- if exceptions is None:
141- exceptions = Exception
142-
143- if logger is None:
144- logger = logging.getLogger()
145-
146159 def decorator(func: C) -> C:
147160 @wraps(func)
148161 def wrapper(*args, **kwargs) -> Any:
149- attempt = 1
150-
151- while attempt < attempts:
152- try:
153- return func(*args, **kwargs)
154- except exceptions:
155- logger.warning(f'Exception thrown when attempting to run {func.__name__}, '
156- f'attempt {attempt} of {attempts}')
157- attempt += 1
158- time.sleep(sleep_time.total_seconds())
159- return func(*args, **kwargs)
162+ return retry_func(
163+ func,
164+ *args,
165+ attempts=attempts,
166+ exceptions=exceptions,
167+ sleep_time=sleep_time,
168+ logger=logger,
169+ **kwargs,
170+ )
160171 return wrapper
161172 return decorator</ code > </ pre >
162173</ details >
163174</ dd >
175+ < dt id ="pedantic.decorators.fn_deco_retry.retry_func "> < code class ="name flex ">
176+ < span > def < span class ="ident "> retry_func</ span > </ span > (< span > func: Callable[~P, ~R], *args: P.args, attempts: int, exceptions: type[Exception] | tuple[type[Exception], ...] = builtins.Exception, sleep_time: datetime.timedelta = datetime.timedelta(0), logger: logging.Logger = None, **kwargs: P.kwargs) ‑> ~R</ span >
177+ </ code > </ dt >
178+ < dd >
179+ < div class ="desc "> </ div >
180+ < details class ="source ">
181+ < summary >
182+ < span > Expand source code</ span >
183+ </ summary >
184+ < pre > < code class ="python "> def retry_func(
185+ func: Callable[P, R],
186+ *args: P.args,
187+ attempts: int,
188+ exceptions: type[Exception] | tuple[type[Exception], ...] = Exception,
189+ sleep_time: timedelta = timedelta(seconds=0),
190+ logger: Logger = None,
191+ **kwargs: P.kwargs,
192+ ) -> R:
193+ attempt = 1
194+
195+ if logger is None:
196+ logger = logging.getLogger()
197+
198+ while attempt < attempts:
199+ try:
200+ return func(*args, **kwargs)
201+ except exceptions:
202+ logger.warning(f'Exception thrown when attempting to run {func.__name__}, '
203+ f'attempt {attempt} of {attempts}')
204+ attempt += 1
205+ time.sleep(sleep_time.total_seconds())
206+
207+ return func(*args, **kwargs)</ code > </ pre >
208+ </ details >
209+ </ dd >
164210</ dl >
165211</ section >
166212< section >
@@ -180,6 +226,7 @@ <h1>Index</h1>
180226< li > < h3 > < a href ="#header-functions "> Functions</ a > </ h3 >
181227< ul class ="">
182228< li > < code > < a title ="pedantic.decorators.fn_deco_retry.retry " href ="#pedantic.decorators.fn_deco_retry.retry "> retry</ a > </ code > </ li >
229+ < li > < code > < a title ="pedantic.decorators.fn_deco_retry.retry_func " href ="#pedantic.decorators.fn_deco_retry.retry_func "> retry_func</ a > </ code > </ li >
183230</ ul >
184231</ li >
185232</ ul >
0 commit comments