1- import copy
1+ from copy import copy
22from dataclasses import dataclass , field , replace
33from typing import Any , Dict , Optional
44
@@ -44,8 +44,9 @@ class Client:
4444 """
4545
4646 _base_url : str
47- raise_on_unexpected_status : bool
4847 _httpx_config : _HttpxConfig
48+ _client : Optional [httpx .Client ]
49+ _async_client : Optional [httpx .AsyncClient ]
4950
5051 def __init__ (
5152 self ,
@@ -61,26 +62,42 @@ def __init__(
6162 self .raise_on_unexpected_status = raise_on_unexpected_status
6263 self ._base_url = base_url
6364 self ._httpx_config = _HttpxConfig (cookies , headers , timeout , verify_ssl , follow_redirects , httpx_args )
65+ self ._client = None
66+ self ._async_client = None
6467
6568 def _with_httpx_config (self , httpx_config : _HttpxConfig ) -> "Client" :
66- ret = copy . copy (self )
69+ ret = copy (self )
6770 ret ._httpx_config = httpx_config
71+ ret ._client = None
72+ ret ._async_client = None
6873 return ret
6974
7075 def with_headers (self , headers : Dict [str , str ]) -> "Client" :
7176 """Get a new client matching this one with additional headers"""
77+ if self ._client is not None :
78+ self ._client .headers .update (headers )
79+ if self ._async_client is not None :
80+ self ._async_client .headers .update (headers )
7281 return self ._with_httpx_config (
7382 replace (self ._httpx_config , headers = {** self ._httpx_config .headers , ** headers }),
7483 )
7584
7685 def with_cookies (self , cookies : Dict [str , str ]) -> "Client" :
7786 """Get a new client matching this one with additional cookies"""
87+ if self ._client is not None :
88+ self ._client .cookies .update (cookies )
89+ if self ._async_client is not None :
90+ self ._async_client .cookies .update (cookies )
7891 return self ._with_httpx_config (
7992 replace (self ._httpx_config , cookies = {** self ._httpx_config .cookies , ** cookies }),
8093 )
8194
8295 def with_timeout (self , timeout : httpx .Timeout ) -> "Client" :
8396 """Get a new client matching this one with a new timeout (in seconds)"""
97+ if self ._client is not None :
98+ self ._client .timeout = timeout
99+ if self ._async_client is not None :
100+ self ._async_client .timeout = timeout
84101 return self ._with_httpx_config (replace (self ._httpx_config , timeout = timeout ))
85102
86103 def set_httpx_client (self , client : httpx .Client ) -> "Client" :
@@ -97,7 +114,7 @@ def get_httpx_client(self) -> httpx.Client:
97114 self ._client = httpx .Client (
98115 base_url = self ._base_url ,
99116 cookies = self ._httpx_config .cookies ,
100- headers = self ._httpx_config . headers ,
117+ headers = self ._headers ,
101118 timeout = self ._httpx_config .timeout ,
102119 verify = self ._httpx_config .verify_ssl ,
103120 follow_redirects = self ._httpx_config .follow_redirects ,
@@ -128,7 +145,7 @@ def get_async_httpx_client(self) -> httpx.AsyncClient:
128145 self ._async_client = httpx .AsyncClient (
129146 base_url = self ._httpx_config .base_url ,
130147 cookies = self ._httpx_config .cookies ,
131- headers = self ._httpx_config . headers ,
148+ headers = self ._headers ,
132149 timeout = self ._httpx_config .timeout ,
133150 verify = self ._httpx_config .verify_ssl ,
134151 follow_redirects = self ._httpx_config .follow_redirects ,
@@ -178,31 +195,70 @@ class AuthenticatedClient:
178195 """
179196
180197 _base_url : str
181- raise_on_unexpected_status : bool
182198 token : str
183199 prefix : str = "Bearer"
184200 auth_header_name : str = "Authorization"
185201 _httpx_config : _HttpxConfig
202+ _client : Optional [httpx .Client ]
203+ _async_client : Optional [httpx .AsyncClient ]
204+
205+ def __init__ (
206+ self ,
207+ base_url : str ,
208+ token : str ,
209+ prefix : str = "Bearer" ,
210+ auth_header_name : str = "Authorization" ,
211+ cookies : Dict [str , str ] = {},
212+ headers : Dict [str , str ] = {},
213+ timeout : Optional [httpx .Timeout ] = None ,
214+ verify_ssl : bool = True ,
215+ follow_redirects : bool = False ,
216+ httpx_args : Dict [str , Any ] = {},
217+ raise_on_unexpected_status : bool = False ,
218+ ) -> None :
219+ self .raise_on_unexpected_status = raise_on_unexpected_status
220+ self ._base_url = base_url
221+ self ._httpx_config = _HttpxConfig (cookies , headers , timeout , verify_ssl , follow_redirects , httpx_args )
222+ self ._client = None
223+ self ._async_client = None
224+
225+ self .token = token
226+ self .prefix = prefix
227+ self .auth_header_name = auth_header_name
186228
187229 def _with_httpx_config (self , httpx_config : _HttpxConfig ) -> "AuthenticatedClient" :
188- ret = copy . copy (self )
230+ ret = copy (self )
189231 ret ._httpx_config = httpx_config
232+ ret ._client = None
233+ ret ._async_client = None
190234 return ret
191235
192236 def with_headers (self , headers : Dict [str , str ]) -> "AuthenticatedClient" :
193237 """Get a new client matching this one with additional headers"""
238+ if self ._client is not None :
239+ self ._client .headers .update (headers )
240+ if self ._async_client is not None :
241+ self ._async_client .headers .update (headers )
194242 return self ._with_httpx_config (
195243 replace (self ._httpx_config , headers = {** self ._httpx_config .headers , ** headers }),
196244 )
197245
198246 def with_cookies (self , cookies : Dict [str , str ]) -> "AuthenticatedClient" :
199247 """Get a new client matching this one with additional cookies"""
248+ if self ._client is not None :
249+ self ._client .cookies .update (cookies )
250+ if self ._async_client is not None :
251+ self ._async_client .cookies .update (cookies )
200252 return self ._with_httpx_config (
201253 replace (self ._httpx_config , cookies = {** self ._httpx_config .cookies , ** cookies }),
202254 )
203255
204256 def with_timeout (self , timeout : httpx .Timeout ) -> "AuthenticatedClient" :
205257 """Get a new client matching this one with a new timeout (in seconds)"""
258+ if self ._client is not None :
259+ self ._client .timeout = timeout
260+ if self ._async_client is not None :
261+ self ._async_client .timeout = timeout
206262 return self ._with_httpx_config (replace (self ._httpx_config , timeout = timeout ))
207263
208264 def set_httpx_client (self , client : httpx .Client ) -> "AuthenticatedClient" :
@@ -216,11 +272,13 @@ def set_httpx_client(self, client: httpx.Client) -> "AuthenticatedClient":
216272 def get_httpx_client (self ) -> httpx .Client :
217273 """Get the underlying httpx.Client, constructing a new one if not previously set"""
218274 if self ._client is None :
219- self ._headers [self .auth_header_name ] = f"{ self .prefix } { self .token } " if self .prefix else self .token
220275 self ._client = httpx .Client (
221276 base_url = self ._base_url ,
222277 cookies = self ._httpx_config .cookies ,
223- headers = self ._httpx_config .headers ,
278+ headers = {
279+ self .auth_header_name : (f"{ self .prefix } { self .token } " if self .prefix else self .token ),
280+ ** self ._httpx_config .headers ,
281+ },
224282 timeout = self ._httpx_config .timeout ,
225283 verify = self ._httpx_config .verify_ssl ,
226284 follow_redirects = self ._httpx_config .follow_redirects ,
@@ -248,11 +306,13 @@ def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "Authentica
248306 def get_async_httpx_client (self ) -> httpx .AsyncClient :
249307 """Get the underlying httpx.AsyncClient, constructing a new one if not previously set"""
250308 if self ._async_client is None :
251- self ._headers [self .auth_header_name ] = f"{ self .prefix } { self .token } " if self .prefix else self .token
252309 self ._async_client = httpx .AsyncClient (
253310 base_url = self ._httpx_config .base_url ,
254311 cookies = self ._httpx_config .cookies ,
255- headers = self ._httpx_config .headers ,
312+ headers = {
313+ self .auth_header_name : (f"{ self .prefix } { self .token } " if self .prefix else self .token ),
314+ ** self ._httpx_config .headers ,
315+ },
256316 timeout = self ._httpx_config .timeout ,
257317 verify = self ._httpx_config .verify_ssl ,
258318 follow_redirects = self ._httpx_config .follow_redirects ,
0 commit comments