diff --git a/news/certifi.vendor.rst b/news/certifi.vendor.rst new file mode 100644 index 00000000000..9ce7d403ec3 --- /dev/null +++ b/news/certifi.vendor.rst @@ -0,0 +1 @@ +Upgrade certifi to 2026.2.25 diff --git a/news/requests.vendor.rst b/news/requests.vendor.rst new file mode 100644 index 00000000000..8aea9cc8ddd --- /dev/null +++ b/news/requests.vendor.rst @@ -0,0 +1 @@ +Upgrade requests to 2.33.1 diff --git a/news/tomli.vendor.rst b/news/tomli.vendor.rst new file mode 100644 index 00000000000..98507625e93 --- /dev/null +++ b/news/tomli.vendor.rst @@ -0,0 +1 @@ +Upgrade tomli to 2.3.1 diff --git a/src/pip/_vendor/certifi/__init__.py b/src/pip/_vendor/certifi/__init__.py index 090fd58487b..16c0c7c268f 100644 --- a/src/pip/_vendor/certifi/__init__.py +++ b/src/pip/_vendor/certifi/__init__.py @@ -1,4 +1,4 @@ from .core import contents, where __all__ = ["contents", "where"] -__version__ = "2026.01.04" +__version__ = "2026.02.25" diff --git a/src/pip/_vendor/certifi/cacert.pem b/src/pip/_vendor/certifi/cacert.pem index 132db0df1b8..5ec1afe02d4 100644 --- a/src/pip/_vendor/certifi/cacert.pem +++ b/src/pip/_vendor/certifi/cacert.pem @@ -4429,7 +4429,7 @@ YmH5LVerVrkR3SW+ak5KGoJr3M/TvEqzPNcum9v4KGm8ay3sMaE641c= # Issuer: CN=OISTE Server Root RSA G1 O=OISTE Foundation # Subject: CN=OISTE Server Root RSA G1 O=OISTE Foundation -# Label: " OISTE Server Root RSA G1" +# Label: "OISTE Server Root RSA G1" # Serial: 113845518112613905024960613408179309848 # MD5 Fingerprint: 23:a7:9e:d4:70:b8:b9:14:57:41:8a:7e:44:59:e2:68 # SHA1 Fingerprint: f7:00:34:25:94:88:68:31:e4:34:87:3f:70:fe:86:b3:86:9f:f0:6e @@ -4466,3 +4466,29 @@ J8tRd/iWkx7P8nd9H0aTolkelUTFLXVksNb54Dxp6gS1HAviRkRNQzuXSXERvSS2 wq1yVAb+axj5d9spLFKebXd7Yv0PTY6YMjAwcRLWJTXjn/hvnLXrahut6hDTlhZy BiElxky8j3C7DOReIoMt0r7+hVu05L0= -----END CERTIFICATE----- + +# Issuer: CN=e-Szigno TLS Root CA 2023 O=Microsec Ltd. +# Subject: CN=e-Szigno TLS Root CA 2023 O=Microsec Ltd. +# Label: "e-Szigno TLS Root CA 2023" +# Serial: 71934828665710877219916191754 +# MD5 Fingerprint: 6a:e9:99:74:a5:da:5e:f1:d9:2e:f2:c8:d1:86:8b:71 +# SHA1 Fingerprint: 6f:9a:d5:d5:df:e8:2c:eb:be:37:07:ee:4f:4f:52:58:29:41:d1:fe +# SHA256 Fingerprint: b4:91:41:50:2d:00:66:3d:74:0f:2e:7e:c3:40:c5:28:00:96:26:66:12:1a:36:d0:9c:f7:dd:2b:90:38:4f:b4 +-----BEGIN CERTIFICATE----- +MIICzzCCAjGgAwIBAgINAOhvGHvWOWuYSkmYCjAKBggqhkjOPQQDBDB1MQswCQYD +VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0 +ZC4xFzAVBgNVBGEMDlZBVEhVLTIzNTg0NDk3MSIwIAYDVQQDDBllLVN6aWdubyBU +TFMgUm9vdCBDQSAyMDIzMB4XDTIzMDcxNzE0MDAwMFoXDTM4MDcxNzE0MDAwMFow +dTELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRYwFAYDVQQKDA1NaWNy +b3NlYyBMdGQuMRcwFQYDVQRhDA5WQVRIVS0yMzU4NDQ5NzEiMCAGA1UEAwwZZS1T +emlnbm8gVExTIFJvb3QgQ0EgMjAyMzCBmzAQBgcqhkjOPQIBBgUrgQQAIwOBhgAE +AGgP36J8PKp0iGEKjcJMpQEiFNT3YHdCnAo4YKGMZz6zY+n6kbCLS+Y53wLCMAFS +AL/fjO1ZrTJlqwlZULUZwmgcAOAFX9pQJhzDrAQixTpN7+lXWDajwRlTEArRzT/v +SzUaQ49CE0y5LBqcvjC2xN7cS53kpDzLLtmt3999Cd8ukv+ho2MwYTAPBgNVHRMB +Af8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUWYQCYlpGePVd3I8K +ECgj3NXW+0UwHwYDVR0jBBgwFoAUWYQCYlpGePVd3I8KECgj3NXW+0UwCgYIKoZI +zj0EAwQDgYsAMIGHAkIBLdqu9S54tma4n7Zwf2Z0z+yOfP7AAXmazlIC58PRDHpt +y7Ve7hekm9sEdu4pKeiv+62sUvTXK9Z3hBC9xdIoaDQCQTV2WnXzkoYI9bIeCvZl +C9p2x1L/Cx6AcCIwwzPbGO2E14vs7dOoY4G1VnxHx1YwlGhza9IuqbnZLBwpvQy6 +uWWL +-----END CERTIFICATE----- diff --git a/src/pip/_vendor/requests/__init__.py b/src/pip/_vendor/requests/__init__.py index 04230fc8d9a..81d38590ad2 100644 --- a/src/pip/_vendor/requests/__init__.py +++ b/src/pip/_vendor/requests/__init__.py @@ -68,8 +68,8 @@ def check_compatibility(urllib3_version, chardet_version, charset_normalizer_ver if chardet_version: major, minor, patch = chardet_version.split(".")[:3] major, minor, patch = int(major), int(minor), int(patch) - # chardet_version >= 3.0.2, < 6.0.0 - assert (3, 0, 2) <= (major, minor, patch) < (6, 0, 0) + # chardet_version >= 3.0.2, < 8.0.0 + assert (3, 0, 2) <= (major, minor, patch) < (8, 0, 0) elif charset_normalizer_version: major, minor, patch = charset_normalizer_version.split(".")[:3] major, minor, patch = int(major), int(minor), int(patch) @@ -88,8 +88,8 @@ def _check_cryptography(cryptography_version): return if cryptography_version < [1, 3, 4]: - warning = "Old version of cryptography ({}) may cause slowdown.".format( - cryptography_version + warning = ( + f"Old version of cryptography ({cryptography_version}) may cause slowdown." ) warnings.warn(warning, RequestsDependencyWarning) @@ -101,10 +101,9 @@ def _check_cryptography(cryptography_version): ) except (AssertionError, ValueError): warnings.warn( - "urllib3 ({}) or chardet ({})/charset_normalizer ({}) doesn't match a supported " - "version!".format( - urllib3.__version__, chardet_version, charset_normalizer_version - ), + f"urllib3 ({urllib3.__version__}) or chardet " + f"({chardet_version})/charset_normalizer ({charset_normalizer_version}) " + "doesn't match a supported version!", RequestsDependencyWarning, ) diff --git a/src/pip/_vendor/requests/__version__.py b/src/pip/_vendor/requests/__version__.py index effdd98cf15..7f8a52c8565 100644 --- a/src/pip/_vendor/requests/__version__.py +++ b/src/pip/_vendor/requests/__version__.py @@ -5,8 +5,8 @@ __title__ = "requests" __description__ = "Python HTTP for Humans." __url__ = "https://requests.readthedocs.io" -__version__ = "2.32.5" -__build__ = 0x023205 +__version__ = "2.33.1" +__build__ = 0x023301 __author__ = "Kenneth Reitz" __author_email__ = "me@kennethreitz.org" __license__ = "Apache-2.0" diff --git a/src/pip/_vendor/requests/_internal_utils.py b/src/pip/_vendor/requests/_internal_utils.py index f2cf635e293..b7cf4695b07 100644 --- a/src/pip/_vendor/requests/_internal_utils.py +++ b/src/pip/_vendor/requests/_internal_utils.py @@ -5,14 +5,15 @@ Provides utility functions that are consumed internally by Requests which depend on extremely few external helpers (such as compat) """ + import re from .compat import builtin_str -_VALID_HEADER_NAME_RE_BYTE = re.compile(rb"^[^:\s][^:\r\n]*$") -_VALID_HEADER_NAME_RE_STR = re.compile(r"^[^:\s][^:\r\n]*$") -_VALID_HEADER_VALUE_RE_BYTE = re.compile(rb"^\S[^\r\n]*$|^$") -_VALID_HEADER_VALUE_RE_STR = re.compile(r"^\S[^\r\n]*$|^$") +_VALID_HEADER_NAME_RE_BYTE = re.compile(rb"^[^:\s][^:\r\n]*\Z") +_VALID_HEADER_NAME_RE_STR = re.compile(r"^[^:\s][^:\r\n]*\Z") +_VALID_HEADER_VALUE_RE_BYTE = re.compile(rb"^\S[^\r\n]*\Z|^\Z") +_VALID_HEADER_VALUE_RE_STR = re.compile(r"^\S[^\r\n]*\Z|^\Z") _HEADER_VALIDATORS_STR = (_VALID_HEADER_NAME_RE_STR, _VALID_HEADER_VALUE_RE_STR) _HEADER_VALIDATORS_BYTE = (_VALID_HEADER_NAME_RE_BYTE, _VALID_HEADER_VALUE_RE_BYTE) diff --git a/src/pip/_vendor/requests/adapters.py b/src/pip/_vendor/requests/adapters.py index 67ccebcbea0..da8959e7787 100644 --- a/src/pip/_vendor/requests/adapters.py +++ b/src/pip/_vendor/requests/adapters.py @@ -11,17 +11,19 @@ import typing import warnings -from pip._vendor.urllib3.exceptions import ClosedPoolError, ConnectTimeoutError -from pip._vendor.urllib3.exceptions import HTTPError as _HTTPError -from pip._vendor.urllib3.exceptions import InvalidHeader as _InvalidHeader from pip._vendor.urllib3.exceptions import ( + ClosedPoolError, + ConnectTimeoutError, LocationValueError, MaxRetryError, NewConnectionError, ProtocolError, + ReadTimeoutError, + ResponseError, ) +from pip._vendor.urllib3.exceptions import HTTPError as _HTTPError +from pip._vendor.urllib3.exceptions import InvalidHeader as _InvalidHeader from pip._vendor.urllib3.exceptions import ProxyError as _ProxyError -from pip._vendor.urllib3.exceptions import ReadTimeoutError, ResponseError from pip._vendor.urllib3.exceptions import SSLError as _SSLError from pip._vendor.urllib3.poolmanager import PoolManager, proxy_from_url from pip._vendor.urllib3.util import Timeout as TimeoutSauce @@ -47,7 +49,6 @@ from .structures import CaseInsensitiveDict from .utils import ( DEFAULT_CA_BUNDLE_PATH, - extract_zipped_paths, get_auth_from_url, get_encoding_from_headers, prepend_scheme_if_needed, @@ -76,9 +77,9 @@ def SOCKSProxyManager(*args, **kwargs): def _urllib3_request_context( request: "PreparedRequest", verify: "bool | str | None", - client_cert: "typing.Tuple[str, str] | str | None", + client_cert: "tuple[str, str] | str | None", poolmanager: "PoolManager", -) -> "(typing.Dict[str, typing.Any], typing.Dict[str, typing.Any])": +) -> "(dict[str, typing.Any], dict[str, typing.Any])": host_params = {} pool_kwargs = {} parsed_request_url = urlparse(request.url) @@ -297,7 +298,7 @@ def cert_verify(self, conn, url, verify, cert): cert_loc = verify if not cert_loc: - cert_loc = extract_zipped_paths(DEFAULT_CA_BUNDLE_PATH) + cert_loc = DEFAULT_CA_BUNDLE_PATH if not cert_loc or not os.path.exists(cert_loc): raise OSError( diff --git a/src/pip/_vendor/requests/auth.py b/src/pip/_vendor/requests/auth.py index 4a7ce6dc146..c39b645189d 100644 --- a/src/pip/_vendor/requests/auth.py +++ b/src/pip/_vendor/requests/auth.py @@ -35,9 +35,9 @@ def _basic_auth_str(username, password): if not isinstance(username, basestring): warnings.warn( "Non-string usernames will no longer be supported in Requests " - "3.0.0. Please convert the object you've passed in ({!r}) to " + f"3.0.0. Please convert the object you've passed in ({username!r}) to " "a string or bytes object in the near future to avoid " - "problems.".format(username), + "problems.", category=DeprecationWarning, ) username = str(username) @@ -45,9 +45,9 @@ def _basic_auth_str(username, password): if not isinstance(password, basestring): warnings.warn( "Non-string passwords will no longer be supported in Requests " - "3.0.0. Please convert the object you've passed in ({!r}) to " + f"3.0.0. Please convert the object you've passed in ({type(password)!r}) to " "a string or bytes object in the near future to avoid " - "problems.".format(type(password)), + "problems.", category=DeprecationWarning, ) password = str(password) diff --git a/src/pip/_vendor/requests/certs.py b/src/pip/_vendor/requests/certs.py index 2743144b994..c5953485fe8 100644 --- a/src/pip/_vendor/requests/certs.py +++ b/src/pip/_vendor/requests/certs.py @@ -11,6 +11,7 @@ environment, you can change the definition of where() to return a separately packaged CA bundle. """ + from pip._vendor.certifi import where if __name__ == "__main__": diff --git a/src/pip/_vendor/requests/exceptions.py b/src/pip/_vendor/requests/exceptions.py index 7f3660f00d9..d84504881a4 100644 --- a/src/pip/_vendor/requests/exceptions.py +++ b/src/pip/_vendor/requests/exceptions.py @@ -4,6 +4,7 @@ This module contains the set of Requests' exceptions. """ + from pip._vendor.urllib3.exceptions import HTTPError as BaseHTTPError from .compat import JSONDecodeError as CompatJSONDecodeError diff --git a/src/pip/_vendor/requests/help.py b/src/pip/_vendor/requests/help.py index ddbb6150d64..022cd6062e0 100644 --- a/src/pip/_vendor/requests/help.py +++ b/src/pip/_vendor/requests/help.py @@ -40,11 +40,8 @@ def _implementation(): if implementation == "CPython": implementation_version = platform.python_version() elif implementation == "PyPy": - implementation_version = "{}.{}.{}".format( - sys.pypy_version_info.major, - sys.pypy_version_info.minor, - sys.pypy_version_info.micro, - ) + pypy = sys.pypy_version_info + implementation_version = f"{pypy.major}.{pypy.minor}.{pypy.micro}" if sys.pypy_version_info.releaselevel != "final": implementation_version = "".join( [implementation_version, sys.pypy_version_info.releaselevel] diff --git a/src/pip/_vendor/requests/hooks.py b/src/pip/_vendor/requests/hooks.py index d181ba2ec2e..5976bc7d0f2 100644 --- a/src/pip/_vendor/requests/hooks.py +++ b/src/pip/_vendor/requests/hooks.py @@ -9,6 +9,7 @@ ``response``: The response generated from a Request. """ + HOOKS = ["response"] diff --git a/src/pip/_vendor/requests/models.py b/src/pip/_vendor/requests/models.py index 22de95c0612..ba7c01d9b3e 100644 --- a/src/pip/_vendor/requests/models.py +++ b/src/pip/_vendor/requests/models.py @@ -34,9 +34,11 @@ builtin_str, chardet, cookielib, + urlencode, + urlsplit, + urlunparse, ) from .compat import json as complexjson -from .compat import urlencode, urlsplit, urlunparse from .cookies import _copy_cookie_jar, cookiejar_from_dict, get_cookie_header from .exceptions import ( ChunkedEncodingError, @@ -45,11 +47,11 @@ HTTPError, InvalidJSONError, InvalidURL, + MissingSchema, + StreamConsumedError, ) from .exceptions import JSONDecodeError as RequestsJSONDecodeError -from .exceptions import MissingSchema from .exceptions import SSLError as RequestsSSLError -from .exceptions import StreamConsumedError from .hooks import default_hooks from .status_codes import codes from .structures import CaseInsensitiveDict diff --git a/src/pip/_vendor/requests/sessions.py b/src/pip/_vendor/requests/sessions.py index 731550de88a..578cc44d5c1 100644 --- a/src/pip/_vendor/requests/sessions.py +++ b/src/pip/_vendor/requests/sessions.py @@ -5,6 +5,7 @@ This module provides a Session object to manage and persist settings across requests (cookies, auth, proxies). """ + import os import sys import time @@ -421,6 +422,8 @@ def __init__(self): #: expired certificates, which will make your application vulnerable to #: man-in-the-middle (MitM) attacks. #: Only set this to `False` for testing. + #: If verify is set to a string, it must be the path to a CA bundle file + #: that will be used to verify the TLS certificate. self.verify = True #: SSL client certificate default, if String, path to ssl client diff --git a/src/pip/_vendor/requests/utils.py b/src/pip/_vendor/requests/utils.py index e8ea5ad3674..6ee16b58037 100644 --- a/src/pip/_vendor/requests/utils.py +++ b/src/pip/_vendor/requests/utils.py @@ -39,9 +39,6 @@ getproxies_environment, integer_types, is_urllib3_1, -) -from .compat import parse_http_list as _parse_list_header -from .compat import ( proxy_bypass, proxy_bypass_environment, quote, @@ -50,6 +47,7 @@ urlparse, urlunparse, ) +from .compat import parse_http_list as _parse_list_header from .cookies import cookiejar_from_dict from .exceptions import ( FileModeWarning, @@ -61,6 +59,7 @@ NETRC_FILES = (".netrc", "_netrc") +# Certificate is extracted by certifi when needed. DEFAULT_CA_BUNDLE_PATH = certs.where() DEFAULT_PORTS = {"http": 80, "https": 443} @@ -233,7 +232,7 @@ def get_netrc_auth(url, raise_errors=False): try: _netrc = netrc(netrc_path).authenticators(host) - if _netrc: + if _netrc and any(_netrc): # Return with login / password login_i = 0 if _netrc[0] else 1 return (_netrc[login_i], _netrc[2]) @@ -283,12 +282,13 @@ def extract_zipped_paths(path): return path # we have a valid zip archive and a valid member of that archive - tmp = tempfile.gettempdir() - extracted_path = os.path.join(tmp, member.split("/")[-1]) - if not os.path.exists(extracted_path): - # use read + write to avoid the creating nested folders, we only want the file, avoids mkdir racing condition - with atomic_open(extracted_path) as file_handler: - file_handler.write(zip_file.read(member)) + suffix = os.path.splitext(member.split("/")[-1])[-1] + fd, extracted_path = tempfile.mkstemp(suffix=suffix) + try: + os.write(fd, zip_file.read(member)) + finally: + os.close(fd) + return extracted_path @@ -502,26 +502,23 @@ def get_encodings_from_content(content): def _parse_content_type_header(header): - """Returns content type and parameters from given header + """Returns content type and parameters from given header. :param header: string :return: tuple containing content type and dictionary of - parameters + parameters. """ tokens = header.split(";") content_type, params = tokens[0].strip(), tokens[1:] params_dict = {} - items_to_strip = "\"' " + strip_chars = "\"' " for param in params: param = param.strip() - if param: - key, value = param, True - index_of_equals = param.find("=") - if index_of_equals != -1: - key = param[:index_of_equals].strip(items_to_strip) - value = param[index_of_equals + 1 :].strip(items_to_strip) + if param and (idx := param.find("=")) != -1: + key = param[:idx].strip(strip_chars) + value = param[idx + 1 :].strip(strip_chars) params_dict[key.lower()] = value return content_type, params_dict diff --git a/src/pip/_vendor/tomli/__init__.py b/src/pip/_vendor/tomli/__init__.py index 9395b043827..aaecab11f9c 100644 --- a/src/pip/_vendor/tomli/__init__.py +++ b/src/pip/_vendor/tomli/__init__.py @@ -3,6 +3,6 @@ # Licensed to PSF under a Contributor Agreement. __all__ = ("loads", "load", "TOMLDecodeError") -__version__ = "2.3.0" # DO NOT EDIT THIS LINE MANUALLY. LET bump2version UTILITY DO IT +__version__ = "2.3.1" # DO NOT EDIT THIS LINE MANUALLY. LET bump2version UTILITY DO IT from ._parser import TOMLDecodeError, load, loads diff --git a/src/pip/_vendor/tomli/_parser.py b/src/pip/_vendor/tomli/_parser.py index 26170e8ed56..f81f468a84f 100644 --- a/src/pip/_vendor/tomli/_parser.py +++ b/src/pip/_vendor/tomli/_parser.py @@ -34,6 +34,13 @@ # lower number than where mypyc binaries crash. MAX_INLINE_NESTING: Final = sys.getrecursionlimit() +# Pathologically excessive number of parts in a key runs into quadratic +# behavior (e.g. in Flags.is_). +# Even if keys aren't currently parsed using recursion, they name a +# recursive structure, so it makes sense to limit it using getrecursionlimit() +# and RecursionError. +MAX_KEY_PARTS: Final = sys.getrecursionlimit() + ASCII_CTRL: Final = frozenset(chr(i) for i in range(32)) | frozenset(chr(127)) # Neither of these sets include quotation mark or backslash. They are @@ -145,7 +152,7 @@ def load(__fp: IO[bytes], *, parse_float: ParseFloat = float) -> dict[str, Any]: return loads(s, parse_float=parse_float) -def loads(__s: str, *, parse_float: ParseFloat = float) -> dict[str, Any]: # noqa: C901 +def loads(__s: str, *, parse_float: ParseFloat = float) -> dict[str, Any]: """Parse TOML from a string.""" # The spec allows converting "\r\n" to "\n", even in string @@ -474,6 +481,10 @@ def parse_key(src: str, pos: Pos) -> tuple[Pos, Key]: pos = skip_chars(src, pos, TOML_WS) pos, key_part = parse_key_part(src, pos) key += (key_part,) + if len(key) > MAX_KEY_PARTS: + raise RecursionError( + f"TOML key has more than the allowed {MAX_KEY_PARTS} parts" + ) pos = skip_chars(src, pos, TOML_WS) @@ -676,7 +687,7 @@ def parse_basic_str(src: str, pos: Pos, *, multiline: bool) -> tuple[Pos, str]: pos += 1 -def parse_value( # noqa: C901 +def parse_value( src: str, pos: Pos, parse_float: ParseFloat, nest_lvl: int ) -> tuple[Pos, Any]: if nest_lvl > MAX_INLINE_NESTING: diff --git a/src/pip/_vendor/vendor.txt b/src/pip/_vendor/vendor.txt index dd2f5f34853..e4c2faad021 100644 --- a/src/pip/_vendor/vendor.txt +++ b/src/pip/_vendor/vendor.txt @@ -5,15 +5,15 @@ msgpack==1.1.2 packaging==26.0 platformdirs==4.5.1 pyproject-hooks==1.2.0 -requests==2.32.5 - certifi==2026.1.4 +requests==2.33.1 + certifi==2026.2.25 idna==3.11 urllib3==1.26.20 rich==14.2.0 pygments==2.19.2 resolvelib==1.2.1 setuptools==70.3.0 -tomli==2.3.0 +tomli==2.3.1 tomli-w==1.2.0 truststore==0.10.4 dependency-groups==1.3.1