aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/requests_toolbelt/adapters/socket_options.py
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/requests_toolbelt/adapters/socket_options.py')
-rw-r--r--.venv/lib/python3.12/site-packages/requests_toolbelt/adapters/socket_options.py129
1 files changed, 129 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/requests_toolbelt/adapters/socket_options.py b/.venv/lib/python3.12/site-packages/requests_toolbelt/adapters/socket_options.py
new file mode 100644
index 00000000..86ebe136
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/requests_toolbelt/adapters/socket_options.py
@@ -0,0 +1,129 @@
+# -*- coding: utf-8 -*-
+"""The implementation of the SocketOptionsAdapter."""
+import socket
+import warnings
+import sys
+
+import requests
+from requests import adapters
+
+from .._compat import connection
+from .._compat import poolmanager
+from .. import exceptions as exc
+
+
+class SocketOptionsAdapter(adapters.HTTPAdapter):
+ """An adapter for requests that allows users to specify socket options.
+
+ Since version 2.4.0 of requests, it is possible to specify a custom list
+ of socket options that need to be set before establishing the connection.
+
+ Example usage::
+
+ >>> import socket
+ >>> import requests
+ >>> from requests_toolbelt.adapters import socket_options
+ >>> s = requests.Session()
+ >>> opts = [(socket.IPPROTO_TCP, socket.TCP_NODELAY, 0)]
+ >>> adapter = socket_options.SocketOptionsAdapter(socket_options=opts)
+ >>> s.mount('http://', adapter)
+
+ You can also take advantage of the list of default options on this class
+ to keep using the original options in addition to your custom options. In
+ that case, ``opts`` might look like::
+
+ >>> opts = socket_options.SocketOptionsAdapter.default_options + opts
+
+ """
+
+ if connection is not None:
+ default_options = getattr(
+ connection.HTTPConnection,
+ 'default_socket_options',
+ [(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)]
+ )
+ else:
+ default_options = []
+ warnings.warn(exc.RequestsVersionTooOld,
+ "This version of Requests is only compatible with a "
+ "version of urllib3 which is too old to support "
+ "setting options on a socket. This adapter is "
+ "functionally useless.")
+
+ def __init__(self, **kwargs):
+ self.socket_options = kwargs.pop('socket_options',
+ self.default_options)
+
+ super(SocketOptionsAdapter, self).__init__(**kwargs)
+
+ def init_poolmanager(self, connections, maxsize, block=False):
+ if requests.__build__ >= 0x020400:
+ # NOTE(Ian): Perhaps we should raise a warning
+ self.poolmanager = poolmanager.PoolManager(
+ num_pools=connections,
+ maxsize=maxsize,
+ block=block,
+ socket_options=self.socket_options
+ )
+ else:
+ super(SocketOptionsAdapter, self).init_poolmanager(
+ connections, maxsize, block
+ )
+
+
+class TCPKeepAliveAdapter(SocketOptionsAdapter):
+ """An adapter for requests that turns on TCP Keep-Alive by default.
+
+ The adapter sets 4 socket options:
+
+ - ``SOL_SOCKET`` ``SO_KEEPALIVE`` - This turns on TCP Keep-Alive
+ - ``IPPROTO_TCP`` ``TCP_KEEPINTVL`` 20 - Sets the keep alive interval
+ - ``IPPROTO_TCP`` ``TCP_KEEPCNT`` 5 - Sets the number of keep alive probes
+ - ``IPPROTO_TCP`` ``TCP_KEEPIDLE`` 60 - Sets the keep alive time if the
+ socket library has the ``TCP_KEEPIDLE`` constant
+
+ The latter three can be overridden by keyword arguments (respectively):
+
+ - ``interval``
+ - ``count``
+ - ``idle``
+
+ You can use this adapter like so::
+
+ >>> from requests_toolbelt.adapters import socket_options
+ >>> tcp = socket_options.TCPKeepAliveAdapter(idle=120, interval=10)
+ >>> s = requests.Session()
+ >>> s.mount('http://', tcp)
+
+ """
+
+ def __init__(self, **kwargs):
+ socket_options = kwargs.pop('socket_options',
+ SocketOptionsAdapter.default_options)
+ idle = kwargs.pop('idle', 60)
+ interval = kwargs.pop('interval', 20)
+ count = kwargs.pop('count', 5)
+ socket_options = socket_options + [
+ (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
+ ]
+
+ # NOTE(Ian): OSX does not have these constants defined, so we
+ # set them conditionally.
+ if getattr(socket, 'TCP_KEEPINTVL', None) is not None:
+ socket_options += [(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL,
+ interval)]
+ elif sys.platform == 'darwin':
+ # On OSX, TCP_KEEPALIVE from netinet/tcp.h is not exported
+ # by python's socket module
+ TCP_KEEPALIVE = getattr(socket, 'TCP_KEEPALIVE', 0x10)
+ socket_options += [(socket.IPPROTO_TCP, TCP_KEEPALIVE, interval)]
+
+ if getattr(socket, 'TCP_KEEPCNT', None) is not None:
+ socket_options += [(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, count)]
+
+ if getattr(socket, 'TCP_KEEPIDLE', None) is not None:
+ socket_options += [(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, idle)]
+
+ super(TCPKeepAliveAdapter, self).__init__(
+ socket_options=socket_options, **kwargs
+ )