5
5
import socket
6
6
import time
7
7
from http import cookiejar
8
- from typing import Any , Callable , Literal , MutableMapping
8
+ from typing import Any , Callable , ClassVar , Literal , MutableMapping
9
9
10
10
import requests
11
11
import requests .adapters
@@ -96,6 +96,18 @@ def should_retry(self, status_code: int | None) -> bool:
96
96
97
97
98
98
class HTTPClient :
99
+ _TIMEOUT_EXCEPTIONS : ClassVar [tuple [type [Exception ], ...]] = (
100
+ socket .timeout ,
101
+ urllib3 .exceptions .ReadTimeoutError ,
102
+ requests .exceptions .ReadTimeout ,
103
+ )
104
+ _CONNECTION_EXCEPTIONS : ClassVar [tuple [type [Exception ], ...]] = (
105
+ ConnectionError ,
106
+ urllib3 .exceptions .ConnectionError ,
107
+ urllib3 .exceptions .ConnectTimeoutError ,
108
+ requests .exceptions .ConnectionError ,
109
+ )
110
+
99
111
def __init__ (
100
112
self ,
101
113
config : HTTPClientConfig ,
@@ -114,7 +126,7 @@ def request(self, method: str, url: str, **kwargs: Any) -> requests.Response:
114
126
last_status = None
115
127
while True :
116
128
try :
117
- res = self ._do_request (method = method , url = url , ** kwargs )
129
+ res = self ._make_request (method = method , url = url , ** kwargs )
118
130
if global_config .usage_tracking_callback :
119
131
# We use the RequestDetails as an indirection to avoid the user mutating the request:
120
132
global_config .usage_tracking_callback (RequestDetails .from_response (res ))
@@ -125,53 +137,45 @@ def request(self, method: str, url: str, **kwargs: Any) -> requests.Response:
125
137
# Cache .json() return value in order to avoid redecoding JSON if called multiple times
126
138
res .json = functools .lru_cache (maxsize = 1 )(res .json ) # type: ignore[assignment]
127
139
return res
128
- except CogniteReadTimeout as e :
140
+
141
+ except CogniteReadTimeout :
129
142
retry_tracker .read += 1
130
143
if not retry_tracker .should_retry (status_code = last_status ):
131
- raise e
132
- except CogniteConnectionError as e :
144
+ raise
145
+
146
+ except CogniteConnectionError :
133
147
retry_tracker .connect += 1
134
148
if not retry_tracker .should_retry (status_code = last_status ):
135
- raise e
149
+ raise
136
150
137
151
# During a backoff loop, our credentials might expire, so we check and maybe refresh:
138
152
time .sleep (retry_tracker .get_backoff_time ())
139
153
if headers is not None :
140
154
# TODO: Refactoring needed to make this "prettier"
141
155
self .refresh_auth_header (headers )
142
156
143
- def _do_request (self , method : str , url : str , ** kwargs : Any ) -> requests .Response :
157
+ def _make_request (self , method : str , url : str , ** kwargs : Any ) -> requests .Response :
144
158
"""requests/urllib3 adds 2 or 3 layers of exceptions on top of built-in networking exceptions.
145
159
146
160
Sometimes the appropriate built-in networking exception is not in the context, sometimes the requests
147
161
exception is not in the context, so we need to check for the appropriate built-in exceptions,
148
162
urllib3 exceptions, and requests exceptions.
149
163
"""
150
164
try :
151
- res = self .session .request (method = method , url = url , ** kwargs )
152
- return res
165
+ return self .session .request (method = method , url = url , ** kwargs )
153
166
except Exception as e :
154
- if self ._any_exception_in_context_isinstance (
155
- e , (socket .timeout , urllib3 .exceptions .ReadTimeoutError , requests .exceptions .ReadTimeout )
156
- ):
167
+ if self ._any_exception_in_context_isinstance (e , self ._TIMEOUT_EXCEPTIONS ):
157
168
raise CogniteReadTimeout from e
158
- if self ._any_exception_in_context_isinstance (
159
- e ,
160
- (
161
- ConnectionError ,
162
- urllib3 .exceptions .ConnectionError ,
163
- urllib3 .exceptions .ConnectTimeoutError ,
164
- requests .exceptions .ConnectionError ,
165
- ),
166
- ):
169
+
170
+ if self ._any_exception_in_context_isinstance (e , self ._CONNECTION_EXCEPTIONS ):
167
171
if self ._any_exception_in_context_isinstance (e , ConnectionRefusedError ):
168
172
raise CogniteConnectionRefused from e
169
173
raise CogniteConnectionError from e
170
- raise e
174
+ raise
171
175
172
176
@classmethod
173
177
def _any_exception_in_context_isinstance (
174
- cls , exc : BaseException , exc_types : tuple [type [BaseException ], ...] | type [BaseException ]
178
+ cls , exc : BaseException , exc_types : tuple [type [Exception ], ...] | type [Exception ]
175
179
) -> bool :
176
180
"""requests does not use the "raise ... from ..." syntax, so we need to access the underlying exceptions using
177
181
the __context__ attribute.
0 commit comments