diff --git a/news/truststore.vendor.rst b/news/truststore.vendor.rst new file mode 100644 index 00000000000..f8ce27e4b32 --- /dev/null +++ b/news/truststore.vendor.rst @@ -0,0 +1 @@ +Upgrade truststore to 0.10.1 diff --git a/src/pip/_vendor/truststore/__init__.py b/src/pip/_vendor/truststore/__init__.py index e468bf8cebd..cdff8143feb 100644 --- a/src/pip/_vendor/truststore/__init__.py +++ b/src/pip/_vendor/truststore/__init__.py @@ -7,7 +7,7 @@ # Detect Python runtimes which don't implement SSLObject.get_unverified_chain() API # This API only became public in Python 3.13 but was available in CPython and PyPy since 3.10. -if _sys.version_info < (3, 13): +if _sys.version_info < (3, 13) and _sys.implementation.name not in ("cpython", "pypy"): try: import ssl as _ssl except ImportError: @@ -33,4 +33,4 @@ del _api, _sys # type: ignore[name-defined] # noqa: F821 __all__ = ["SSLContext", "inject_into_ssl", "extract_from_ssl"] -__version__ = "0.10.0" +__version__ = "0.10.1" diff --git a/src/pip/_vendor/truststore/_api.py b/src/pip/_vendor/truststore/_api.py index aeb023af756..2c0ce196a36 100644 --- a/src/pip/_vendor/truststore/_api.py +++ b/src/pip/_vendor/truststore/_api.py @@ -5,7 +5,7 @@ import sys import typing -import _ssl # type: ignore[import-not-found] +import _ssl from ._ssl_constants import ( _original_SSLContext, @@ -43,6 +43,23 @@ def inject_into_ssl() -> None: except ImportError: pass + # requests starting with 2.32.0 added a preloaded SSL context to improve concurrent performance; + # this unfortunately leads to a RecursionError, which can be avoided by patching the preloaded SSL context with + # the truststore patched instance + # also see https://github.com/psf/requests/pull/6667 + try: + from pip._vendor.requests import adapters as requests_adapters + + preloaded_context = getattr(requests_adapters, "_preloaded_ssl_context", None) + if preloaded_context is not None: + setattr( + requests_adapters, + "_preloaded_ssl_context", + SSLContext(ssl.PROTOCOL_TLS_CLIENT), + ) + except ImportError: + pass + def extract_from_ssl() -> None: """Restores the :class:`ssl.SSLContext` class to its original state""" diff --git a/src/pip/_vendor/vendor.txt b/src/pip/_vendor/vendor.txt index f04a9c1e73c..4a1933596b6 100644 --- a/src/pip/_vendor/vendor.txt +++ b/src/pip/_vendor/vendor.txt @@ -15,4 +15,4 @@ rich==13.9.4 resolvelib==1.0.1 setuptools==70.3.0 tomli==2.2.1 -truststore==0.10.0 +truststore==0.10.1 diff --git a/tools/vendoring/patches/truststore.patch b/tools/vendoring/patches/truststore.patch new file mode 100644 index 00000000000..d8d6351d9d4 --- /dev/null +++ b/tools/vendoring/patches/truststore.patch @@ -0,0 +1,20 @@ +diff --git a/src/pip/_vendor/truststore/_api.py b/src/pip/_vendor/truststore/_api.py +index 47b7a63ab..d09d3096f 100644 +--- a/src/pip/_vendor/truststore/_api.py ++++ b/src/pip/_vendor/truststore/_api.py +@@ -48,12 +48,12 @@ def inject_into_ssl() -> None: + # the truststore patched instance + # also see https://github.com/psf/requests/pull/6667 + try: +- import requests.adapters ++ from pip._vendor.requests import adapters as requests_adapters + +- preloaded_context = getattr(requests.adapters, "_preloaded_ssl_context", None) ++ preloaded_context = getattr(requests_adapters, "_preloaded_ssl_context", None) + if preloaded_context is not None: + setattr( +- requests.adapters, ++ requests_adapters, + "_preloaded_ssl_context", + SSLContext(ssl.PROTOCOL_TLS_CLIENT), + )