66
77_RETRY_STATUSES = {429 , 502 , 503 , 504 }
88
9+
910class HTTPTransport :
10- def __init__ (self , address : str , token : str , * , timeout : float , verify_tls : bool ,
11- user_agent_suffix : str | None , max_retries : int , backoff_base : float ,
12- backoff_cap : float , backoff_jitter : bool , http2 : bool , proxies : dict | None ,
13- ca_bundle : str | None ):
14- self .base = address .rstrip ('/' )
11+ def __init__ (
12+ self ,
13+ address : str ,
14+ token : str ,
15+ * ,
16+ timeout : float ,
17+ verify_tls : bool ,
18+ user_agent_suffix : str | None ,
19+ max_retries : int ,
20+ backoff_base : float ,
21+ backoff_cap : float ,
22+ backoff_jitter : bool ,
23+ http2 : bool ,
24+ proxies : dict | None ,
25+ ca_bundle : str | None ,
26+ ):
27+ self .base = address .rstrip ("/" )
1528 self .headers = build_headers (user_agent_suffix )
1629 if token :
1730 self .headers ["Authorization" ] = f"Bearer { token } "
@@ -24,70 +37,131 @@ def __init__(self, address: str, token: str, *, timeout: float, verify_tls: bool
2437 self .http2 = http2
2538 self .proxies = proxies
2639 self .ca_bundle = ca_bundle
27- self ._sync = httpx .Client (http2 = http2 , timeout = timeout , verify = ca_bundle or verify_tls ) #proxies=proxies
28- self ._async = httpx .AsyncClient (http2 = http2 , timeout = timeout , verify = ca_bundle or verify_tls ) #proxies=proxies
40+ self ._sync = httpx .Client (
41+ http2 = http2 , timeout = timeout , verify = ca_bundle or verify_tls
42+ ) # proxies=proxies
43+ self ._async = httpx .AsyncClient (
44+ http2 = http2 , timeout = timeout , verify = ca_bundle or verify_tls
45+ ) # proxies=proxies
2946
30- def request (self , method : str , path : str , * , params : Mapping [str , Any ] | None = None ,
31- json_body : Mapping [str , Any ] | None = None , headers : dict [str , str ] | None = None ,
32- allow_redirects : bool = True ) -> httpx .Response :
47+ def request (
48+ self ,
49+ method : str ,
50+ path : str ,
51+ * ,
52+ params : Mapping [str , Any ] | None = None ,
53+ json_body : Mapping [str , Any ] | None = None ,
54+ headers : dict [str , str ] | None = None ,
55+ allow_redirects : bool = True ,
56+ ) -> httpx .Response :
3357 url = f"{ self .base } { path } "
3458 hdrs = dict (self .headers )
3559 if headers :
3660 hdrs .update (headers )
3761 attempt = 0
3862 while True :
3963 try :
40- resp = self ._sync .request (method , url , params = params , json = json_body , headers = hdrs , follow_redirects = allow_redirects )
64+ resp = self ._sync .request (
65+ method ,
66+ url ,
67+ params = params ,
68+ json = json_body ,
69+ headers = hdrs ,
70+ follow_redirects = allow_redirects ,
71+ )
4172 except httpx .HTTPError as e :
42- if attempt >= self .max_retries : raise ServerError (str (e ))
43- self ._sleep (attempt , None ); attempt += 1 ; continue
73+ if attempt >= self .max_retries :
74+ raise ServerError (str (e ))
75+ self ._sleep (attempt , None )
76+ attempt += 1
77+ continue
4478 if resp .status_code in _RETRY_STATUSES and attempt < self .max_retries :
4579 retry_after = _parse_retry_after (resp )
46- self ._sleep (attempt , retry_after ); attempt += 1 ; continue
47- self ._raise_if_error (resp ); return resp
80+ self ._sleep (attempt , retry_after )
81+ attempt += 1
82+ continue
83+ self ._raise_if_error (resp )
84+ return resp
4885
49- async def arequest (self , method : str , path : str , * , params : Mapping [str , Any ] | None = None ,
50- json_body : Mapping [str , Any ] | None = None , headers : dict [str , str ] | None = None ,
51- allow_redirects : bool = True ) -> httpx .Response :
52- url = f"{ self .base } { path } " ; hdrs = dict (self .headers ); hdrs .update (headers or {})
86+ async def arequest (
87+ self ,
88+ method : str ,
89+ path : str ,
90+ * ,
91+ params : Mapping [str , Any ] | None = None ,
92+ json_body : Mapping [str , Any ] | None = None ,
93+ headers : dict [str , str ] | None = None ,
94+ allow_redirects : bool = True ,
95+ ) -> httpx .Response :
96+ url = f"{ self .base } { path } "
97+ hdrs = dict (self .headers )
98+ hdrs .update (headers or {})
5399 attempt = 0
54100 while True :
55101 try :
56- resp = await self ._async .request (method , url , params = params , json = json_body , headers = hdrs , follow_redirects = allow_redirects )
102+ resp = await self ._async .request (
103+ method ,
104+ url ,
105+ params = params ,
106+ json = json_body ,
107+ headers = hdrs ,
108+ follow_redirects = allow_redirects ,
109+ )
57110 except httpx .HTTPError as e :
58- if attempt >= self .max_retries : raise ServerError (str (e ))
59- await self ._asleep (attempt , None ); attempt += 1 ; continue
111+ if attempt >= self .max_retries :
112+ raise ServerError (str (e ))
113+ await self ._asleep (attempt , None )
114+ attempt += 1
115+ continue
60116 if resp .status_code in _RETRY_STATUSES and attempt < self .max_retries :
61117 retry_after = _parse_retry_after (resp )
62- await self ._asleep (attempt , retry_after ); attempt += 1 ; continue
63- self ._raise_if_error (resp ); return resp
118+ await self ._asleep (attempt , retry_after )
119+ attempt += 1
120+ continue
121+ self ._raise_if_error (resp )
122+ return resp
64123
65124 def _sleep (self , attempt : int , retry_after : float | None ):
66- if retry_after is not None : time .sleep (retry_after ); return
67- delay = min (self .backoff_cap , self .backoff_base * (2 ** attempt ))
125+ if retry_after is not None :
126+ time .sleep (retry_after )
127+ return
128+ delay = min (self .backoff_cap , self .backoff_base * (2 ** attempt ))
68129 time .sleep (delay )
69130
70131 async def _asleep (self , attempt : int , retry_after : float | None ):
71- if retry_after is not None : await anyio .sleep (retry_after ); return
72- delay = min (self .backoff_cap , self .backoff_base * (2 ** attempt ))
132+ if retry_after is not None :
133+ await anyio .sleep (retry_after )
134+ return
135+ delay = min (self .backoff_cap , self .backoff_base * (2 ** attempt ))
73136 await anyio .sleep (delay )
74137
75138 def _raise_if_error (self , resp : httpx .Response ):
76- if 200 <= resp .status_code < 300 : return
77- try : payload = resp .json ()
78- except Exception : payload = {}
139+ if 200 <= resp .status_code < 300 :
140+ return
141+ try :
142+ payload = resp .json ()
143+ except Exception :
144+ payload = {}
79145 errors = parse_error_payload (payload )
80- msg = ( errors [0 ].get ("detail" ) if errors else f"HTTP { resp .status_code } " )
146+ msg = errors [0 ].get ("detail" ) if errors else f"HTTP { resp .status_code } "
81147 status = resp .status_code
82- if status in (401 ,403 ): raise AuthError (msg , status = status , errors = errors )
83- if status == 404 : raise NotFound (msg , status = status , errors = errors )
148+ if status in (401 , 403 ):
149+ raise AuthError (msg , status = status , errors = errors )
150+ if status == 404 :
151+ raise NotFound (msg , status = status , errors = errors )
84152 if status == 429 :
85- ra = _parse_retry_after (resp ); raise RateLimited (msg , status = status , errors = errors , retry_after = ra )
86- if status >= 500 : raise ServerError (msg , status = status , errors = errors )
153+ ra = _parse_retry_after (resp )
154+ raise RateLimited (msg , status = status , errors = errors , retry_after = ra )
155+ if status >= 500 :
156+ raise ServerError (msg , status = status , errors = errors )
87157 raise TFEError (msg , status = status , errors = errors )
88158
159+
89160def _parse_retry_after (resp : httpx .Response ) -> float | None :
90161 ra = resp .headers .get ("Retry-After" )
91- if not ra : return None
92- try : return float (ra )
93- except Exception : return None
162+ if not ra :
163+ return None
164+ try :
165+ return float (ra )
166+ except Exception :
167+ return None
0 commit comments