Path: blob/master/venv/Lib/site-packages/urllib3/util/timeout.py
811 views
from __future__ import absolute_import12# The default socket timeout, used by httplib to indicate that no timeout was3# specified by the user4from socket import _GLOBAL_DEFAULT_TIMEOUT5import time67from ..exceptions import TimeoutStateError89# A sentinel value to indicate that no timeout was specified by the user in10# urllib311_Default = object()121314# Use time.monotonic if available.15current_time = getattr(time, "monotonic", time.time)161718class Timeout(object):19""" Timeout configuration.2021Timeouts can be defined as a default for a pool::2223timeout = Timeout(connect=2.0, read=7.0)24http = PoolManager(timeout=timeout)25response = http.request('GET', 'http://example.com/')2627Or per-request (which overrides the default for the pool)::2829response = http.request('GET', 'http://example.com/', timeout=Timeout(10))3031Timeouts can be disabled by setting all the parameters to ``None``::3233no_timeout = Timeout(connect=None, read=None)34response = http.request('GET', 'http://example.com/, timeout=no_timeout)353637:param total:38This combines the connect and read timeouts into one; the read timeout39will be set to the time leftover from the connect attempt. In the40event that both a connect timeout and a total are specified, or a read41timeout and a total are specified, the shorter timeout will be applied.4243Defaults to None.4445:type total: integer, float, or None4647:param connect:48The maximum amount of time (in seconds) to wait for a connection49attempt to a server to succeed. Omitting the parameter will default the50connect timeout to the system default, probably `the global default51timeout in socket.py52<http://hg.python.org/cpython/file/603b4d593758/Lib/socket.py#l535>`_.53None will set an infinite timeout for connection attempts.5455:type connect: integer, float, or None5657:param read:58The maximum amount of time (in seconds) to wait between consecutive59read operations for a response from the server. Omitting the parameter60will default the read timeout to the system default, probably `the61global default timeout in socket.py62<http://hg.python.org/cpython/file/603b4d593758/Lib/socket.py#l535>`_.63None will set an infinite timeout.6465:type read: integer, float, or None6667.. note::6869Many factors can affect the total amount of time for urllib3 to return70an HTTP response.7172For example, Python's DNS resolver does not obey the timeout specified73on the socket. Other factors that can affect total request time include74high CPU load, high swap, the program running at a low priority level,75or other behaviors.7677In addition, the read and total timeouts only measure the time between78read operations on the socket connecting the client and the server,79not the total amount of time for the request to return a complete80response. For most requests, the timeout is raised because the server81has not sent the first byte in the specified time. This is not always82the case; if a server streams one byte every fifteen seconds, a timeout83of 20 seconds will not trigger, even though the request will take84several minutes to complete.8586If your goal is to cut off any request after a set amount of wall clock87time, consider having a second "watcher" thread to cut off a slow88request.89"""9091#: A sentinel object representing the default timeout value92DEFAULT_TIMEOUT = _GLOBAL_DEFAULT_TIMEOUT9394def __init__(self, total=None, connect=_Default, read=_Default):95self._connect = self._validate_timeout(connect, "connect")96self._read = self._validate_timeout(read, "read")97self.total = self._validate_timeout(total, "total")98self._start_connect = None99100def __repr__(self):101return "%s(connect=%r, read=%r, total=%r)" % (102type(self).__name__,103self._connect,104self._read,105self.total,106)107108# __str__ provided for backwards compatibility109__str__ = __repr__110111@classmethod112def _validate_timeout(cls, value, name):113""" Check that a timeout attribute is valid.114115:param value: The timeout value to validate116:param name: The name of the timeout attribute to validate. This is117used to specify in error messages.118:return: The validated and casted version of the given value.119:raises ValueError: If it is a numeric value less than or equal to120zero, or the type is not an integer, float, or None.121"""122if value is _Default:123return cls.DEFAULT_TIMEOUT124125if value is None or value is cls.DEFAULT_TIMEOUT:126return value127128if isinstance(value, bool):129raise ValueError(130"Timeout cannot be a boolean value. It must "131"be an int, float or None."132)133try:134float(value)135except (TypeError, ValueError):136raise ValueError(137"Timeout value %s was %s, but it must be an "138"int, float or None." % (name, value)139)140141try:142if value <= 0:143raise ValueError(144"Attempted to set %s timeout to %s, but the "145"timeout cannot be set to a value less "146"than or equal to 0." % (name, value)147)148except TypeError:149# Python 3150raise ValueError(151"Timeout value %s was %s, but it must be an "152"int, float or None." % (name, value)153)154155return value156157@classmethod158def from_float(cls, timeout):159""" Create a new Timeout from a legacy timeout value.160161The timeout value used by httplib.py sets the same timeout on the162connect(), and recv() socket requests. This creates a :class:`Timeout`163object that sets the individual timeouts to the ``timeout`` value164passed to this function.165166:param timeout: The legacy timeout value.167:type timeout: integer, float, sentinel default object, or None168:return: Timeout object169:rtype: :class:`Timeout`170"""171return Timeout(read=timeout, connect=timeout)172173def clone(self):174""" Create a copy of the timeout object175176Timeout properties are stored per-pool but each request needs a fresh177Timeout object to ensure each one has its own start/stop configured.178179:return: a copy of the timeout object180:rtype: :class:`Timeout`181"""182# We can't use copy.deepcopy because that will also create a new object183# for _GLOBAL_DEFAULT_TIMEOUT, which socket.py uses as a sentinel to184# detect the user default.185return Timeout(connect=self._connect, read=self._read, total=self.total)186187def start_connect(self):188""" Start the timeout clock, used during a connect() attempt189190:raises urllib3.exceptions.TimeoutStateError: if you attempt191to start a timer that has been started already.192"""193if self._start_connect is not None:194raise TimeoutStateError("Timeout timer has already been started.")195self._start_connect = current_time()196return self._start_connect197198def get_connect_duration(self):199""" Gets the time elapsed since the call to :meth:`start_connect`.200201:return: Elapsed time in seconds.202:rtype: float203:raises urllib3.exceptions.TimeoutStateError: if you attempt204to get duration for a timer that hasn't been started.205"""206if self._start_connect is None:207raise TimeoutStateError(208"Can't get connect duration for timer that has not started."209)210return current_time() - self._start_connect211212@property213def connect_timeout(self):214""" Get the value to use when setting a connection timeout.215216This will be a positive float or integer, the value None217(never timeout), or the default system timeout.218219:return: Connect timeout.220:rtype: int, float, :attr:`Timeout.DEFAULT_TIMEOUT` or None221"""222if self.total is None:223return self._connect224225if self._connect is None or self._connect is self.DEFAULT_TIMEOUT:226return self.total227228return min(self._connect, self.total)229230@property231def read_timeout(self):232""" Get the value for the read timeout.233234This assumes some time has elapsed in the connection timeout and235computes the read timeout appropriately.236237If self.total is set, the read timeout is dependent on the amount of238time taken by the connect timeout. If the connection time has not been239established, a :exc:`~urllib3.exceptions.TimeoutStateError` will be240raised.241242:return: Value to use for the read timeout.243:rtype: int, float, :attr:`Timeout.DEFAULT_TIMEOUT` or None244:raises urllib3.exceptions.TimeoutStateError: If :meth:`start_connect`245has not yet been called on this object.246"""247if (248self.total is not None249and self.total is not self.DEFAULT_TIMEOUT250and self._read is not None251and self._read is not self.DEFAULT_TIMEOUT252):253# In case the connect timeout has not yet been established.254if self._start_connect is None:255return self._read256return max(0, min(self.total - self.get_connect_duration(), self._read))257elif self.total is not None and self.total is not self.DEFAULT_TIMEOUT:258return max(0, self.total - self.get_connect_duration())259else:260return self._read261262263