Mercurial > repos > shellac > sam_consensus_v3
comparison env/lib/python3.9/site-packages/urllib3/util/timeout.py @ 0:4f3585e2f14b draft default tip
"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author | shellac |
---|---|
date | Mon, 22 Mar 2021 18:12:50 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4f3585e2f14b |
---|---|
1 from __future__ import absolute_import | |
2 | |
3 import time | |
4 | |
5 # The default socket timeout, used by httplib to indicate that no timeout was | |
6 # specified by the user | |
7 from socket import _GLOBAL_DEFAULT_TIMEOUT | |
8 | |
9 from ..exceptions import TimeoutStateError | |
10 | |
11 # A sentinel value to indicate that no timeout was specified by the user in | |
12 # urllib3 | |
13 _Default = object() | |
14 | |
15 | |
16 # Use time.monotonic if available. | |
17 current_time = getattr(time, "monotonic", time.time) | |
18 | |
19 | |
20 class Timeout(object): | |
21 """Timeout configuration. | |
22 | |
23 Timeouts can be defined as a default for a pool: | |
24 | |
25 .. code-block:: python | |
26 | |
27 timeout = Timeout(connect=2.0, read=7.0) | |
28 http = PoolManager(timeout=timeout) | |
29 response = http.request('GET', 'http://example.com/') | |
30 | |
31 Or per-request (which overrides the default for the pool): | |
32 | |
33 .. code-block:: python | |
34 | |
35 response = http.request('GET', 'http://example.com/', timeout=Timeout(10)) | |
36 | |
37 Timeouts can be disabled by setting all the parameters to ``None``: | |
38 | |
39 .. code-block:: python | |
40 | |
41 no_timeout = Timeout(connect=None, read=None) | |
42 response = http.request('GET', 'http://example.com/, timeout=no_timeout) | |
43 | |
44 | |
45 :param total: | |
46 This combines the connect and read timeouts into one; the read timeout | |
47 will be set to the time leftover from the connect attempt. In the | |
48 event that both a connect timeout and a total are specified, or a read | |
49 timeout and a total are specified, the shorter timeout will be applied. | |
50 | |
51 Defaults to None. | |
52 | |
53 :type total: int, float, or None | |
54 | |
55 :param connect: | |
56 The maximum amount of time (in seconds) to wait for a connection | |
57 attempt to a server to succeed. Omitting the parameter will default the | |
58 connect timeout to the system default, probably `the global default | |
59 timeout in socket.py | |
60 <http://hg.python.org/cpython/file/603b4d593758/Lib/socket.py#l535>`_. | |
61 None will set an infinite timeout for connection attempts. | |
62 | |
63 :type connect: int, float, or None | |
64 | |
65 :param read: | |
66 The maximum amount of time (in seconds) to wait between consecutive | |
67 read operations for a response from the server. Omitting the parameter | |
68 will default the read timeout to the system default, probably `the | |
69 global default timeout in socket.py | |
70 <http://hg.python.org/cpython/file/603b4d593758/Lib/socket.py#l535>`_. | |
71 None will set an infinite timeout. | |
72 | |
73 :type read: int, float, or None | |
74 | |
75 .. note:: | |
76 | |
77 Many factors can affect the total amount of time for urllib3 to return | |
78 an HTTP response. | |
79 | |
80 For example, Python's DNS resolver does not obey the timeout specified | |
81 on the socket. Other factors that can affect total request time include | |
82 high CPU load, high swap, the program running at a low priority level, | |
83 or other behaviors. | |
84 | |
85 In addition, the read and total timeouts only measure the time between | |
86 read operations on the socket connecting the client and the server, | |
87 not the total amount of time for the request to return a complete | |
88 response. For most requests, the timeout is raised because the server | |
89 has not sent the first byte in the specified time. This is not always | |
90 the case; if a server streams one byte every fifteen seconds, a timeout | |
91 of 20 seconds will not trigger, even though the request will take | |
92 several minutes to complete. | |
93 | |
94 If your goal is to cut off any request after a set amount of wall clock | |
95 time, consider having a second "watcher" thread to cut off a slow | |
96 request. | |
97 """ | |
98 | |
99 #: A sentinel object representing the default timeout value | |
100 DEFAULT_TIMEOUT = _GLOBAL_DEFAULT_TIMEOUT | |
101 | |
102 def __init__(self, total=None, connect=_Default, read=_Default): | |
103 self._connect = self._validate_timeout(connect, "connect") | |
104 self._read = self._validate_timeout(read, "read") | |
105 self.total = self._validate_timeout(total, "total") | |
106 self._start_connect = None | |
107 | |
108 def __repr__(self): | |
109 return "%s(connect=%r, read=%r, total=%r)" % ( | |
110 type(self).__name__, | |
111 self._connect, | |
112 self._read, | |
113 self.total, | |
114 ) | |
115 | |
116 # __str__ provided for backwards compatibility | |
117 __str__ = __repr__ | |
118 | |
119 @classmethod | |
120 def _validate_timeout(cls, value, name): | |
121 """Check that a timeout attribute is valid. | |
122 | |
123 :param value: The timeout value to validate | |
124 :param name: The name of the timeout attribute to validate. This is | |
125 used to specify in error messages. | |
126 :return: The validated and casted version of the given value. | |
127 :raises ValueError: If it is a numeric value less than or equal to | |
128 zero, or the type is not an integer, float, or None. | |
129 """ | |
130 if value is _Default: | |
131 return cls.DEFAULT_TIMEOUT | |
132 | |
133 if value is None or value is cls.DEFAULT_TIMEOUT: | |
134 return value | |
135 | |
136 if isinstance(value, bool): | |
137 raise ValueError( | |
138 "Timeout cannot be a boolean value. It must " | |
139 "be an int, float or None." | |
140 ) | |
141 try: | |
142 float(value) | |
143 except (TypeError, ValueError): | |
144 raise ValueError( | |
145 "Timeout value %s was %s, but it must be an " | |
146 "int, float or None." % (name, value) | |
147 ) | |
148 | |
149 try: | |
150 if value <= 0: | |
151 raise ValueError( | |
152 "Attempted to set %s timeout to %s, but the " | |
153 "timeout cannot be set to a value less " | |
154 "than or equal to 0." % (name, value) | |
155 ) | |
156 except TypeError: | |
157 # Python 3 | |
158 raise ValueError( | |
159 "Timeout value %s was %s, but it must be an " | |
160 "int, float or None." % (name, value) | |
161 ) | |
162 | |
163 return value | |
164 | |
165 @classmethod | |
166 def from_float(cls, timeout): | |
167 """Create a new Timeout from a legacy timeout value. | |
168 | |
169 The timeout value used by httplib.py sets the same timeout on the | |
170 connect(), and recv() socket requests. This creates a :class:`Timeout` | |
171 object that sets the individual timeouts to the ``timeout`` value | |
172 passed to this function. | |
173 | |
174 :param timeout: The legacy timeout value. | |
175 :type timeout: integer, float, sentinel default object, or None | |
176 :return: Timeout object | |
177 :rtype: :class:`Timeout` | |
178 """ | |
179 return Timeout(read=timeout, connect=timeout) | |
180 | |
181 def clone(self): | |
182 """Create a copy of the timeout object | |
183 | |
184 Timeout properties are stored per-pool but each request needs a fresh | |
185 Timeout object to ensure each one has its own start/stop configured. | |
186 | |
187 :return: a copy of the timeout object | |
188 :rtype: :class:`Timeout` | |
189 """ | |
190 # We can't use copy.deepcopy because that will also create a new object | |
191 # for _GLOBAL_DEFAULT_TIMEOUT, which socket.py uses as a sentinel to | |
192 # detect the user default. | |
193 return Timeout(connect=self._connect, read=self._read, total=self.total) | |
194 | |
195 def start_connect(self): | |
196 """Start the timeout clock, used during a connect() attempt | |
197 | |
198 :raises urllib3.exceptions.TimeoutStateError: if you attempt | |
199 to start a timer that has been started already. | |
200 """ | |
201 if self._start_connect is not None: | |
202 raise TimeoutStateError("Timeout timer has already been started.") | |
203 self._start_connect = current_time() | |
204 return self._start_connect | |
205 | |
206 def get_connect_duration(self): | |
207 """Gets the time elapsed since the call to :meth:`start_connect`. | |
208 | |
209 :return: Elapsed time in seconds. | |
210 :rtype: float | |
211 :raises urllib3.exceptions.TimeoutStateError: if you attempt | |
212 to get duration for a timer that hasn't been started. | |
213 """ | |
214 if self._start_connect is None: | |
215 raise TimeoutStateError( | |
216 "Can't get connect duration for timer that has not started." | |
217 ) | |
218 return current_time() - self._start_connect | |
219 | |
220 @property | |
221 def connect_timeout(self): | |
222 """Get the value to use when setting a connection timeout. | |
223 | |
224 This will be a positive float or integer, the value None | |
225 (never timeout), or the default system timeout. | |
226 | |
227 :return: Connect timeout. | |
228 :rtype: int, float, :attr:`Timeout.DEFAULT_TIMEOUT` or None | |
229 """ | |
230 if self.total is None: | |
231 return self._connect | |
232 | |
233 if self._connect is None or self._connect is self.DEFAULT_TIMEOUT: | |
234 return self.total | |
235 | |
236 return min(self._connect, self.total) | |
237 | |
238 @property | |
239 def read_timeout(self): | |
240 """Get the value for the read timeout. | |
241 | |
242 This assumes some time has elapsed in the connection timeout and | |
243 computes the read timeout appropriately. | |
244 | |
245 If self.total is set, the read timeout is dependent on the amount of | |
246 time taken by the connect timeout. If the connection time has not been | |
247 established, a :exc:`~urllib3.exceptions.TimeoutStateError` will be | |
248 raised. | |
249 | |
250 :return: Value to use for the read timeout. | |
251 :rtype: int, float, :attr:`Timeout.DEFAULT_TIMEOUT` or None | |
252 :raises urllib3.exceptions.TimeoutStateError: If :meth:`start_connect` | |
253 has not yet been called on this object. | |
254 """ | |
255 if ( | |
256 self.total is not None | |
257 and self.total is not self.DEFAULT_TIMEOUT | |
258 and self._read is not None | |
259 and self._read is not self.DEFAULT_TIMEOUT | |
260 ): | |
261 # In case the connect timeout has not yet been established. | |
262 if self._start_connect is None: | |
263 return self._read | |
264 return max(0, min(self.total - self.get_connect_duration(), self._read)) | |
265 elif self.total is not None and self.total is not self.DEFAULT_TIMEOUT: | |
266 return max(0, self.total - self.get_connect_duration()) | |
267 else: | |
268 return self._read |