Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-urllib3_1 for
openSUSE:Factory checked in at 2023-05-25 23:52:08
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-urllib3_1 (Old)
and /work/SRC/openSUSE:Factory/.python-urllib3_1.new.1533 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-urllib3_1"
Thu May 25 23:52:08 2023 rev:3 rq:1088727 version:1.26.16
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-urllib3_1/python-urllib3_1.changes
2023-05-23 14:53:34.642140196 +0200
+++
/work/SRC/openSUSE:Factory/.python-urllib3_1.new.1533/python-urllib3_1.changes
2023-05-25 23:52:12.923497797 +0200
@@ -1,0 +2,9 @@
+Tue May 23 20:02:08 UTC 2023 - Dirk Müller <[email protected]>
+
+- update to 1.26.16:
+ * Fixed thread-safety issue where accessing a ``PoolManager``
+ with many distinct origins would cause connection pools to
+ be closed while requests are in progress
+- drop support-fixed-ssl-shared_ciphers.patch (obsolete)
+
+-------------------------------------------------------------------
Old:
----
support-fixed-ssl-shared_ciphers.patch
urllib3-1.26.15.tar.gz
New:
----
urllib3-1.26.16.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-urllib3_1.spec ++++++
--- /var/tmp/diff_new_pack.ZN1Gwg/_old 2023-05-25 23:52:13.435500803 +0200
+++ /var/tmp/diff_new_pack.ZN1Gwg/_new 2023-05-25 23:52:13.439500827 +0200
@@ -26,7 +26,7 @@
%endif
%{?sle15_python_module_pythons}
Name: python-urllib3_1%{psuffix}
-Version: 1.26.15
+Version: 1.26.16
Release: 0
Summary: HTTP library with thread-safe connection pooling, file post,
and more
License: MIT
@@ -36,8 +36,6 @@
# PATCH-FIX-UPSTREAM remove_mock.patch gh#urllib3/urllib3#2108 [email protected]
# remove dependency on the external module mock
Patch0: remove_mock.patch
-# PATCH-FIX-OPENSUSE New Python versions fixed behaviour of ssl.shared_ciphers
-Patch1: support-fixed-ssl-shared_ciphers.patch
BuildRequires: %{python_module base >= 3.7}
BuildRequires: %{python_module setuptools}
BuildRequires: %{python_module six}
++++++ remove_mock.patch ++++++
--- /var/tmp/diff_new_pack.ZN1Gwg/_old 2023-05-25 23:52:13.483501085 +0200
+++ /var/tmp/diff_new_pack.ZN1Gwg/_new 2023-05-25 23:52:13.487501108 +0200
@@ -1,7 +1,7 @@
-Index: urllib3-1.26.10/docs/conf.py
+Index: urllib3-1.26.16/docs/conf.py
===================================================================
---- urllib3-1.26.10.orig/docs/conf.py
-+++ urllib3-1.26.10/docs/conf.py
+--- urllib3-1.26.16.orig/docs/conf.py
++++ urllib3-1.26.16/docs/conf.py
@@ -14,7 +14,10 @@ sys.path.insert(0, root_path)
# Mock some expensive/platform-specific modules so build will work.
# (https://read-the-docs.readthedocs.io/en/latest/faq.html#\
@@ -14,10 +14,10 @@
class MockModule(mock.Mock):
-Index: urllib3-1.26.10/test/contrib/test_pyopenssl.py
+Index: urllib3-1.26.16/test/contrib/test_pyopenssl.py
===================================================================
---- urllib3-1.26.10.orig/test/contrib/test_pyopenssl.py
-+++ urllib3-1.26.10/test/contrib/test_pyopenssl.py
+--- urllib3-1.26.16.orig/test/contrib/test_pyopenssl.py
++++ urllib3-1.26.16/test/contrib/test_pyopenssl.py
@@ -1,7 +1,10 @@
# -*- coding: utf-8 -*-
import os
@@ -30,10 +30,10 @@
import pytest
try:
-Index: urllib3-1.26.10/test/contrib/test_pyopenssl_dependencies.py
+Index: urllib3-1.26.16/test/contrib/test_pyopenssl_dependencies.py
===================================================================
---- urllib3-1.26.10.orig/test/contrib/test_pyopenssl_dependencies.py
-+++ urllib3-1.26.10/test/contrib/test_pyopenssl_dependencies.py
+--- urllib3-1.26.16.orig/test/contrib/test_pyopenssl_dependencies.py
++++ urllib3-1.26.16/test/contrib/test_pyopenssl_dependencies.py
@@ -1,6 +1,9 @@
# -*- coding: utf-8 -*-
import pytest
@@ -45,10 +45,10 @@
try:
from urllib3.contrib.pyopenssl import extract_from_urllib3,
inject_into_urllib3
-Index: urllib3-1.26.10/test/test_connection.py
+Index: urllib3-1.26.16/test/test_connection.py
===================================================================
---- urllib3-1.26.10.orig/test/test_connection.py
-+++ urllib3-1.26.10/test/test_connection.py
+--- urllib3-1.26.16.orig/test/test_connection.py
++++ urllib3-1.26.16/test/test_connection.py
@@ -1,6 +1,9 @@
import datetime
@@ -60,10 +60,10 @@
import pytest
from urllib3.connection import RECENT_DATE, CertificateError, _match_hostname
-Index: urllib3-1.26.10/test/test_connectionpool.py
+Index: urllib3-1.26.16/test/test_connectionpool.py
===================================================================
---- urllib3-1.26.10.orig/test/test_connectionpool.py
-+++ urllib3-1.26.10/test/test_connectionpool.py
+--- urllib3-1.26.16.orig/test/test_connectionpool.py
++++ urllib3-1.26.16/test/test_connectionpool.py
@@ -6,7 +6,10 @@ from ssl import SSLError as BaseSSLError
from test import SHORT_TIMEOUT
@@ -76,10 +76,10 @@
from dummyserver.server import DEFAULT_CA
from urllib3._collections import HTTPHeaderDict
-Index: urllib3-1.26.10/test/test_queue_monkeypatch.py
+Index: urllib3-1.26.16/test/test_queue_monkeypatch.py
===================================================================
---- urllib3-1.26.10.orig/test/test_queue_monkeypatch.py
-+++ urllib3-1.26.10/test/test_queue_monkeypatch.py
+--- urllib3-1.26.16.orig/test/test_queue_monkeypatch.py
++++ urllib3-1.26.16/test/test_queue_monkeypatch.py
@@ -1,6 +1,9 @@
from __future__ import absolute_import
@@ -91,10 +91,10 @@
import pytest
from urllib3 import HTTPConnectionPool
-Index: urllib3-1.26.10/test/test_response.py
+Index: urllib3-1.26.16/test/test_response.py
===================================================================
---- urllib3-1.26.10.orig/test/test_response.py
-+++ urllib3-1.26.10/test/test_response.py
+--- urllib3-1.26.16.orig/test/test_response.py
++++ urllib3-1.26.16/test/test_response.py
@@ -9,7 +9,10 @@ from base64 import b64decode
from io import BufferedReader, BytesIO, TextIOWrapper
from test import onlyBrotlipy
@@ -107,10 +107,10 @@
import pytest
import six
-Index: urllib3-1.26.10/test/test_retry.py
+Index: urllib3-1.26.16/test/test_retry.py
===================================================================
---- urllib3-1.26.10.orig/test/test_retry.py
-+++ urllib3-1.26.10/test/test_retry.py
+--- urllib3-1.26.16.orig/test/test_retry.py
++++ urllib3-1.26.16/test/test_retry.py
@@ -1,6 +1,9 @@
import warnings
@@ -122,10 +122,10 @@
import pytest
from urllib3.exceptions import (
-Index: urllib3-1.26.10/test/test_retry_deprecated.py
+Index: urllib3-1.26.16/test/test_retry_deprecated.py
===================================================================
---- urllib3-1.26.10.orig/test/test_retry_deprecated.py
-+++ urllib3-1.26.10/test/test_retry_deprecated.py
+--- urllib3-1.26.16.orig/test/test_retry_deprecated.py
++++ urllib3-1.26.16/test/test_retry_deprecated.py
@@ -1,7 +1,10 @@
# This is a copy-paste of test_retry.py with extra asserts about deprecated
options. It will be removed for v2.
import warnings
@@ -138,10 +138,10 @@
import pytest
from urllib3.exceptions import (
-Index: urllib3-1.26.10/test/test_ssl.py
+Index: urllib3-1.26.16/test/test_ssl.py
===================================================================
---- urllib3-1.26.10.orig/test/test_ssl.py
-+++ urllib3-1.26.10/test/test_ssl.py
+--- urllib3-1.26.16.orig/test/test_ssl.py
++++ urllib3-1.26.16/test/test_ssl.py
@@ -1,6 +1,9 @@
from test import notPyPy2
@@ -153,10 +153,10 @@
import pytest
from urllib3.exceptions import SNIMissingWarning
-Index: urllib3-1.26.10/test/test_ssltransport.py
+Index: urllib3-1.26.16/test/test_ssltransport.py
===================================================================
---- urllib3-1.26.10.orig/test/test_ssltransport.py
-+++ urllib3-1.26.10/test/test_ssltransport.py
+--- urllib3-1.26.16.orig/test/test_ssltransport.py
++++ urllib3-1.26.16/test/test_ssltransport.py
@@ -4,7 +4,10 @@ import socket
import ssl
import sys
@@ -169,10 +169,10 @@
import pytest
from dummyserver.server import DEFAULT_CA, DEFAULT_CERTS
-Index: urllib3-1.26.10/test/test_util.py
+Index: urllib3-1.26.16/test/test_util.py
===================================================================
---- urllib3-1.26.10.orig/test/test_util.py
-+++ urllib3-1.26.10/test/test_util.py
+--- urllib3-1.26.16.orig/test/test_util.py
++++ urllib3-1.26.16/test/test_util.py
@@ -9,7 +9,10 @@ from itertools import chain
from test import notBrotlipy, onlyBrotlipy, onlyPy2, onlyPy3
@@ -185,10 +185,10 @@
from urllib3 import add_stderr_logger, disable_warnings, util
from urllib3.exceptions import (
-Index: urllib3-1.26.10/test/with_dummyserver/test_connectionpool.py
+Index: urllib3-1.26.16/test/with_dummyserver/test_connectionpool.py
===================================================================
---- urllib3-1.26.10.orig/test/with_dummyserver/test_connectionpool.py
-+++ urllib3-1.26.10/test/with_dummyserver/test_connectionpool.py
+--- urllib3-1.26.16.orig/test/with_dummyserver/test_connectionpool.py
++++ urllib3-1.26.16/test/with_dummyserver/test_connectionpool.py
@@ -12,7 +12,10 @@ import warnings
from test import LONG_TIMEOUT, SHORT_TIMEOUT, onlyPy2
from threading import Event
@@ -201,10 +201,10 @@
import pytest
import six
-Index: urllib3-1.26.10/test/with_dummyserver/test_https.py
+Index: urllib3-1.26.16/test/with_dummyserver/test_https.py
===================================================================
---- urllib3-1.26.10.orig/test/with_dummyserver/test_https.py
-+++ urllib3-1.26.10/test/with_dummyserver/test_https.py
+--- urllib3-1.26.16.orig/test/with_dummyserver/test_https.py
++++ urllib3-1.26.16/test/with_dummyserver/test_https.py
@@ -18,7 +18,10 @@ from test import (
resolvesLocalhostFQDN,
)
@@ -217,11 +217,11 @@
import pytest
import trustme
-Index: urllib3-1.26.10/test/with_dummyserver/test_socketlevel.py
+Index: urllib3-1.26.16/test/with_dummyserver/test_socketlevel.py
===================================================================
---- urllib3-1.26.10.orig/test/with_dummyserver/test_socketlevel.py
-+++ urllib3-1.26.10/test/with_dummyserver/test_socketlevel.py
-@@ -53,7 +53,10 @@ from test import (
+--- urllib3-1.26.16.orig/test/with_dummyserver/test_socketlevel.py
++++ urllib3-1.26.16/test/with_dummyserver/test_socketlevel.py
+@@ -54,7 +54,10 @@ from test import (
)
from threading import Event
@@ -233,11 +233,11 @@
import pytest
import trustme
-Index: urllib3-1.26.10/test/test_poolmanager.py
+Index: urllib3-1.26.16/test/test_poolmanager.py
===================================================================
---- urllib3-1.26.10.orig/test/test_poolmanager.py
-+++ urllib3-1.26.10/test/test_poolmanager.py
-@@ -2,7 +2,11 @@ import socket
+--- urllib3-1.26.16.orig/test/test_poolmanager.py
++++ urllib3-1.26.16/test/test_poolmanager.py
+@@ -3,7 +3,11 @@ import socket
from test import resolvesLocalhostFQDN
import pytest
@@ -249,8 +249,8 @@
+ import mock
from urllib3 import connection_from_url
- from urllib3.exceptions import ClosedPoolError, LocationValueError
-@@ -383,7 +387,7 @@ class TestPoolManager(object):
+ from urllib3.exceptions import LocationValueError
+@@ -361,7 +365,7 @@ class TestPoolManager(object):
"http://[a::b%25zone]",
],
)
++++++ urllib3-1.26.15.tar.gz -> urllib3-1.26.16.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/urllib3-1.26.15/CHANGES.rst
new/urllib3-1.26.16/CHANGES.rst
--- old/urllib3-1.26.15/CHANGES.rst 2023-03-11 00:57:45.000000000 +0100
+++ new/urllib3-1.26.16/CHANGES.rst 2023-05-23 12:51:05.000000000 +0200
@@ -1,6 +1,13 @@
Changes
=======
+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)
--------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/urllib3-1.26.15/PKG-INFO new/urllib3-1.26.16/PKG-INFO
--- old/urllib3-1.26.15/PKG-INFO 2023-03-11 00:57:54.565305700 +0100
+++ new/urllib3-1.26.16/PKG-INFO 2023-05-23 12:51:13.747491400 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: urllib3
-Version: 1.26.15
+Version: 1.26.16
Summary: HTTP library with thread-safe connection pooling, file post, and more.
Home-page: https://urllib3.readthedocs.io/
Author: Andrey Petrov
@@ -144,6 +144,13 @@
Changes
=======
+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)
--------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/urllib3-1.26.15/docs/v2-roadmap.rst
new/urllib3-1.26.16/docs/v2-roadmap.rst
--- old/urllib3-1.26.15/docs/v2-roadmap.rst 2023-03-11 00:57:45.000000000
+0100
+++ new/urllib3-1.26.16/docs/v2-roadmap.rst 2023-05-23 12:51:05.000000000
+0200
@@ -80,15 +80,15 @@
available.
-**⨠Optimized for Python 3.6+**
+**⨠Optimized for Python 3.7+**
--------------------------------
In v2.0 we'll be specifically be targeting
-CPython 3.6+ and PyPy 7.0+ (compatible with CPython 3.6)
-and dropping support Python versions 2.7 and 3.5.
+CPython 3.7+ and PyPy 7.3.10+ (compatible with CPython 3.8)
+and dropping support Python versions 2.7 and 3.6.
By dropping end-of-life Python versions we're able to optimize
-the codebase for Python 3.6+ by using new features to improve
+the codebase for Python 3.7+ by using new features to improve
performance and reduce the amount of code that needs to be executed
in order to support legacy versions.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/urllib3-1.26.15/src/urllib3/_version.py
new/urllib3-1.26.16/src/urllib3/_version.py
--- old/urllib3-1.26.15/src/urllib3/_version.py 2023-03-11 00:57:45.000000000
+0100
+++ new/urllib3-1.26.16/src/urllib3/_version.py 2023-05-23 12:51:05.000000000
+0200
@@ -1,2 +1,2 @@
# This file is protected via CODEOWNERS
-__version__ = "1.26.15"
+__version__ = "1.26.16"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/urllib3-1.26.15/src/urllib3/connectionpool.py
new/urllib3-1.26.16/src/urllib3/connectionpool.py
--- old/urllib3-1.26.15/src/urllib3/connectionpool.py 2023-03-11
00:57:45.000000000 +0100
+++ new/urllib3-1.26.16/src/urllib3/connectionpool.py 2023-05-23
12:51:05.000000000 +0200
@@ -50,6 +50,13 @@
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 +227,16 @@
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`.
@@ -489,14 +506,8 @@
# 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):
"""
@@ -1108,3 +1119,14 @@
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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/urllib3-1.26.15/src/urllib3/packages/backports/weakref_finalize.py
new/urllib3-1.26.16/src/urllib3/packages/backports/weakref_finalize.py
--- old/urllib3-1.26.15/src/urllib3/packages/backports/weakref_finalize.py
1970-01-01 01:00:00.000000000 +0100
+++ new/urllib3-1.26.16/src/urllib3/packages/backports/weakref_finalize.py
2023-05-23 12:51:05.000000000 +0200
@@ -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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/urllib3-1.26.15/src/urllib3/poolmanager.py
new/urllib3-1.26.16/src/urllib3/poolmanager.py
--- old/urllib3-1.26.15/src/urllib3/poolmanager.py 2023-03-11
00:57:45.000000000 +0100
+++ new/urllib3-1.26.16/src/urllib3/poolmanager.py 2023-05-23
12:51:05.000000000 +0200
@@ -171,7 +171,7 @@
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.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/urllib3-1.26.15/src/urllib3.egg-info/PKG-INFO
new/urllib3-1.26.16/src/urllib3.egg-info/PKG-INFO
--- old/urllib3-1.26.15/src/urllib3.egg-info/PKG-INFO 2023-03-11
00:57:54.000000000 +0100
+++ new/urllib3-1.26.16/src/urllib3.egg-info/PKG-INFO 2023-05-23
12:51:13.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: urllib3
-Version: 1.26.15
+Version: 1.26.16
Summary: HTTP library with thread-safe connection pooling, file post, and more.
Home-page: https://urllib3.readthedocs.io/
Author: Andrey Petrov
@@ -144,6 +144,13 @@
Changes
=======
+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)
--------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/urllib3-1.26.15/src/urllib3.egg-info/SOURCES.txt
new/urllib3-1.26.16/src/urllib3.egg-info/SOURCES.txt
--- old/urllib3-1.26.15/src/urllib3.egg-info/SOURCES.txt 2023-03-11
00:57:54.000000000 +0100
+++ new/urllib3-1.26.16/src/urllib3.egg-info/SOURCES.txt 2023-05-23
12:51:13.000000000 +0200
@@ -77,6 +77,7 @@
src/urllib3/packages/six.py
src/urllib3/packages/backports/__init__.py
src/urllib3/packages/backports/makefile.py
+src/urllib3/packages/backports/weakref_finalize.py
src/urllib3/util/__init__.py
src/urllib3/util/connection.py
src/urllib3/util/proxy.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/urllib3-1.26.15/test/test_poolmanager.py
new/urllib3-1.26.16/test/test_poolmanager.py
--- old/urllib3-1.26.15/test/test_poolmanager.py 2023-03-11
00:57:45.000000000 +0100
+++ new/urllib3-1.26.16/test/test_poolmanager.py 2023-05-23
12:51:05.000000000 +0200
@@ -1,3 +1,4 @@
+import gc
import socket
from test import resolvesLocalhostFQDN
@@ -5,7 +6,7 @@
from mock import patch
from urllib3 import connection_from_url
-from urllib3.exceptions import ClosedPoolError, LocationValueError
+from urllib3.exceptions import LocationValueError
from urllib3.poolmanager import PoolKey, PoolManager, key_fn_by_scheme
from urllib3.util import retry, timeout
@@ -60,24 +61,12 @@
def test_manager_clear(self):
p = PoolManager(5)
- conn_pool = p.connection_from_url("http://google.com")
+ p.connection_from_url("http://google.com")
assert len(p.pools) == 1
- conn = conn_pool._get_conn()
-
p.clear()
assert len(p.pools) == 0
- with pytest.raises(ClosedPoolError):
- conn_pool._get_conn()
-
- conn_pool._put_conn(conn)
-
- with pytest.raises(ClosedPoolError):
- conn_pool._get_conn()
-
- assert len(p.pools) == 0
-
@pytest.mark.parametrize("url", ["http://@", None])
def test_nohost(self, url):
p = PoolManager(5)
@@ -86,19 +75,8 @@
def test_contextmanager(self):
with PoolManager(1) as p:
- conn_pool = p.connection_from_url("http://google.com")
+ p.connection_from_url("http://google.com")
assert len(p.pools) == 1
- conn = conn_pool._get_conn()
-
- assert len(p.pools) == 0
-
- with pytest.raises(ClosedPoolError):
- conn_pool._get_conn()
-
- conn_pool._put_conn(conn)
-
- with pytest.raises(ClosedPoolError):
- conn_pool._get_conn()
assert len(p.pools) == 0
@@ -397,3 +375,30 @@
conn.connect()
assert create_connection.call_args[0][0] == ("a::b%zone", 80)
+
+ def test_thread_safty(self):
+ pool_manager = PoolManager(num_pools=2)
+
+ # thread 1 gets a pool for host x
+ pool_1 = pool_manager.connection_from_url("http://host_x:80/")
+
+ # thread 2 gets a pool for host y
+ pool_2 = pool_manager.connection_from_url("http://host_y:80/")
+
+ # thread 3 gets a pool for host z
+ pool_3 = pool_manager.connection_from_url("http://host_z:80")
+
+ # None of the pools should be closed, since all of them are referenced.
+ assert pool_1.pool is not None
+ assert pool_2.pool is not None
+ assert pool_3.pool is not None
+
+ conn_queue = pool_1.pool
+ assert conn_queue.qsize() > 0
+
+ # thread 1 stops.
+ del pool_1
+ gc.collect()
+
+ # Connection should be closed, because reference to pool_1 is gone.
+ assert conn_queue.qsize() == 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/urllib3-1.26.15/test/test_ssltransport.py
new/urllib3-1.26.16/test/test_ssltransport.py
--- old/urllib3-1.26.15/test/test_ssltransport.py 2023-03-11
00:57:45.000000000 +0100
+++ new/urllib3-1.26.16/test/test_ssltransport.py 2023-05-23
12:51:05.000000000 +0200
@@ -202,8 +202,11 @@
assert ssock.selected_npn_protocol() is None
shared_ciphers = ssock.shared_ciphers()
- assert type(shared_ciphers) == list
- assert len(shared_ciphers) > 0
+ # SSLContext.shared_ciphers() changed behavior completely in a
patch version.
+ # See: https://github.com/python/cpython/issues/96931
+ assert shared_ciphers is None or (
+ type(shared_ciphers) is list and len(shared_ciphers) > 0
+ )
assert ssock.compression() is None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/urllib3-1.26.15/test/with_dummyserver/test_socketlevel.py
new/urllib3-1.26.16/test/with_dummyserver/test_socketlevel.py
--- old/urllib3-1.26.15/test/with_dummyserver/test_socketlevel.py
2023-03-11 00:57:45.000000000 +0100
+++ new/urllib3-1.26.16/test/with_dummyserver/test_socketlevel.py
2023-05-23 12:51:05.000000000 +0200
@@ -1221,10 +1221,11 @@
ssl_sock.close()
self._start_server(socket_handler)
- with HTTPSConnectionPool(self.host, self.port) as pool:
- with pytest.raises(MaxRetryError) as cm:
- pool.request("GET", "/", retries=0)
- assert isinstance(cm.value.reason, SSLError)
+ with HTTPSConnectionPool(self.host, self.port, ca_certs=DEFAULT_CA) as
pool:
+ with pytest.raises(
+ SSLError, match=r"(wrong version number|record overflow)"
+ ):
+ pool.request("GET", "/", retries=False)
@notSecureTransport
def test_ssl_read_timeout(self):