Index: third_party/google-endpoints/requests/packages/urllib3/util/timeout.py |
diff --git a/third_party/google-endpoints/requests/packages/urllib3/util/timeout.py b/third_party/google-endpoints/requests/packages/urllib3/util/timeout.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..cec817e6efa53e830cb2b5877faa42013743d5db |
--- /dev/null |
+++ b/third_party/google-endpoints/requests/packages/urllib3/util/timeout.py |
@@ -0,0 +1,242 @@ |
+from __future__ import absolute_import |
+# The default socket timeout, used by httplib to indicate that no timeout was |
+# specified by the user |
+from socket import _GLOBAL_DEFAULT_TIMEOUT |
+import time |
+ |
+from ..exceptions import TimeoutStateError |
+ |
+# A sentinel value to indicate that no timeout was specified by the user in |
+# urllib3 |
+_Default = object() |
+ |
+ |
+# Use time.monotonic if available. |
+current_time = getattr(time, "monotonic", time.time) |
+ |
+ |
+class Timeout(object): |
+ """ Timeout configuration. |
+ |
+ Timeouts can be defined as a default for a pool:: |
+ |
+ timeout = Timeout(connect=2.0, read=7.0) |
+ http = PoolManager(timeout=timeout) |
+ response = http.request('GET', 'http://example.com/') |
+ |
+ Or per-request (which overrides the default for the pool):: |
+ |
+ response = http.request('GET', 'http://example.com/', timeout=Timeout(10)) |
+ |
+ Timeouts can be disabled by setting all the parameters to ``None``:: |
+ |
+ no_timeout = Timeout(connect=None, read=None) |
+ response = http.request('GET', 'http://example.com/, timeout=no_timeout) |
+ |
+ |
+ :param total: |
+ This combines the connect and read timeouts into one; the read timeout |
+ will be set to the time leftover from the connect attempt. In the |
+ event that both a connect timeout and a total are specified, or a read |
+ timeout and a total are specified, the shorter timeout will be applied. |
+ |
+ Defaults to None. |
+ |
+ :type total: integer, float, or None |
+ |
+ :param connect: |
+ The maximum amount of time to wait for a connection attempt to a server |
+ to succeed. Omitting the parameter will default the connect timeout to |
+ the system default, probably `the global default timeout in socket.py |
+ <http://hg.python.org/cpython/file/603b4d593758/Lib/socket.py#l535>`_. |
+ None will set an infinite timeout for connection attempts. |
+ |
+ :type connect: integer, float, or None |
+ |
+ :param read: |
+ The maximum amount of time to wait between consecutive |
+ read operations for a response from the server. Omitting |
+ the parameter will default the read timeout to the system |
+ default, probably `the global default timeout in socket.py |
+ <http://hg.python.org/cpython/file/603b4d593758/Lib/socket.py#l535>`_. |
+ None will set an infinite timeout. |
+ |
+ :type read: integer, float, or None |
+ |
+ .. note:: |
+ |
+ Many factors can affect the total amount of time for urllib3 to return |
+ an HTTP response. |
+ |
+ For example, Python's DNS resolver does not obey the timeout specified |
+ on the socket. Other factors that can affect total request time include |
+ high CPU load, high swap, the program running at a low priority level, |
+ or other behaviors. |
+ |
+ In addition, the read and total timeouts only measure the time between |
+ read operations on the socket connecting the client and the server, |
+ not the total amount of time for the request to return a complete |
+ response. For most requests, the timeout is raised because the server |
+ has not sent the first byte in the specified time. This is not always |
+ the case; if a server streams one byte every fifteen seconds, a timeout |
+ of 20 seconds will not trigger, even though the request will take |
+ several minutes to complete. |
+ |
+ If your goal is to cut off any request after a set amount of wall clock |
+ time, consider having a second "watcher" thread to cut off a slow |
+ request. |
+ """ |
+ |
+ #: A sentinel object representing the default timeout value |
+ DEFAULT_TIMEOUT = _GLOBAL_DEFAULT_TIMEOUT |
+ |
+ def __init__(self, total=None, connect=_Default, read=_Default): |
+ self._connect = self._validate_timeout(connect, 'connect') |
+ self._read = self._validate_timeout(read, 'read') |
+ self.total = self._validate_timeout(total, 'total') |
+ self._start_connect = None |
+ |
+ def __str__(self): |
+ return '%s(connect=%r, read=%r, total=%r)' % ( |
+ type(self).__name__, self._connect, self._read, self.total) |
+ |
+ @classmethod |
+ def _validate_timeout(cls, value, name): |
+ """ Check that a timeout attribute is valid. |
+ |
+ :param value: The timeout value to validate |
+ :param name: The name of the timeout attribute to validate. This is |
+ used to specify in error messages. |
+ :return: The validated and casted version of the given value. |
+ :raises ValueError: If it is a numeric value less than or equal to |
+ zero, or the type is not an integer, float, or None. |
+ """ |
+ if value is _Default: |
+ return cls.DEFAULT_TIMEOUT |
+ |
+ if value is None or value is cls.DEFAULT_TIMEOUT: |
+ return value |
+ |
+ if isinstance(value, bool): |
+ raise ValueError("Timeout cannot be a boolean value. It must " |
+ "be an int, float or None.") |
+ try: |
+ float(value) |
+ except (TypeError, ValueError): |
+ raise ValueError("Timeout value %s was %s, but it must be an " |
+ "int, float or None." % (name, value)) |
+ |
+ try: |
+ if value <= 0: |
+ raise ValueError("Attempted to set %s timeout to %s, but the " |
+ "timeout cannot be set to a value less " |
+ "than or equal to 0." % (name, value)) |
+ except TypeError: # Python 3 |
+ raise ValueError("Timeout value %s was %s, but it must be an " |
+ "int, float or None." % (name, value)) |
+ |
+ return value |
+ |
+ @classmethod |
+ def from_float(cls, timeout): |
+ """ Create a new Timeout from a legacy timeout value. |
+ |
+ The timeout value used by httplib.py sets the same timeout on the |
+ connect(), and recv() socket requests. This creates a :class:`Timeout` |
+ object that sets the individual timeouts to the ``timeout`` value |
+ passed to this function. |
+ |
+ :param timeout: The legacy timeout value. |
+ :type timeout: integer, float, sentinel default object, or None |
+ :return: Timeout object |
+ :rtype: :class:`Timeout` |
+ """ |
+ return Timeout(read=timeout, connect=timeout) |
+ |
+ def clone(self): |
+ """ Create a copy of the timeout object |
+ |
+ Timeout properties are stored per-pool but each request needs a fresh |
+ Timeout object to ensure each one has its own start/stop configured. |
+ |
+ :return: a copy of the timeout object |
+ :rtype: :class:`Timeout` |
+ """ |
+ # We can't use copy.deepcopy because that will also create a new object |
+ # for _GLOBAL_DEFAULT_TIMEOUT, which socket.py uses as a sentinel to |
+ # detect the user default. |
+ return Timeout(connect=self._connect, read=self._read, |
+ total=self.total) |
+ |
+ def start_connect(self): |
+ """ Start the timeout clock, used during a connect() attempt |
+ |
+ :raises urllib3.exceptions.TimeoutStateError: if you attempt |
+ to start a timer that has been started already. |
+ """ |
+ if self._start_connect is not None: |
+ raise TimeoutStateError("Timeout timer has already been started.") |
+ self._start_connect = current_time() |
+ return self._start_connect |
+ |
+ def get_connect_duration(self): |
+ """ Gets the time elapsed since the call to :meth:`start_connect`. |
+ |
+ :return: Elapsed time. |
+ :rtype: float |
+ :raises urllib3.exceptions.TimeoutStateError: if you attempt |
+ to get duration for a timer that hasn't been started. |
+ """ |
+ if self._start_connect is None: |
+ raise TimeoutStateError("Can't get connect duration for timer " |
+ "that has not started.") |
+ return current_time() - self._start_connect |
+ |
+ @property |
+ def connect_timeout(self): |
+ """ Get the value to use when setting a connection timeout. |
+ |
+ This will be a positive float or integer, the value None |
+ (never timeout), or the default system timeout. |
+ |
+ :return: Connect timeout. |
+ :rtype: int, float, :attr:`Timeout.DEFAULT_TIMEOUT` or None |
+ """ |
+ if self.total is None: |
+ return self._connect |
+ |
+ if self._connect is None or self._connect is self.DEFAULT_TIMEOUT: |
+ return self.total |
+ |
+ return min(self._connect, self.total) |
+ |
+ @property |
+ def read_timeout(self): |
+ """ Get the value for the read timeout. |
+ |
+ This assumes some time has elapsed in the connection timeout and |
+ computes the read timeout appropriately. |
+ |
+ If self.total is set, the read timeout is dependent on the amount of |
+ time taken by the connect timeout. If the connection time has not been |
+ established, a :exc:`~urllib3.exceptions.TimeoutStateError` will be |
+ raised. |
+ |
+ :return: Value to use for the read timeout. |
+ :rtype: int, float, :attr:`Timeout.DEFAULT_TIMEOUT` or None |
+ :raises urllib3.exceptions.TimeoutStateError: If :meth:`start_connect` |
+ has not yet been called on this object. |
+ """ |
+ if (self.total is not None and |
+ self.total is not self.DEFAULT_TIMEOUT and |
+ self._read is not None and |
+ self._read is not self.DEFAULT_TIMEOUT): |
+ # In case the connect timeout has not yet been established. |
+ if self._start_connect is None: |
+ return self._read |
+ return max(0, min(self.total - self.get_connect_duration(), |
+ self._read)) |
+ elif self.total is not None and self.total is not self.DEFAULT_TIMEOUT: |
+ return max(0, self.total - self.get_connect_duration()) |
+ else: |
+ return self._read |