Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pip/_internal/utils/retry.py: 52%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

23 statements  

1from __future__ import annotations 

2 

3import functools 

4from collections.abc import Callable 

5from time import perf_counter, sleep 

6from typing import TYPE_CHECKING, TypeVar 

7 

8if TYPE_CHECKING: 

9 from typing_extensions import ParamSpec 

10 

11 T = TypeVar("T") 

12 P = ParamSpec("P") 

13 

14 

15def retry( 

16 wait: float, stop_after_delay: float 

17) -> Callable[[Callable[P, T]], Callable[P, T]]: 

18 """Decorator to automatically retry a function on error. 

19 

20 If the function raises, the function is recalled with the same arguments 

21 until it returns or the time limit is reached. When the time limit is 

22 surpassed, the last exception raised is reraised. 

23 

24 :param wait: The time to wait after an error before retrying, in seconds. 

25 :param stop_after_delay: The time limit after which retries will cease, 

26 in seconds. 

27 """ 

28 

29 def wrapper(func: Callable[P, T]) -> Callable[P, T]: 

30 

31 @functools.wraps(func) 

32 def retry_wrapped(*args: P.args, **kwargs: P.kwargs) -> T: 

33 # The performance counter is monotonic on all platforms we care 

34 # about and has much better resolution than time.monotonic(). 

35 start_time = perf_counter() 

36 while True: 

37 try: 

38 return func(*args, **kwargs) 

39 except Exception: 

40 if perf_counter() - start_time > stop_after_delay: 

41 raise 

42 sleep(wait) 

43 

44 return retry_wrapped 

45 

46 return wrapper