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