|
3 | 3 | __license__ = "Apache-2.0"
|
4 | 4 |
|
5 | 5 | import time
|
6 |
| -from functools import partial, update_wrapper |
| 6 | +from functools import wraps |
7 | 7 |
|
8 | 8 | import oras.auth
|
9 | 9 | from oras.logger import logger
|
10 | 10 |
|
11 | 11 |
|
12 |
| -class Decorator: |
13 |
| - """ |
14 |
| - Shared parent decorator class |
15 |
| - """ |
16 |
| - |
17 |
| - def __init__(self, func): |
18 |
| - update_wrapper(self, func) |
19 |
| - self.func = func |
20 |
| - |
21 |
| - def __get__(self, obj, objtype): |
22 |
| - return partial(self.__call__, obj) |
23 |
| - |
24 |
| - |
25 |
| -class ensure_container(Decorator): |
| 12 | +def ensure_container(func): |
26 | 13 | """
|
27 | 14 | Ensure the first argument is a container, and not a string.
|
28 | 15 | """
|
29 | 16 |
|
30 |
| - def __call__(self, cls, *args, **kwargs): |
| 17 | + @wraps(func) |
| 18 | + def wrapper(cls, *args, **kwargs): |
31 | 19 | if "container" in kwargs:
|
32 | 20 | kwargs["container"] = cls.get_container(kwargs["container"])
|
33 | 21 | elif args:
|
34 | 22 | container = cls.get_container(args[0])
|
35 | 23 | args = (container, *args[1:])
|
36 |
| - return self.func(cls, *args, **kwargs) |
37 |
| - |
38 |
| - |
39 |
| -class classretry(Decorator): |
40 |
| - """ |
41 |
| - Retry a function that is part of a class |
42 |
| - """ |
43 |
| - |
44 |
| - def __init__(self, func, attempts=5, timeout=2): |
45 |
| - super().__init__(func) |
46 |
| - self.attempts = attempts |
47 |
| - self.timeout = timeout |
| 24 | + return func(cls, *args, **kwargs) |
48 | 25 |
|
49 |
| - def __call__(self, cls, *args, **kwargs): |
50 |
| - attempt = 0 |
51 |
| - attempts = self.attempts |
52 |
| - timeout = self.timeout |
53 |
| - while attempt < attempts: |
54 |
| - try: |
55 |
| - return self.func(cls, *args, **kwargs) |
56 |
| - except oras.auth.AuthenticationException as e: |
57 |
| - raise e |
58 |
| - except Exception as e: |
59 |
| - sleep = timeout + 3**attempt |
60 |
| - logger.info(f"Retrying in {sleep} seconds - error: {e}") |
61 |
| - time.sleep(sleep) |
62 |
| - attempt += 1 |
63 |
| - return self.func(cls, *args, **kwargs) |
| 26 | + return wrapper |
64 | 27 |
|
65 | 28 |
|
66 |
| -def retry(attempts, timeout=2): |
| 29 | +def retry(attempts=5, timeout=2): |
67 | 30 | """
|
68 | 31 | A simple retry decorator
|
69 | 32 | """
|
70 | 33 |
|
71 | 34 | def decorator(func):
|
| 35 | + @wraps(func) |
72 | 36 | def inner(*args, **kwargs):
|
73 | 37 | attempt = 0
|
74 | 38 | while attempt < attempts:
|
75 | 39 | try:
|
76 |
| - return func(*args, **kwargs) |
| 40 | + res = func(*args, **kwargs) |
| 41 | + if res.status_code == 500: |
| 42 | + try: |
| 43 | + msg = res.json() |
| 44 | + for error in msg.get("errors", []): |
| 45 | + if isinstance(error, dict) and "message" in error: |
| 46 | + logger.error(error["message"]) |
| 47 | + except Exception: |
| 48 | + pass |
| 49 | + raise ValueError(f"Issue with {res.request.url}: {res.reason}") |
| 50 | + return res |
77 | 51 | except oras.auth.AuthenticationException as e:
|
78 | 52 | raise e
|
79 | 53 | except Exception as e:
|
|
0 commit comments