1111from forklet .infrastructure .logger import logger
1212
1313
14-
15-
1614####
1715## DOWNLOAD ERROR MODEL
1816#####
1917class DownloadError (Exception ):
2018 """Base exception for download-related errors."""
21-
22- def __init__ (
23- self ,
24- message : str ,
25- original_error : Optional [Exception ] = None
26- ):
19+
20+ def __init__ (self , message : str , original_error : Optional [Exception ] = None ):
2721 super ().__init__ (message )
2822 self .original_error = original_error
2923 self .message = message
30-
24+
3125 def __str__ (self ) -> str :
3226 if self .original_error :
3327 return f"{ self .message } (Original: { self .original_error } )"
@@ -39,6 +33,7 @@ def __str__(self) -> str:
3933#####
4034class RateLimitError (DownloadError ):
4135 """Exception raised when rate limits are exceeded."""
36+
4237 pass
4338
4439
@@ -47,6 +42,7 @@ class RateLimitError(DownloadError):
4742#####
4843class AuthenticationError (DownloadError ):
4944 """Exception raised for authentication failures."""
45+
5046 pass
5147
5248
@@ -55,20 +51,20 @@ class AuthenticationError(DownloadError):
5551#####
5652class RepositoryNotFoundError (DownloadError ):
5753 """Exception raised when repository is not found."""
58- pass
5954
55+ pass
6056
6157
6258####
63- ## RROR HANDLER UTILITIES
59+ ## ERROR HANDLER UTILITIES
6460#####
6561def handle_api_error (func : Callable ) -> Callable :
6662 """
6763 Decorator to handle API errors and convert to appropriate exceptions.
68-
64+
6965 Args:
7066 func: Function to decorate
71-
67+
7268 Returns:
7369 Decorated function
7470 """
@@ -81,8 +77,7 @@ def wrapper(*args, **kwargs) -> Any:
8177
8278 # Cse of GH Exceptions
8379 except GithubException as e :
84-
85- if e .status == 403 and 'rate limit' in str (e ).lower ():
80+ if e .status == 403 and "rate limit" in str (e ).lower ():
8681 raise RateLimitError ("GitHub API rate limit exceeded" , e ) from e
8782
8883 elif e .status == 401 or e .status == 403 :
@@ -96,45 +91,39 @@ def wrapper(*args, **kwargs) -> Any:
9691
9792 # Request Exceptions
9893 except httpx .RequestError as e :
99-
100- if '429' in str (e ) or 'rate limit' in str (e ).lower ():
94+ if "429" in str (e ) or "rate limit" in str (e ).lower ():
10195 raise RateLimitError ("Rate limit exceeded" , e ) from e
10296
10397 else :
10498 raise DownloadError (f"Network error: { e } " , e ) from e
10599
106100 except Exception as e :
107101 raise DownloadError (f"Unexpected error: { e } " , e ) from e
108-
102+
109103 return wrapper
110104
111105
112106def retry_on_error (max_retries : int = 3 ) -> Callable :
113107 """
114108 Decorator to retry operations on specific errors.
115-
109+
116110 Args:
117111 max_retries: Maximum number of retry attempts
118-
112+
119113 Returns:
120- Decorated function
114+ Decorator function
121115 """
122116
123117 def decorator (func : Callable ) -> Callable :
124-
118+
125119 @functools .wraps (func )
126120 def wrapper (* args , ** kwargs ) -> Any :
127121 last_exception = None
128-
122+
129123 for attempt in range (max_retries + 1 ):
130124 try :
131125 return func (* args , ** kwargs )
132- except (
133- RateLimitError ,
134- httpx .RequestError ,
135- ConnectionError
136- ) as e :
137-
126+ except (RateLimitError , httpx .RequestError , ConnectionError ) as e :
138127 last_exception = e
139128 if attempt < max_retries :
140129 logger .warning (
@@ -147,7 +136,9 @@ def wrapper(*args, **kwargs) -> Any:
147136 # Don't retry on other errors
148137 logger .error (f"Non-retryable error: { e } " )
149138 raise
150-
139+
151140 raise last_exception or Exception ("All retry attempts failed" )
141+
152142 return wrapper
143+
153144 return decorator
0 commit comments