From 3ac3ec5413932a107eb2096f146cae4d96be2f87 Mon Sep 17 00:00:00 2001 From: Python Maint Date: Wed, 3 Jun 2026 21:13:47 +0200 Subject: [PATCH 1/6] Bootstrap for Python 3.15 --- python-urllib3.spec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python-urllib3.spec b/python-urllib3.spec index b2854a7..dd792c1 100644 --- a/python-urllib3.spec +++ b/python-urllib3.spec @@ -1,3 +1,5 @@ +%global _without_extradeps 1 +%global _without_tests 1 # When bootstrapping Python, we cannot test this yet # RHEL does not include the test dependencies and the dependencies for extras %bcond tests %{undefined rhel} From 192dc8ec6f9dd4cb30976ca97ffd5aa2d8ed38f9 Mon Sep 17 00:00:00 2001 From: Python Maint Date: Fri, 5 Jun 2026 00:43:32 +0200 Subject: [PATCH 2/6] Rebuilt for Python 3.15 --- python-urllib3.spec | 2 -- 1 file changed, 2 deletions(-) diff --git a/python-urllib3.spec b/python-urllib3.spec index dd792c1..b2854a7 100644 --- a/python-urllib3.spec +++ b/python-urllib3.spec @@ -1,5 +1,3 @@ -%global _without_extradeps 1 -%global _without_tests 1 # When bootstrapping Python, we cannot test this yet # RHEL does not include the test dependencies and the dependencies for extras %bcond tests %{undefined rhel} From d982eea4c74bdde4a50676ceccd2edf909f4b852 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Thu, 16 Jul 2026 22:28:37 +0000 Subject: [PATCH 3/6] Rebuilt for https://fedoraproject.org/wiki/Fedora_45_Mass_Rebuild From fed40e731b013510ec2bf49d4af37950c1d45d5f Mon Sep 17 00:00:00 2001 From: Filipe Rosset Date: Mon, 27 Jul 2026 16:23:08 -0300 Subject: [PATCH 4/6] Deal with ssl.PROTOCOL_TLSv1 removal from Python built with OpenSSL 4+ OpenSSL 4+ removed TLSv1 and TLSv1.1 support, this patched address this issue in rawhide, note the upstream already received another patch: https://github.com/urllib3/urllib3/pull/5097 Resolves: rhbz#2504593 Signed-off-by: Filipe Rosset --- python-urllib3-py315-ssl.patch | 67 ++++++++++++++++++++++++++++++++++ python-urllib3.spec | 6 ++- 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 python-urllib3-py315-ssl.patch diff --git a/python-urllib3-py315-ssl.patch b/python-urllib3-py315-ssl.patch new file mode 100644 index 0000000..ec0d1fb --- /dev/null +++ b/python-urllib3-py315-ssl.patch @@ -0,0 +1,67 @@ +--- a/src/urllib3/contrib/pyopenssl.py ++++ b/src/urllib3/contrib/pyopenssl.py +@@ -69,9 +69,11 @@ + _openssl_versions: dict[int, int] = { + util.ssl_.PROTOCOL_TLS: OpenSSL.SSL.SSLv23_METHOD, # type: ignore[attr-defined] + util.ssl_.PROTOCOL_TLS_CLIENT: OpenSSL.SSL.SSLv23_METHOD, # type: ignore[attr-defined] +- ssl.PROTOCOL_TLSv1: OpenSSL.SSL.TLSv1_METHOD, + } + ++if hasattr(ssl, "PROTOCOL_TLSv1") and hasattr(OpenSSL.SSL, "TLSv1_METHOD"): ++ _openssl_versions[ssl.PROTOCOL_TLSv1] = OpenSSL.SSL.TLSv1_METHOD ++ + if hasattr(ssl, "PROTOCOL_TLSv1_1") and hasattr(OpenSSL.SSL, "TLSv1_1_METHOD"): + _openssl_versions[ssl.PROTOCOL_TLSv1_1] = OpenSSL.SSL.TLSv1_1_METHOD + +--- a/test/test_ssl.py ++++ b/test/test_ssl.py +@@ -173,15 +173,15 @@ + "kwargs", + [ + { +- "ssl_version": ssl.PROTOCOL_TLSv1, ++ "ssl_version": getattr(ssl, "PROTOCOL_TLSv1", getattr(ssl, "PROTOCOL_TLSv1_2", 1)), + "ssl_minimum_version": ssl.TLSVersion.MINIMUM_SUPPORTED, + }, + { +- "ssl_version": ssl.PROTOCOL_TLSv1, ++ "ssl_version": getattr(ssl, "PROTOCOL_TLSv1", getattr(ssl, "PROTOCOL_TLSv1_2", 1)), + "ssl_maximum_version": ssl.TLSVersion.TLSv1, + }, + { +- "ssl_version": ssl.PROTOCOL_TLSv1, ++ "ssl_version": getattr(ssl, "PROTOCOL_TLSv1", getattr(ssl, "PROTOCOL_TLSv1_2", 1)), + "ssl_minimum_version": ssl.TLSVersion.MINIMUM_SUPPORTED, + "ssl_maximum_version": ssl.TLSVersion.MAXIMUM_SUPPORTED, + }, +@@ -222,10 +222,10 @@ + @pytest.mark.parametrize( + "kwargs", + [ +- {"ssl_version": ssl.PROTOCOL_TLSv1, "ssl_minimum_version": None}, +- {"ssl_version": ssl.PROTOCOL_TLSv1, "ssl_maximum_version": None}, ++ {"ssl_version": getattr(ssl, "PROTOCOL_TLSv1", getattr(ssl, "PROTOCOL_TLSv1_2", 1)), "ssl_minimum_version": None}, ++ {"ssl_version": getattr(ssl, "PROTOCOL_TLSv1", getattr(ssl, "PROTOCOL_TLSv1_2", 1)), "ssl_maximum_version": None}, + { +- "ssl_version": ssl.PROTOCOL_TLSv1, ++ "ssl_version": getattr(ssl, "PROTOCOL_TLSv1", getattr(ssl, "PROTOCOL_TLSv1_2", 1)), + "ssl_minimum_version": None, + "ssl_maximum_version": None, + }, +--- a/test/test_util.py ++++ b/test/test_util.py +@@ -982,9 +982,11 @@ + @pytest.mark.parametrize( + "candidate, version", + [ +- (ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1), +- ("PROTOCOL_TLSv1", ssl.PROTOCOL_TLSv1), +- ("TLSv1", ssl.PROTOCOL_TLSv1), ++ *([ ++ (getattr(ssl, "PROTOCOL_TLSv1", None), getattr(ssl, "PROTOCOL_TLSv1", None)), ++ ("PROTOCOL_TLSv1", getattr(ssl, "PROTOCOL_TLSv1", None)), ++ ("TLSv1", getattr(ssl, "PROTOCOL_TLSv1", None)), ++ ] if hasattr(ssl, "PROTOCOL_TLSv1") else []), + (ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23), + ], + ) diff --git a/python-urllib3.spec b/python-urllib3.spec index b2854a7..b4683e8 100644 --- a/python-urllib3.spec +++ b/python-urllib3.spec @@ -31,6 +31,10 @@ Source0: %{url}/archive/%{version}/urllib3-%{version}.tar.gz %global hypercorn_commit d1719f8c1570cbd8e6a3719ffdb14a4d72880abb Source1: %{hypercorn_url}/archive/%{hypercorn_commit}/hypercorn-%{hypercorn_commit}.tar.gz +# Deal with ssl.PROTOCOL_TLSv1 removal from Python built with OpenSSL 4+ +# https://github.com/urllib3/urllib3/pull/5097 +Patch: python-urllib3-py315-ssl.patch + BuildArch: noarch BuildRequires: python3-devel @@ -82,7 +86,7 @@ Recommends: python3-urllib3+socks %prep -%autosetup -n urllib3-%{version} +%autosetup -p1 -n urllib3-%{version} %setup -q -n urllib3-%{version} -T -D -b 1 # Allow setuptools-scm 10+ From d75d492045c1f0435d8508e84f093063e4a88135 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Mon, 27 Jul 2026 22:22:53 +0200 Subject: [PATCH 5/6] Fix test failures (OpenSSL 4 and pyOpenSSL 26.3) - Fixes: rhbz#2504593 Used LLM to identify and rebase upstream patch #5103 Assisted-By: Claude Opus 4.6 --- 5097.patch | 133 +++++++++++++++++++++++++++++++++ 5103.patch | 83 ++++++++++++++++++++ python-urllib3-py315-ssl.patch | 67 ----------------- python-urllib3.spec | 6 +- 4 files changed, 220 insertions(+), 69 deletions(-) create mode 100644 5097.patch create mode 100644 5103.patch delete mode 100644 python-urllib3-py315-ssl.patch diff --git a/5097.patch b/5097.patch new file mode 100644 index 0000000..ac3af0f --- /dev/null +++ b/5097.patch @@ -0,0 +1,133 @@ +From 8d2659ac68ec8d46dfd8c2fc0ab057b647ac7940 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= +Date: Wed, 1 Jul 2026 15:05:18 +0200 +Subject: [PATCH] Deal with ssl.PROTOCOL_TLSv1 removal from Python built with + OpenSSL 4+ + +https://github.com/python/cpython/commit/3364e7e62fa24d0e19133fb0f90b1c24ef1110c5 +removed ssl.PROTOCOL_TLSv1 when python is built with OpenSSL 4+. + +We are hitting this error in Fedora (where we already updated OpenSSL): + + ImportError while loading conftest '/builddir/build/BUILD/python-urllib3-2.7.0-build/urllib3-2.7.0/test/conftest.py'. + test/__init__.py:42: in + import urllib3.contrib.pyopenssl as pyopenssl + ../BUILDROOT/usr/lib/python3.15/site-packages/urllib3/contrib/pyopenssl.py:72: in + ssl.PROTOCOL_TLSv1: OpenSSL.SSL.TLSv1_METHOD, + ^^^^^^^^^^^^^^^^^^ + E AttributeError: module 'ssl' has no attribute 'PROTOCOL_TLSv1'. Did you mean '.PROTOCOL_TLS' instead of '.PROTOCOL_TLSv1'? + +Used LLM to figure out what to use as a replacement protocol in tests. + +Assisted-By: Claude Opus 4.6 +--- + changelog/5097.bugfix.rst | 2 ++ + src/urllib3/contrib/pyopenssl.py | 4 +++- + test/test_ssl.py | 14 ++++++++------ + test/test_util.py | 24 +++++++++++++++--------- + 4 files changed, 28 insertions(+), 16 deletions(-) + create mode 100644 changelog/5097.bugfix.rst + +diff --git a/changelog/5097.bugfix.rst b/changelog/5097.bugfix.rst +new file mode 100644 +index 0000000000..73ed0ddaa1 +--- /dev/null ++++ b/changelog/5097.bugfix.rst +@@ -0,0 +1,2 @@ ++Fixed an ``AttributeError`` on Python built with OpenSSL 4+, where ++``ssl.PROTOCOL_TLSv1`` no longer exists. +diff --git a/src/urllib3/contrib/pyopenssl.py b/src/urllib3/contrib/pyopenssl.py +index 42781590ee..76a225b7bf 100644 +--- a/src/urllib3/contrib/pyopenssl.py ++++ b/src/urllib3/contrib/pyopenssl.py +@@ -68,9 +68,11 @@ class UnsupportedExtension(Exception): # type: ignore[no-redef] + _openssl_versions: dict[int, int] = { + util.ssl_.PROTOCOL_TLS: OpenSSL.SSL.SSLv23_METHOD, # type: ignore[attr-defined] + util.ssl_.PROTOCOL_TLS_CLIENT: OpenSSL.SSL.SSLv23_METHOD, # type: ignore[attr-defined] +- ssl.PROTOCOL_TLSv1: OpenSSL.SSL.TLSv1_METHOD, + } + ++if hasattr(ssl, "PROTOCOL_TLSv1") and hasattr(OpenSSL.SSL, "TLSv1_METHOD"): ++ _openssl_versions[ssl.PROTOCOL_TLSv1] = OpenSSL.SSL.TLSv1_METHOD ++ + if hasattr(ssl, "PROTOCOL_TLSv1_1") and hasattr(OpenSSL.SSL, "TLSv1_1_METHOD"): + _openssl_versions[ssl.PROTOCOL_TLSv1_1] = OpenSSL.SSL.TLSv1_1_METHOD + +diff --git a/test/test_ssl.py b/test/test_ssl.py +index 6b1ab8589b..1e4063bf68 100644 +--- a/test/test_ssl.py ++++ b/test/test_ssl.py +@@ -176,19 +176,21 @@ def test_create_urllib3_context_default_ciphers( + + context.set_ciphers.assert_not_called() + ++ # PROTOCOL_TLS_SERVER is used as a stand-in for any non-default ssl_version. ++ # PROTOCOL_TLSv1/TLSv1_2 are unavailable when Python is built with OpenSSL 4+. + @pytest.mark.parametrize( + "kwargs", + [ + { +- "ssl_version": ssl.PROTOCOL_TLSv1, ++ "ssl_version": ssl.PROTOCOL_TLS_SERVER, + "ssl_minimum_version": ssl.TLSVersion.MINIMUM_SUPPORTED, + }, + { +- "ssl_version": ssl.PROTOCOL_TLSv1, ++ "ssl_version": ssl.PROTOCOL_TLS_SERVER, + "ssl_maximum_version": ssl.TLSVersion.TLSv1, + }, + { +- "ssl_version": ssl.PROTOCOL_TLSv1, ++ "ssl_version": ssl.PROTOCOL_TLS_SERVER, + "ssl_minimum_version": ssl.TLSVersion.MINIMUM_SUPPORTED, + "ssl_maximum_version": ssl.TLSVersion.MAXIMUM_SUPPORTED, + }, +@@ -229,10 +231,10 @@ def test_create_urllib3_context_ssl_version_and_ssl_min_max_version_no_warning( + @pytest.mark.parametrize( + "kwargs", + [ +- {"ssl_version": ssl.PROTOCOL_TLSv1, "ssl_minimum_version": None}, +- {"ssl_version": ssl.PROTOCOL_TLSv1, "ssl_maximum_version": None}, ++ {"ssl_version": ssl.PROTOCOL_TLS_SERVER, "ssl_minimum_version": None}, ++ {"ssl_version": ssl.PROTOCOL_TLS_SERVER, "ssl_maximum_version": None}, + { +- "ssl_version": ssl.PROTOCOL_TLSv1, ++ "ssl_version": ssl.PROTOCOL_TLS_SERVER, + "ssl_minimum_version": None, + "ssl_maximum_version": None, + }, +diff --git a/test/test_util.py b/test/test_util.py +index 8612ab5eaf..18c65f0312 100644 +--- a/test/test_util.py ++++ b/test/test_util.py +@@ -1216,15 +1216,21 @@ def test_resolve_cert_reqs( + ) -> None: + assert resolve_cert_reqs(candidate) == requirements + +- @pytest.mark.parametrize( +- "candidate, version", +- [ +- (ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1), +- ("PROTOCOL_TLSv1", ssl.PROTOCOL_TLSv1), +- ("TLSv1", ssl.PROTOCOL_TLSv1), +- (ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23), +- ], +- ) ++ candidate_version = [ ++ (ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23), ++ ("PROTOCOL_SSLv23", ssl.PROTOCOL_SSLv23), ++ ("SSLv23", ssl.PROTOCOL_SSLv23), ++ ] ++ if hasattr(ssl, "PROTOCOL_TLSv1"): ++ candidate_version.extend( ++ [ ++ (ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1), ++ ("PROTOCOL_TLSv1", ssl.PROTOCOL_TLSv1), ++ ("TLSv1", ssl.PROTOCOL_TLSv1), ++ ] ++ ) ++ ++ @pytest.mark.parametrize("candidate, version", candidate_version) + def test_resolve_ssl_version(self, candidate: int | str, version: int) -> None: + assert resolve_ssl_version(candidate) == version + diff --git a/5103.patch b/5103.patch new file mode 100644 index 0000000..c1b28d5 --- /dev/null +++ b/5103.patch @@ -0,0 +1,83 @@ +From 13fa1e033b37405b228599ee590af485dc3e38aa Mon Sep 17 00:00:00 2001 +From: Illia Volochii +Date: Sat, 18 Jul 2026 13:25:41 +0200 +Subject: [PATCH] Replace deprecated pyOpenSSL `X509.get_subject` and + `Context.set_passwd_cb` methods (#5103) + +Rebased on top of urllib3-2.7.0. +--- + src/urllib3/contrib/pyopenssl.py | 35 ++++++++++++++++++++++++++------- + 1 file changed, 28 insertions(+), 7 deletions(-) + +diff --git a/src/urllib3/contrib/pyopenssl.py b/src/urllib3/contrib/pyopenssl.py +index 76a225b7bf..a1b2c3d4e5 100644 +--- a/src/urllib3/contrib/pyopenssl.py ++++ b/src/urllib3/contrib/pyopenssl.py +@@ -42,6 +42,8 @@ + + import OpenSSL.SSL # type: ignore[import-not-found] + from cryptography import x509 ++from cryptography.hazmat.primitives.serialization import load_pem_private_key ++from cryptography.x509.oid import NameOID + + try: + from cryptography.x509 import UnsupportedExtension # type: ignore[attr-defined] +@@ -272,6 +274,15 @@ + return names + + ++def _get_common_name(peer_cert: X509) -> str | None: ++ """ ++ Given a pyOpenSSL certificate, return the subject's common name. ++ """ ++ cert = peer_cert.to_cryptography() ++ names = cert.subject.get_attributes_for_oid(NameOID.COMMON_NAME) ++ return typing.cast(str, names[0].value) if names else None ++ ++ + class WrappedSocket: + """API-compatibility wrapper for Python OpenSSL's Connection-class.""" + +@@ -396,7 +407,7 @@ + return OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_ASN1, x509) # type: ignore[no-any-return] + + return { +- "subject": ((("commonName", x509.get_subject().CN),),), # type: ignore[dict-item] ++ "subject": ((("commonName", _get_common_name(x509)),),), # type: ignore[dict-item] + "subjectAltName": get_subj_alt_name(x509), + } + +@@ -482,16 +493,28 @@ + self, + certfile: str, + keyfile: str | None = None, +- password: str | None = None, ++ password: str | bytes | None = None, + ) -> None: + try: + self._ctx.use_certificate_chain_file(certfile) + if password is not None: + if not isinstance(password, bytes): +- password = password.encode("utf-8") # type: ignore[assignment] +- self._ctx.set_passwd_cb(lambda *_: password) +- self._ctx.use_privatekey_file(keyfile or certfile) +- except OpenSSL.SSL.Error as e: ++ password = password.encode("utf-8") ++ # pyOpenSSL added cryptography-key support in 24.3.0. ++ # Keep using the older password-callback path until 2026's ++ # versions because set_passwd_cb() became deprecated in 26.3.0. ++ if int(OpenSSL.__version__.split(".")[0]) >= 26: ++ with open(keyfile or certfile, "rb") as key_file: ++ private_key = load_pem_private_key(key_file.read(), password) ++ # cryptography's loader returns a wider private-key union ++ # than pyOpenSSL accepts, so we add `type: ignore` here. ++ self._ctx.use_privatekey(private_key) # type: ignore[arg-type] ++ else: ++ self._ctx.set_passwd_cb(lambda *_: password) ++ self._ctx.use_privatekey_file(keyfile or certfile) ++ else: ++ self._ctx.use_privatekey_file(keyfile or certfile) ++ except (OpenSSL.SSL.Error, TypeError, ValueError) as e: + raise ssl.SSLError(f"Unable to load certificate chain: {e!r}") from e + + def set_alpn_protocols(self, protocols: list[bytes | str]) -> None: diff --git a/python-urllib3-py315-ssl.patch b/python-urllib3-py315-ssl.patch deleted file mode 100644 index ec0d1fb..0000000 --- a/python-urllib3-py315-ssl.patch +++ /dev/null @@ -1,67 +0,0 @@ ---- a/src/urllib3/contrib/pyopenssl.py -+++ b/src/urllib3/contrib/pyopenssl.py -@@ -69,9 +69,11 @@ - _openssl_versions: dict[int, int] = { - util.ssl_.PROTOCOL_TLS: OpenSSL.SSL.SSLv23_METHOD, # type: ignore[attr-defined] - util.ssl_.PROTOCOL_TLS_CLIENT: OpenSSL.SSL.SSLv23_METHOD, # type: ignore[attr-defined] -- ssl.PROTOCOL_TLSv1: OpenSSL.SSL.TLSv1_METHOD, - } - -+if hasattr(ssl, "PROTOCOL_TLSv1") and hasattr(OpenSSL.SSL, "TLSv1_METHOD"): -+ _openssl_versions[ssl.PROTOCOL_TLSv1] = OpenSSL.SSL.TLSv1_METHOD -+ - if hasattr(ssl, "PROTOCOL_TLSv1_1") and hasattr(OpenSSL.SSL, "TLSv1_1_METHOD"): - _openssl_versions[ssl.PROTOCOL_TLSv1_1] = OpenSSL.SSL.TLSv1_1_METHOD - ---- a/test/test_ssl.py -+++ b/test/test_ssl.py -@@ -173,15 +173,15 @@ - "kwargs", - [ - { -- "ssl_version": ssl.PROTOCOL_TLSv1, -+ "ssl_version": getattr(ssl, "PROTOCOL_TLSv1", getattr(ssl, "PROTOCOL_TLSv1_2", 1)), - "ssl_minimum_version": ssl.TLSVersion.MINIMUM_SUPPORTED, - }, - { -- "ssl_version": ssl.PROTOCOL_TLSv1, -+ "ssl_version": getattr(ssl, "PROTOCOL_TLSv1", getattr(ssl, "PROTOCOL_TLSv1_2", 1)), - "ssl_maximum_version": ssl.TLSVersion.TLSv1, - }, - { -- "ssl_version": ssl.PROTOCOL_TLSv1, -+ "ssl_version": getattr(ssl, "PROTOCOL_TLSv1", getattr(ssl, "PROTOCOL_TLSv1_2", 1)), - "ssl_minimum_version": ssl.TLSVersion.MINIMUM_SUPPORTED, - "ssl_maximum_version": ssl.TLSVersion.MAXIMUM_SUPPORTED, - }, -@@ -222,10 +222,10 @@ - @pytest.mark.parametrize( - "kwargs", - [ -- {"ssl_version": ssl.PROTOCOL_TLSv1, "ssl_minimum_version": None}, -- {"ssl_version": ssl.PROTOCOL_TLSv1, "ssl_maximum_version": None}, -+ {"ssl_version": getattr(ssl, "PROTOCOL_TLSv1", getattr(ssl, "PROTOCOL_TLSv1_2", 1)), "ssl_minimum_version": None}, -+ {"ssl_version": getattr(ssl, "PROTOCOL_TLSv1", getattr(ssl, "PROTOCOL_TLSv1_2", 1)), "ssl_maximum_version": None}, - { -- "ssl_version": ssl.PROTOCOL_TLSv1, -+ "ssl_version": getattr(ssl, "PROTOCOL_TLSv1", getattr(ssl, "PROTOCOL_TLSv1_2", 1)), - "ssl_minimum_version": None, - "ssl_maximum_version": None, - }, ---- a/test/test_util.py -+++ b/test/test_util.py -@@ -982,9 +982,11 @@ - @pytest.mark.parametrize( - "candidate, version", - [ -- (ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1), -- ("PROTOCOL_TLSv1", ssl.PROTOCOL_TLSv1), -- ("TLSv1", ssl.PROTOCOL_TLSv1), -+ *([ -+ (getattr(ssl, "PROTOCOL_TLSv1", None), getattr(ssl, "PROTOCOL_TLSv1", None)), -+ ("PROTOCOL_TLSv1", getattr(ssl, "PROTOCOL_TLSv1", None)), -+ ("TLSv1", getattr(ssl, "PROTOCOL_TLSv1", None)), -+ ] if hasattr(ssl, "PROTOCOL_TLSv1") else []), - (ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23), - ], - ) diff --git a/python-urllib3.spec b/python-urllib3.spec index b4683e8..49ec528 100644 --- a/python-urllib3.spec +++ b/python-urllib3.spec @@ -32,8 +32,10 @@ Source0: %{url}/archive/%{version}/urllib3-%{version}.tar.gz Source1: %{hypercorn_url}/archive/%{hypercorn_commit}/hypercorn-%{hypercorn_commit}.tar.gz # Deal with ssl.PROTOCOL_TLSv1 removal from Python built with OpenSSL 4+ -# https://github.com/urllib3/urllib3/pull/5097 -Patch: python-urllib3-py315-ssl.patch +Patch: https://github.com/urllib3/urllib3/pull/5097.patch +# Replace deprecated pyOpenSSL X509.get_subject and Context.set_passwd_cb methods +# https://github.com/urllib3/urllib3/pull/5103 rebased +Patch: 5103.patch BuildArch: noarch From c60a40812cecb329ac6e0d5abb793a6dea0f1b73 Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Mon, 10 Aug 2026 10:03:48 +0200 Subject: [PATCH 6/6] Fix compatibility with the latest pytest --- c420e267.patch | 66 +++++++++++++++++++++++++++++++++++++++++++++ python-urllib3.spec | 3 +++ 2 files changed, 69 insertions(+) create mode 100644 c420e267.patch diff --git a/c420e267.patch b/c420e267.patch new file mode 100644 index 0000000..74cf1fd --- /dev/null +++ b/c420e267.patch @@ -0,0 +1,66 @@ +From c420e267acb739917bee96e021ad9a2d27de8aae Mon Sep 17 00:00:00 2001 +From: Colin Watson +Date: Tue, 30 Jun 2026 21:48:57 +0100 +Subject: [PATCH] Fix test failures with pytest >= 9.1 (#5094) + +Co-authored-by: Illia Volochii +--- + changelog/5094.misc.rst | 1 + + test/test_util.py | 3 +-- + uv.lock | 6 +++--- + 3 files changed, 5 insertions(+), 5 deletions(-) + create mode 100644 changelog/5094.misc.rst + +diff --git a/changelog/5094.misc.rst b/changelog/5094.misc.rst +new file mode 100644 +index 0000000000..e6f2a24f2f +--- /dev/null ++++ b/changelog/5094.misc.rst +@@ -0,0 +1 @@ ++Fixed test failures with pytest >= 9.1. +diff --git a/test/test_util.py b/test/test_util.py +index fb8f81eb7e..8612ab5eaf 100644 +--- a/test/test_util.py ++++ b/test/test_util.py +@@ -7,7 +7,6 @@ + import sys + import typing + import warnings +-from itertools import chain + from test import ImportBlocker, ModuleStash, notBrotli, notZstd, onlyBrotli, onlyZstd + from unittest import mock + from unittest.mock import MagicMock, Mock, patch +@@ -438,7 +437,7 @@ def test_percent_encoded_control_ipv6_zone_ids_raise(self, url: str) -> None: + + @pytest.mark.parametrize( + "url, expected_url", +- chain(parse_url_host_map, non_round_tripping_parse_url_host_map), ++ [*parse_url_host_map, *non_round_tripping_parse_url_host_map], + ) + def test_parse_url(self, url: str, expected_url: Url) -> None: + returned_url = parse_url(url) +diff --git a/uv.lock b/uv.lock +index 03ec5fb75a..82d0c070eb 100644 +--- a/uv.lock ++++ b/uv.lock +@@ -1707,7 +1707,7 @@ wheels = [ + + [[package]] + name = "pytest" +-version = "9.0.3" ++version = "9.1.1" + source = { registry = "https://pypi.org/simple" } + dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'group-7-urllib3-dev' and extra == 'group-7-urllib3-dev-min-pyopenssl') or (extra == 'group-7-urllib3-dev-min-pyopenssl' and extra == 'group-7-urllib3-mypy')" }, +@@ -1718,9 +1718,9 @@ dependencies = [ + { name = "pygments" }, + { name = "tomli", marker = "python_full_version < '3.11' or (extra == 'group-7-urllib3-dev' and extra == 'group-7-urllib3-dev-min-pyopenssl') or (extra == 'group-7-urllib3-dev-min-pyopenssl' and extra == 'group-7-urllib3-mypy')" }, + ] +-sdist = { url = "https://files.pythonhosted.org/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c", size = 1572165, upload-time = "2026-04-07T17:16:18.027Z" } ++sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" } + wheels = [ +- { url = "https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9", size = 375249, upload-time = "2026-04-07T17:16:16.13Z" }, ++ { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" }, + ] + + [[package]] diff --git a/python-urllib3.spec b/python-urllib3.spec index 49ec528..aebd212 100644 --- a/python-urllib3.spec +++ b/python-urllib3.spec @@ -37,6 +37,9 @@ Patch: https://github.com/urllib3/urllib3/pull/5097.patch # https://github.com/urllib3/urllib3/pull/5103 rebased Patch: 5103.patch +# Compatibility with the latest pytest +Patch: https://github.com/urllib3/urllib3/commit/c420e267.patch + BuildArch: noarch BuildRequires: python3-devel