1
- import copy
1
+ from copy import copy
2
2
from dataclasses import dataclass , field , replace
3
3
from typing import Any , Dict , Optional
4
4
@@ -44,8 +44,9 @@ class Client:
44
44
"""
45
45
46
46
_base_url : str
47
- raise_on_unexpected_status : bool
48
47
_httpx_config : _HttpxConfig
48
+ _client : Optional [httpx .Client ]
49
+ _async_client : Optional [httpx .AsyncClient ]
49
50
50
51
def __init__ (
51
52
self ,
@@ -61,26 +62,42 @@ def __init__(
61
62
self .raise_on_unexpected_status = raise_on_unexpected_status
62
63
self ._base_url = base_url
63
64
self ._httpx_config = _HttpxConfig (cookies , headers , timeout , verify_ssl , follow_redirects , httpx_args )
65
+ self ._client = None
66
+ self ._async_client = None
64
67
65
68
def _with_httpx_config (self , httpx_config : _HttpxConfig ) -> "Client" :
66
- ret = copy . copy (self )
69
+ ret = copy (self )
67
70
ret ._httpx_config = httpx_config
71
+ ret ._client = None
72
+ ret ._async_client = None
68
73
return ret
69
74
70
75
def with_headers (self , headers : Dict [str , str ]) -> "Client" :
71
76
"""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 )
72
81
return self ._with_httpx_config (
73
82
replace (self ._httpx_config , headers = {** self ._httpx_config .headers , ** headers }),
74
83
)
75
84
76
85
def with_cookies (self , cookies : Dict [str , str ]) -> "Client" :
77
86
"""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 )
78
91
return self ._with_httpx_config (
79
92
replace (self ._httpx_config , cookies = {** self ._httpx_config .cookies , ** cookies }),
80
93
)
81
94
82
95
def with_timeout (self , timeout : httpx .Timeout ) -> "Client" :
83
96
"""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
84
101
return self ._with_httpx_config (replace (self ._httpx_config , timeout = timeout ))
85
102
86
103
def set_httpx_client (self , client : httpx .Client ) -> "Client" :
@@ -97,7 +114,7 @@ def get_httpx_client(self) -> httpx.Client:
97
114
self ._client = httpx .Client (
98
115
base_url = self ._base_url ,
99
116
cookies = self ._httpx_config .cookies ,
100
- headers = self ._httpx_config . headers ,
117
+ headers = self ._headers ,
101
118
timeout = self ._httpx_config .timeout ,
102
119
verify = self ._httpx_config .verify_ssl ,
103
120
follow_redirects = self ._httpx_config .follow_redirects ,
@@ -128,7 +145,7 @@ def get_async_httpx_client(self) -> httpx.AsyncClient:
128
145
self ._async_client = httpx .AsyncClient (
129
146
base_url = self ._httpx_config .base_url ,
130
147
cookies = self ._httpx_config .cookies ,
131
- headers = self ._httpx_config . headers ,
148
+ headers = self ._headers ,
132
149
timeout = self ._httpx_config .timeout ,
133
150
verify = self ._httpx_config .verify_ssl ,
134
151
follow_redirects = self ._httpx_config .follow_redirects ,
@@ -178,31 +195,70 @@ class AuthenticatedClient:
178
195
"""
179
196
180
197
_base_url : str
181
- raise_on_unexpected_status : bool
182
198
token : str
183
199
prefix : str = "Bearer"
184
200
auth_header_name : str = "Authorization"
185
201
_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
186
228
187
229
def _with_httpx_config (self , httpx_config : _HttpxConfig ) -> "AuthenticatedClient" :
188
- ret = copy . copy (self )
230
+ ret = copy (self )
189
231
ret ._httpx_config = httpx_config
232
+ ret ._client = None
233
+ ret ._async_client = None
190
234
return ret
191
235
192
236
def with_headers (self , headers : Dict [str , str ]) -> "AuthenticatedClient" :
193
237
"""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 )
194
242
return self ._with_httpx_config (
195
243
replace (self ._httpx_config , headers = {** self ._httpx_config .headers , ** headers }),
196
244
)
197
245
198
246
def with_cookies (self , cookies : Dict [str , str ]) -> "AuthenticatedClient" :
199
247
"""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 )
200
252
return self ._with_httpx_config (
201
253
replace (self ._httpx_config , cookies = {** self ._httpx_config .cookies , ** cookies }),
202
254
)
203
255
204
256
def with_timeout (self , timeout : httpx .Timeout ) -> "AuthenticatedClient" :
205
257
"""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
206
262
return self ._with_httpx_config (replace (self ._httpx_config , timeout = timeout ))
207
263
208
264
def set_httpx_client (self , client : httpx .Client ) -> "AuthenticatedClient" :
@@ -216,11 +272,13 @@ def set_httpx_client(self, client: httpx.Client) -> "AuthenticatedClient":
216
272
def get_httpx_client (self ) -> httpx .Client :
217
273
"""Get the underlying httpx.Client, constructing a new one if not previously set"""
218
274
if self ._client is None :
219
- self ._headers [self .auth_header_name ] = f"{ self .prefix } { self .token } " if self .prefix else self .token
220
275
self ._client = httpx .Client (
221
276
base_url = self ._base_url ,
222
277
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
+ },
224
282
timeout = self ._httpx_config .timeout ,
225
283
verify = self ._httpx_config .verify_ssl ,
226
284
follow_redirects = self ._httpx_config .follow_redirects ,
@@ -248,11 +306,13 @@ def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "Authentica
248
306
def get_async_httpx_client (self ) -> httpx .AsyncClient :
249
307
"""Get the underlying httpx.AsyncClient, constructing a new one if not previously set"""
250
308
if self ._async_client is None :
251
- self ._headers [self .auth_header_name ] = f"{ self .prefix } { self .token } " if self .prefix else self .token
252
309
self ._async_client = httpx .AsyncClient (
253
310
base_url = self ._httpx_config .base_url ,
254
311
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
+ },
256
316
timeout = self ._httpx_config .timeout ,
257
317
verify = self ._httpx_config .verify_ssl ,
258
318
follow_redirects = self ._httpx_config .follow_redirects ,
0 commit comments