3737from typing import Any , Optional , cast
3838
3939from requests import Response , adapters
40+ from requests .exceptions import RetryError as RequestsRetryError
4041from requests_toolbelt import sessions # type: ignore
4142from requests_toolbelt .sessions import BaseUrlSession # type: ignore
4243from urllib3 .util .retry import Retry
5556 status_forcelist = [
5657 403 ,
5758 429 ,
58- 500 ,
5959 502 ,
6060 503 ,
6161 504 ,
6262 ], # Example: also retry on these HTTP status codes
6363 allowed_methods = ["GET" , "PUT" , "POST" , "PATCH" , "DELETE" ], # Methods to retry
64+ raise_on_status = False ,
6465)
6566SESSION = sessions .BaseUrlSession (base_url = API_ROOT )
6667adapter = adapters .HTTPAdapter (
@@ -140,6 +141,27 @@ class PermissionError(ApiError):
140141 """Raised when the CDA request is not authorized for the current caller."""
141142
142143
144+ def _unwrap_retry_error (error : RequestsRetryError ) -> Exception :
145+ """Return the original retry cause when requests wraps it in RetryError."""
146+
147+ current : Exception = error
148+ cause = error .__cause__
149+ while isinstance (cause , Exception ):
150+ current = cause
151+ cause = cause .__cause__
152+
153+ if current is error and error .args :
154+ first_arg = error .args [0 ]
155+ if isinstance (first_arg , Exception ):
156+ current = first_arg
157+ reason = getattr (current , "reason" , None )
158+ while isinstance (reason , Exception ):
159+ current = reason
160+ reason = getattr (current , "reason" , None )
161+
162+ return current
163+
164+
143165def init_session (
144166 * ,
145167 api_root : Optional [str ] = None ,
@@ -308,11 +330,14 @@ def get(
308330 """
309331
310332 headers = {"Accept" : api_version_text (api_version )}
311- with SESSION .get (endpoint , params = params , headers = headers ) as response :
312- if not response .ok :
313- logging .error (f"CDA Error: response={ response } " )
314- raise ApiError (response )
315- return _process_response (response )
333+ try :
334+ with SESSION .get (endpoint , params = params , headers = headers ) as response :
335+ if not response .ok :
336+ logging .error (f"CDA Error: response={ response } " )
337+ raise ApiError (response )
338+ return _process_response (response )
339+ except RequestsRetryError as error :
340+ raise _unwrap_retry_error (error ) from None
316341
317342
318343def get_with_paging (
@@ -367,11 +392,16 @@ def _post_function(
367392 headers = {"accept" : "*/*" , "Content-Type" : api_version_text (api_version )}
368393 if isinstance (data , dict ) or isinstance (data , list ):
369394 data = json .dumps (data )
370- with SESSION .post (endpoint , params = params , headers = headers , data = data ) as response :
371- if not response .ok :
372- logging .error (f"CDA Error: response={ response } " )
373- raise ApiError (response )
374- return response
395+ try :
396+ with SESSION .post (
397+ endpoint , params = params , headers = headers , data = data
398+ ) as response :
399+ if not response .ok :
400+ logging .error (f"CDA Error: response={ response } " )
401+ raise ApiError (response )
402+ return response
403+ except RequestsRetryError as error :
404+ raise _unwrap_retry_error (error ) from None
375405
376406
377407def post (
@@ -461,10 +491,15 @@ def patch(
461491
462492 if data and isinstance (data , dict ) or isinstance (data , list ):
463493 data = json .dumps (data )
464- with SESSION .patch (endpoint , params = params , headers = headers , data = data ) as response :
465- if not response .ok :
466- logging .error (f"CDA Error: response={ response } " )
467- raise ApiError (response )
494+ try :
495+ with SESSION .patch (
496+ endpoint , params = params , headers = headers , data = data
497+ ) as response :
498+ if not response .ok :
499+ logging .error (f"CDA Error: response={ response } " )
500+ raise ApiError (response )
501+ except RequestsRetryError as error :
502+ raise _unwrap_retry_error (error ) from None
468503
469504
470505def delete (
@@ -488,7 +523,10 @@ def delete(
488523 """
489524
490525 headers = {"Accept" : api_version_text (api_version )}
491- with SESSION .delete (endpoint , params = params , headers = headers ) as response :
492- if not response .ok :
493- logging .error (f"CDA Error: response={ response } " )
494- raise ApiError (response )
526+ try :
527+ with SESSION .delete (endpoint , params = params , headers = headers ) as response :
528+ if not response .ok :
529+ logging .error (f"CDA Error: response={ response } " )
530+ raise ApiError (response )
531+ except RequestsRetryError as error :
532+ raise _unwrap_retry_error (error ) from None
0 commit comments