diff options
| author | robot-piglet <[email protected]> | 2025-05-14 14:52:53 +0300 |
|---|---|---|
| committer | robot-piglet <[email protected]> | 2025-05-14 15:02:43 +0300 |
| commit | 0b8daea4ea00e541685569c84670115ed35ed8ac (patch) | |
| tree | aa33afd23f9831fc1c57b34f81fdf02def663d23 /contrib/python | |
| parent | 1565ceee67746697db75e898d9f6ebb51232bc5f (diff) | |
Intermediate changes
commit_hash:c71c347c3e639c8b11c86cd2f11082a2e1805123
Diffstat (limited to 'contrib/python')
13 files changed, 321 insertions, 37 deletions
diff --git a/contrib/python/urllib3/py2/.dist-info/METADATA b/contrib/python/urllib3/py2/.dist-info/METADATA index 5d2a438fa11..0f21c233a89 100644 --- a/contrib/python/urllib3/py2/.dist-info/METADATA +++ b/contrib/python/urllib3/py2/.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: urllib3 -Version: 1.26.15 +Version: 1.26.20 Summary: HTTP library with thread-safe connection pooling, file post, and more. Home-page: https://urllib3.readthedocs.io/ Author: Andrey Petrov @@ -24,6 +24,8 @@ Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Topic :: Internet :: WWW/HTTP @@ -32,18 +34,19 @@ Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.* Description-Content-Type: text/x-rst License-File: LICENSE.txt Provides-Extra: brotli -Requires-Dist: brotlicffi (>=0.8.0) ; ((os_name != "nt" or python_version >= "3") and platform_python_implementation != "CPython") and extra == 'brotli' -Requires-Dist: brotli (>=1.0.9) ; ((os_name != "nt" or python_version >= "3") and platform_python_implementation == "CPython") and extra == 'brotli' -Requires-Dist: brotlipy (>=0.6.0) ; (os_name == "nt" and python_version < "3") and extra == 'brotli' +Requires-Dist: brotlicffi>=0.8.0; ((os_name != "nt" or python_version >= "3") and platform_python_implementation != "CPython") and extra == "brotli" +Requires-Dist: brotli==1.0.9; (os_name != "nt" and python_version < "3" and platform_python_implementation == "CPython") and extra == "brotli" +Requires-Dist: brotlipy>=0.6.0; (os_name == "nt" and python_version < "3") and extra == "brotli" +Requires-Dist: brotli>=1.0.9; (python_version >= "3" and platform_python_implementation == "CPython") and extra == "brotli" Provides-Extra: secure -Requires-Dist: pyOpenSSL (>=0.14) ; extra == 'secure' -Requires-Dist: cryptography (>=1.3.4) ; extra == 'secure' -Requires-Dist: idna (>=2.0.0) ; extra == 'secure' -Requires-Dist: certifi ; extra == 'secure' -Requires-Dist: urllib3-secure-extra ; extra == 'secure' -Requires-Dist: ipaddress ; (python_version == "2.7") and extra == 'secure' +Requires-Dist: pyOpenSSL>=0.14; extra == "secure" +Requires-Dist: cryptography>=1.3.4; extra == "secure" +Requires-Dist: idna>=2.0.0; extra == "secure" +Requires-Dist: certifi; extra == "secure" +Requires-Dist: urllib3-secure-extra; extra == "secure" +Requires-Dist: ipaddress; python_version == "2.7" and extra == "secure" Provides-Extra: socks -Requires-Dist: PySocks (!=1.5.7,<2.0,>=1.5.6) ; extra == 'socks' +Requires-Dist: PySocks!=1.5.7,<2.0,>=1.5.6; extra == "socks" urllib3 is a powerful, *user-friendly* HTTP client for Python. Much of the @@ -154,6 +157,48 @@ For Enterprise Changes ======= +1.26.20 (2024-08-29) +-------------------- + +* Fixed a crash where certain standard library hash functions were absent in + FIPS-compliant environments. + (`#3432 <https://github.com/urllib3/urllib3/issues/3432>`__) +* Replaced deprecated dash-separated setuptools entries in ``setup.cfg``. + (`#3461 <https://github.com/urllib3/urllib3/pull/3461>`__) +* Took into account macOS setting ``ECONNRESET`` instead of ``EPROTOTYPE`` in + its newer versions. + (`#3416 <https://github.com/urllib3/urllib3/pull/3416>`__) +* Backported changes to our tests and CI configuration from v2.x to support + testing with CPython 3.12 and 3.13. + (`#3436 <https://github.com/urllib3/urllib3/pull/3436>`__) + + +1.26.19 (2024-06-17) +-------------------- + +* Added the ``Proxy-Authorization`` header to the list of headers to strip from requests when redirecting to a different host. As before, different headers can be set via ``Retry.remove_headers_on_redirect``. +* Fixed handling of OpenSSL 3.2.0 new error message for misconfiguring an HTTP proxy as HTTPS. (`#3405 <https://github.com/urllib3/urllib3/issues/3405>`__) + + +1.26.18 (2023-10-17) +-------------------- + +* Made body stripped from HTTP requests changing the request method to GET after HTTP 303 "See Other" redirect responses. + + +1.26.17 (2023-10-02) +-------------------- + +* Added the ``Cookie`` header to the list of headers to strip from requests when redirecting to a different host. As before, different headers can be set via ``Retry.remove_headers_on_redirect``. + + +1.26.16 (2023-05-23) +-------------------- + +* Fixed thread-safety issue where accessing a ``PoolManager`` with many distinct origins + would cause connection pools to be closed while requests are in progress (`#2954 <https://github.com/urllib3/urllib3/pull/2954>`_) + + 1.26.15 (2023-03-10) -------------------- @@ -307,7 +352,7 @@ Changes * Added default ``User-Agent`` header to every request (Pull #1750) -* Added ``urllib3.util.SKIP_HEADER`` for skipping ``User-Agent``, ``Accept-Encoding``, +* Added ``urllib3.util.SKIP_HEADER`` for skipping ``User-Agent``, ``Accept-Encoding``, and ``Host`` headers from being automatically emitted with requests (Pull #2018) * Collapse ``transfer-encoding: chunked`` request data and framing into diff --git a/contrib/python/urllib3/py2/.yandex_meta/yamaker.yaml b/contrib/python/urllib3/py2/.yandex_meta/yamaker.yaml index 4141ecf8796..39372c0910e 100644 --- a/contrib/python/urllib3/py2/.yandex_meta/yamaker.yaml +++ b/contrib/python/urllib3/py2/.yandex_meta/yamaker.yaml @@ -3,4 +3,3 @@ exclude_from_macros: - urllib3/contrib/ntlmpool.py - urllib3/contrib/pyopenssl.py - urllib3/contrib/securetransport.py - - urllib3/packages/backports/*.py diff --git a/contrib/python/urllib3/py2/urllib3/_collections.py b/contrib/python/urllib3/py2/urllib3/_collections.py index da9857e986d..bceb8451f0e 100644 --- a/contrib/python/urllib3/py2/urllib3/_collections.py +++ b/contrib/python/urllib3/py2/urllib3/_collections.py @@ -268,6 +268,24 @@ class HTTPHeaderDict(MutableMapping): else: return vals[1:] + def _prepare_for_method_change(self): + """ + Remove content-specific header fields before changing the request + method to GET or HEAD according to RFC 9110, Section 15.4. + """ + content_specific_headers = [ + "Content-Encoding", + "Content-Language", + "Content-Location", + "Content-Type", + "Content-Length", + "Digest", + "Last-Modified", + ] + for header in content_specific_headers: + self.discard(header) + return self + # Backwards compatibility for httplib getheaders = getlist getallmatchingheaders = getlist diff --git a/contrib/python/urllib3/py2/urllib3/_version.py b/contrib/python/urllib3/py2/urllib3/_version.py index e12dd0e7853..d49df2a0c54 100644 --- a/contrib/python/urllib3/py2/urllib3/_version.py +++ b/contrib/python/urllib3/py2/urllib3/_version.py @@ -1,2 +1,2 @@ # This file is protected via CODEOWNERS -__version__ = "1.26.15" +__version__ = "1.26.20" diff --git a/contrib/python/urllib3/py2/urllib3/connection.py b/contrib/python/urllib3/py2/urllib3/connection.py index d8b1f61a550..112a6228db2 100644 --- a/contrib/python/urllib3/py2/urllib3/connection.py +++ b/contrib/python/urllib3/py2/urllib3/connection.py @@ -68,7 +68,7 @@ port_by_scheme = {"http": 80, "https": 443} # When it comes time to update this value as a part of regular maintenance # (ie test_recent_date is failing) update it to ~6 months before the current date. -RECENT_DATE = datetime.date(2022, 1, 1) +RECENT_DATE = datetime.date(2024, 1, 1) _CONTAINS_CONTROL_CHAR_RE = re.compile(r"[^-!#$%&'*+.^_`|~0-9a-zA-Z]") @@ -438,7 +438,7 @@ class HTTPSConnection(HTTPConnection): and self.ssl_version is None and hasattr(self.sock, "version") and self.sock.version() in {"TLSv1", "TLSv1.1"} - ): + ): # Defensive: warnings.warn( "Negotiating TLSv1/TLSv1.1 by default is deprecated " "and will be disabled in urllib3 v2.0.0. Connecting to " diff --git a/contrib/python/urllib3/py2/urllib3/connectionpool.py b/contrib/python/urllib3/py2/urllib3/connectionpool.py index c23d736b186..0872ed77011 100644 --- a/contrib/python/urllib3/py2/urllib3/connectionpool.py +++ b/contrib/python/urllib3/py2/urllib3/connectionpool.py @@ -9,6 +9,7 @@ import warnings from socket import error as SocketError from socket import timeout as SocketTimeout +from ._collections import HTTPHeaderDict from .connection import ( BaseSSLError, BrokenPipeError, @@ -50,6 +51,13 @@ from .util.url import Url, _encode_target from .util.url import _normalize_host as normalize_host from .util.url import get_host, parse_url +try: # Platform-specific: Python 3 + import weakref + + weakref_finalize = weakref.finalize +except AttributeError: # Platform-specific: Python 2 + from .packages.backports.weakref_finalize import weakref_finalize + xrange = six.moves.xrange log = logging.getLogger(__name__) @@ -220,6 +228,16 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods): self.conn_kw["proxy"] = self.proxy self.conn_kw["proxy_config"] = self.proxy_config + # Do not pass 'self' as callback to 'finalize'. + # Then the 'finalize' would keep an endless living (leak) to self. + # By just passing a reference to the pool allows the garbage collector + # to free self if nobody else has a reference to it. + pool = self.pool + + # Close all the HTTPConnections in the pool before the + # HTTPConnectionPool object is garbage collected. + weakref_finalize(self, _close_pool_connections, pool) + def _new_conn(self): """ Return a fresh :class:`HTTPConnection`. @@ -405,12 +423,13 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods): pass except IOError as e: # Python 2 and macOS/Linux - # EPIPE and ESHUTDOWN are BrokenPipeError on Python 2, and EPROTOTYPE is needed on macOS + # EPIPE and ESHUTDOWN are BrokenPipeError on Python 2, and EPROTOTYPE/ECONNRESET are needed on macOS # https://erickt.github.io/blog/2014/11/19/adventures-in-debugging-a-potential-osx-kernel-bug/ if e.errno not in { errno.EPIPE, errno.ESHUTDOWN, errno.EPROTOTYPE, + errno.ECONNRESET, }: raise @@ -489,14 +508,8 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods): # Disable access to the pool old_pool, self.pool = self.pool, None - try: - while True: - conn = old_pool.get(block=False) - if conn: - conn.close() - - except queue.Empty: - pass # Done. + # Close all the HTTPConnections in the pool. + _close_pool_connections(old_pool) def is_same_host(self, url): """ @@ -756,7 +769,9 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods): # so we try to cover our bases here! message = " ".join(re.split("[^a-z]", str(ssl_error).lower())) return ( - "wrong version number" in message or "unknown protocol" in message + "wrong version number" in message + or "unknown protocol" in message + or "record layer failure" in message ) # Try to detect a common user error with proxies which is to @@ -832,7 +847,11 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods): redirect_location = redirect and response.get_redirect_location() if redirect_location: if response.status == 303: + # Change the method according to RFC 9110, Section 15.4.4. method = "GET" + # And lose the body not to transfer anything sensitive. + body = None + headers = HTTPHeaderDict(headers)._prepare_for_method_change() try: retries = retries.increment(method, url, response=response, _pool=self) @@ -1108,3 +1127,14 @@ def _normalize_host(host, scheme): if host.startswith("[") and host.endswith("]"): host = host[1:-1] return host + + +def _close_pool_connections(pool): + """Drains a queue of connections and closes each one.""" + try: + while True: + conn = pool.get(block=False) + if conn: + conn.close() + except queue.Empty: + pass # Done. diff --git a/contrib/python/urllib3/py2/urllib3/contrib/securetransport.py b/contrib/python/urllib3/py2/urllib3/contrib/securetransport.py index 6c46a3b9f03..e311c0c899a 100644 --- a/contrib/python/urllib3/py2/urllib3/contrib/securetransport.py +++ b/contrib/python/urllib3/py2/urllib3/contrib/securetransport.py @@ -64,9 +64,8 @@ import struct import threading import weakref -import six - from .. import util +from ..packages import six from ..util.ssl_ import PROTOCOL_TLS_CLIENT from ._securetransport.bindings import CoreFoundation, Security, SecurityConst from ._securetransport.low_level import ( diff --git a/contrib/python/urllib3/py2/urllib3/packages/backports/weakref_finalize.py b/contrib/python/urllib3/py2/urllib3/packages/backports/weakref_finalize.py new file mode 100644 index 00000000000..a2f2966e549 --- /dev/null +++ b/contrib/python/urllib3/py2/urllib3/packages/backports/weakref_finalize.py @@ -0,0 +1,155 @@ +# -*- coding: utf-8 -*- +""" +backports.weakref_finalize +~~~~~~~~~~~~~~~~~~ + +Backports the Python 3 ``weakref.finalize`` method. +""" +from __future__ import absolute_import + +import itertools +import sys +from weakref import ref + +__all__ = ["weakref_finalize"] + + +class weakref_finalize(object): + """Class for finalization of weakrefable objects + finalize(obj, func, *args, **kwargs) returns a callable finalizer + object which will be called when obj is garbage collected. The + first time the finalizer is called it evaluates func(*arg, **kwargs) + and returns the result. After this the finalizer is dead, and + calling it just returns None. + When the program exits any remaining finalizers for which the + atexit attribute is true will be run in reverse order of creation. + By default atexit is true. + """ + + # Finalizer objects don't have any state of their own. They are + # just used as keys to lookup _Info objects in the registry. This + # ensures that they cannot be part of a ref-cycle. + + __slots__ = () + _registry = {} + _shutdown = False + _index_iter = itertools.count() + _dirty = False + _registered_with_atexit = False + + class _Info(object): + __slots__ = ("weakref", "func", "args", "kwargs", "atexit", "index") + + def __init__(self, obj, func, *args, **kwargs): + if not self._registered_with_atexit: + # We may register the exit function more than once because + # of a thread race, but that is harmless + import atexit + + atexit.register(self._exitfunc) + weakref_finalize._registered_with_atexit = True + info = self._Info() + info.weakref = ref(obj, self) + info.func = func + info.args = args + info.kwargs = kwargs or None + info.atexit = True + info.index = next(self._index_iter) + self._registry[self] = info + weakref_finalize._dirty = True + + def __call__(self, _=None): + """If alive then mark as dead and return func(*args, **kwargs); + otherwise return None""" + info = self._registry.pop(self, None) + if info and not self._shutdown: + return info.func(*info.args, **(info.kwargs or {})) + + def detach(self): + """If alive then mark as dead and return (obj, func, args, kwargs); + otherwise return None""" + info = self._registry.get(self) + obj = info and info.weakref() + if obj is not None and self._registry.pop(self, None): + return (obj, info.func, info.args, info.kwargs or {}) + + def peek(self): + """If alive then return (obj, func, args, kwargs); + otherwise return None""" + info = self._registry.get(self) + obj = info and info.weakref() + if obj is not None: + return (obj, info.func, info.args, info.kwargs or {}) + + @property + def alive(self): + """Whether finalizer is alive""" + return self in self._registry + + @property + def atexit(self): + """Whether finalizer should be called at exit""" + info = self._registry.get(self) + return bool(info) and info.atexit + + @atexit.setter + def atexit(self, value): + info = self._registry.get(self) + if info: + info.atexit = bool(value) + + def __repr__(self): + info = self._registry.get(self) + obj = info and info.weakref() + if obj is None: + return "<%s object at %#x; dead>" % (type(self).__name__, id(self)) + else: + return "<%s object at %#x; for %r at %#x>" % ( + type(self).__name__, + id(self), + type(obj).__name__, + id(obj), + ) + + @classmethod + def _select_for_exit(cls): + # Return live finalizers marked for exit, oldest first + L = [(f, i) for (f, i) in cls._registry.items() if i.atexit] + L.sort(key=lambda item: item[1].index) + return [f for (f, i) in L] + + @classmethod + def _exitfunc(cls): + # At shutdown invoke finalizers for which atexit is true. + # This is called once all other non-daemonic threads have been + # joined. + reenable_gc = False + try: + if cls._registry: + import gc + + if gc.isenabled(): + reenable_gc = True + gc.disable() + pending = None + while True: + if pending is None or weakref_finalize._dirty: + pending = cls._select_for_exit() + weakref_finalize._dirty = False + if not pending: + break + f = pending.pop() + try: + # gc is disabled, so (assuming no daemonic + # threads) the following is the only line in + # this function which might trigger creation + # of a new finalizer + f() + except Exception: + sys.excepthook(*sys.exc_info()) + assert f not in cls._registry + finally: + # prevent any more finalizers from executing during shutdown + weakref_finalize._shutdown = True + if reenable_gc: + gc.enable() diff --git a/contrib/python/urllib3/py2/urllib3/poolmanager.py b/contrib/python/urllib3/py2/urllib3/poolmanager.py index ca4ec341184..fb51bf7d96b 100644 --- a/contrib/python/urllib3/py2/urllib3/poolmanager.py +++ b/contrib/python/urllib3/py2/urllib3/poolmanager.py @@ -4,7 +4,7 @@ import collections import functools import logging -from ._collections import RecentlyUsedContainer +from ._collections import HTTPHeaderDict, RecentlyUsedContainer from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool, port_by_scheme from .exceptions import ( LocationValueError, @@ -171,7 +171,7 @@ class PoolManager(RequestMethods): def __init__(self, num_pools=10, headers=None, **connection_pool_kw): RequestMethods.__init__(self, headers) self.connection_pool_kw = connection_pool_kw - self.pools = RecentlyUsedContainer(num_pools, dispose_func=lambda p: p.close()) + self.pools = RecentlyUsedContainer(num_pools) # Locally set the pool classes and keys so other PoolManagers can # override them. @@ -382,9 +382,12 @@ class PoolManager(RequestMethods): # Support relative URLs for redirecting. redirect_location = urljoin(url, redirect_location) - # RFC 7231, Section 6.4.4 if response.status == 303: + # Change the method according to RFC 9110, Section 15.4.4. method = "GET" + # And lose the body not to transfer anything sensitive. + kw["body"] = None + kw["headers"] = HTTPHeaderDict(kw["headers"])._prepare_for_method_change() retries = kw.get("retries") if not isinstance(retries, Retry): diff --git a/contrib/python/urllib3/py2/urllib3/request.py b/contrib/python/urllib3/py2/urllib3/request.py index 398386a5b9f..3b4cf999225 100644 --- a/contrib/python/urllib3/py2/urllib3/request.py +++ b/contrib/python/urllib3/py2/urllib3/request.py @@ -1,6 +1,9 @@ from __future__ import absolute_import +import sys + from .filepost import encode_multipart_formdata +from .packages import six from .packages.six.moves.urllib.parse import urlencode __all__ = ["RequestMethods"] @@ -168,3 +171,21 @@ class RequestMethods(object): extra_kw.update(urlopen_kw) return self.urlopen(method, url, **extra_kw) + + +if not six.PY2: + + class RequestModule(sys.modules[__name__].__class__): + def __call__(self, *args, **kwargs): + """ + If user tries to call this module directly urllib3 v2.x style raise an error to the user + suggesting they may need urllib3 v2 + """ + raise TypeError( + "'module' object is not callable\n" + "urllib3.request() method is not supported in this release, " + "upgrade to urllib3 v2 to use it\n" + "see https://urllib3.readthedocs.io/en/stable/v2-migration-guide.html" + ) + + sys.modules[__name__].__class__ = RequestModule diff --git a/contrib/python/urllib3/py2/urllib3/util/retry.py b/contrib/python/urllib3/py2/urllib3/util/retry.py index 2490d5e5b63..9a1e90d0b23 100644 --- a/contrib/python/urllib3/py2/urllib3/util/retry.py +++ b/contrib/python/urllib3/py2/urllib3/util/retry.py @@ -235,7 +235,9 @@ class Retry(object): RETRY_AFTER_STATUS_CODES = frozenset([413, 429, 503]) #: Default headers to be used for ``remove_headers_on_redirect`` - DEFAULT_REMOVE_HEADERS_ON_REDIRECT = frozenset(["Authorization"]) + DEFAULT_REMOVE_HEADERS_ON_REDIRECT = frozenset( + ["Cookie", "Authorization", "Proxy-Authorization"] + ) #: Maximum backoff time. DEFAULT_BACKOFF_MAX = 120 diff --git a/contrib/python/urllib3/py2/urllib3/util/ssl_.py b/contrib/python/urllib3/py2/urllib3/util/ssl_.py index 8f867812a5e..f26809c766a 100644 --- a/contrib/python/urllib3/py2/urllib3/util/ssl_.py +++ b/contrib/python/urllib3/py2/urllib3/util/ssl_.py @@ -1,11 +1,11 @@ from __future__ import absolute_import +import hashlib import hmac import os import sys import warnings from binascii import hexlify, unhexlify -from hashlib import md5, sha1, sha256 from ..exceptions import ( InsecurePlatformWarning, @@ -24,7 +24,10 @@ IS_SECURETRANSPORT = False ALPN_PROTOCOLS = ["http/1.1"] # Maps the length of a digest to a possible hash function producing this digest -HASHFUNC_MAP = {32: md5, 40: sha1, 64: sha256} +HASHFUNC_MAP = { + length: getattr(hashlib, algorithm, None) + for length, algorithm in ((32, "md5"), (40, "sha1"), (64, "sha256")) +} def _const_compare_digest_backport(a, b): @@ -191,9 +194,15 @@ def assert_fingerprint(cert, fingerprint): fingerprint = fingerprint.replace(":", "").lower() digest_length = len(fingerprint) - hashfunc = HASHFUNC_MAP.get(digest_length) - if not hashfunc: + if digest_length not in HASHFUNC_MAP: raise SSLError("Fingerprint of invalid length: {0}".format(fingerprint)) + hashfunc = HASHFUNC_MAP.get(digest_length) + if hashfunc is None: + raise SSLError( + "Hash function implementation unavailable for fingerprint length: {0}".format( + digest_length + ) + ) # We need encode() here for py32; works on py2 and p33. fingerprint_bytes = unhexlify(fingerprint.encode()) diff --git a/contrib/python/urllib3/py2/ya.make b/contrib/python/urllib3/py2/ya.make index 5261a4c9edf..535ed1656f9 100644 --- a/contrib/python/urllib3/py2/ya.make +++ b/contrib/python/urllib3/py2/ya.make @@ -2,7 +2,7 @@ PY2_LIBRARY() -VERSION(1.26.15) +VERSION(1.26.20) LICENSE(MIT) @@ -28,6 +28,9 @@ PY_SRCS( urllib3/fields.py urllib3/filepost.py urllib3/packages/__init__.py + urllib3/packages/backports/__init__.py + urllib3/packages/backports/makefile.py + urllib3/packages/backports/weakref_finalize.py urllib3/packages/six.py urllib3/poolmanager.py urllib3/request.py |
