From e384d1032c189312ac21f23844c9c6f1f4750eb1 Mon Sep 17 00:00:00 2001 From: Richard Si Date: Sat, 26 Jul 2025 16:10:41 -0400 Subject: [PATCH 1/3] Declare Python 3.14 support --- .github/workflows/ci.yml | 2 ++ docs/html/development/ci.rst | 15 ++++++++++++++- news/13506.feature.rst | 1 + noxfile.py | 2 +- pyproject.toml | 1 + 5 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 news/13506.feature.rst diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 815617e1c19..f3d69fa5763 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -122,6 +122,7 @@ jobs: - "3.11" - "3.12" - "3.13" + - "3.14" steps: - uses: actions/checkout@v4 @@ -181,6 +182,7 @@ jobs: # - "3.11" # - "3.12" - "3.13" + - "3.14" group: - { number: 1, pytest-filter: "not test_install" } - { number: 2, pytest-filter: "test_install" } diff --git a/docs/html/development/ci.rst b/docs/html/development/ci.rst index f2db084addb..031c283d815 100644 --- a/docs/html/development/ci.rst +++ b/docs/html/development/ci.rst @@ -23,6 +23,7 @@ pip support a variety of Python interpreters: - CPython 3.11 - CPython 3.12 - CPython 3.13 +- CPython 3.14 - Latest PyPy3 on different operating systems: @@ -37,7 +38,7 @@ and on different architectures: - x86 - arm64 (macOS only) -so 49 hypothetical interpreters. +so 56 hypothetical interpreters. Checks @@ -100,6 +101,8 @@ Actual testing | | +-------+---------------+-----------------+ | | | CP3.13| | | | | +-------+---------------+-----------------+ +| | | CP3.14| | | +| | +-------+---------------+-----------------+ | | | PyPy3 | | | | Windows +----------+-------+---------------+-----------------+ | | x64 | CP3.9 | GitHub | GitHub | @@ -112,6 +115,8 @@ Actual testing | | +-------+---------------+-----------------+ | | | CP3.13| GitHub | GitHub | | | +-------+---------------+-----------------+ +| | | CP3.14| GitHub | GitHub | +| | +-------+---------------+-----------------+ | | | PyPy3 | | | +-----------+----------+-------+---------------+-----------------+ | | x86 | CP3.9 | | | @@ -124,6 +129,8 @@ Actual testing | | +-------+---------------+-----------------+ | | | CP3.13| | | | | +-------+---------------+-----------------+ +| | | CP3.14| | | +| | +-------+---------------+-----------------+ | | | PyPy3 | | | | Linux +----------+-------+---------------+-----------------+ | | x64 | CP3.9 | GitHub | GitHub | @@ -136,6 +143,8 @@ Actual testing | | +-------+---------------+-----------------+ | | | CP3.13| GitHub | GitHub | | | +-------+---------------+-----------------+ +| | | CP3.14| GitHub | GitHub | +| | +-------+---------------+-----------------+ | | | PyPy3 | | | +-----------+----------+-------+---------------+-----------------+ | | arm64 | CP3.9 | GitHub | GitHub | @@ -148,6 +157,8 @@ Actual testing | | +-------+---------------+-----------------+ | | | CP3.13| GitHub | GitHub | | | +-------+---------------+-----------------+ +| | | CP3.14| GitHub | GitHub | +| | +-------+---------------+-----------------+ | | | PyPy3 | | | | macOS +----------+-------+---------------+-----------------+ | | x64 | CP3.9 | GitHub | GitHub | @@ -160,5 +171,7 @@ Actual testing | | +-------+---------------+-----------------+ | | | CP3.13| GitHub | GitHub | | | +-------+---------------+-----------------+ +| | | CP3.14| GitHub | GitHub | +| | +-------+---------------+-----------------+ | | | PyPy3 | | | +-----------+----------+-------+---------------+-----------------+ diff --git a/news/13506.feature.rst b/news/13506.feature.rst new file mode 100644 index 00000000000..597ea4546aa --- /dev/null +++ b/news/13506.feature.rst @@ -0,0 +1 @@ +Declare support for Python 3.14 diff --git a/noxfile.py b/noxfile.py index 160e823e9f1..88e9d5dec66 100644 --- a/noxfile.py +++ b/noxfile.py @@ -67,7 +67,7 @@ def should_update_common_wheels() -> bool: # ----------------------------------------------------------------------------- # Development Commands # ----------------------------------------------------------------------------- -@nox.session(python=["3.9", "3.10", "3.11", "3.12", "3.13", "pypy3"]) +@nox.session(python=["3.9", "3.10", "3.11", "3.12", "3.13", "3.14", "pypy3"]) def test(session: nox.Session) -> None: # Get the common wheels. if should_update_common_wheels(): diff --git a/pyproject.toml b/pyproject.toml index 019cab5eb3f..9ebc0854445 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,6 +23,7 @@ classifiers = [ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", ] From 2773b13baa59ec68b03df9f0f73e4e3c21fcd958 Mon Sep 17 00:00:00 2001 From: Richard Si Date: Mon, 28 Jul 2025 15:47:47 -0400 Subject: [PATCH 2/3] Reformat and add --allow-unix-socket to pytest config Seems like some underlying change in multiprocessing or some related module in Python 3.14 now means our test suite uses unix sockets. We have a pytest plugin installed that blocks sockets by default to avoid mistakenly adding tests that rely on the Internet. Local unix sockets are totally fine, of course. I've added them to the allowlist. --- pyproject.toml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 9ebc0854445..2da4e4aa2b5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -300,7 +300,15 @@ follow_imports = "skip" # [tool.pytest.ini_options] -addopts = "--ignore src/pip/_vendor --ignore tests/tests_cache -r aR --color=yes --disable-socket --allow-hosts=localhost" +addopts = [ + "-r=aR", + "--color=yes", + "--ignore=src/pip/_vendor", + "--ignore=tests/tests_cache", + "--disable-socket", + "--allow-unix-socket", + "--allow-hosts=localhost", +] xfail_strict = true markers = [ "network: tests that need network", From 775a86f2bac8894771911ab068b18f09550cb6f0 Mon Sep 17 00:00:00 2001 From: Richard Si Date: Mon, 28 Jul 2025 16:53:16 -0400 Subject: [PATCH 3/3] Fix broken unit tests & xfail weird failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed the test_unsupported_hashes and test_install_editable_with_wrong_egg_name tests to use pip's own path -> URL function instead of simply adding file:// which results in the malformed file://C:/. This will be handled gracefully in the next 3.14 release (as a matter of backwards compatibility) but the test suite shouldn't be relying on such behaviour anyway. Marked test_build_deps_use_proxy_from_cli as a xfail on Python 3.14+ because it seems to be an intermittent issue with proxy.py or something else with our test suite. I can only reproduce the failure locally if I run the test suite with two workers 🙃. Given it doesn't seem to be a problem with pip itself, I'm prioritizing getting 25.2 released on time than doing a full proper investigation into what's wrong. --- tests/functional/test_install.py | 2 +- tests/functional/test_proxy.py | 6 ++++++ tests/unit/test_req.py | 9 +++------ 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/tests/functional/test_install.py b/tests/functional/test_install.py index f23b156dcf7..a1bd81d31d0 100644 --- a/tests/functional/test_install.py +++ b/tests/functional/test_install.py @@ -1880,7 +1880,7 @@ def test_install_editable_with_wrong_egg_name( result = script.pip( "install", "--editable", - f"file://{pkga_path}#egg=pkgb", + path_to_url(str(pkga_path)) + "#egg=pkgb", expect_error=(resolver_variant == "resolvelib"), ) assert ( diff --git a/tests/functional/test_proxy.py b/tests/functional/test_proxy.py index 3f9db4a958b..32eb94a1edf 100644 --- a/tests/functional/test_proxy.py +++ b/tests/functional/test_proxy.py @@ -1,4 +1,5 @@ import ssl +import sys from pathlib import Path from typing import Any @@ -92,6 +93,11 @@ def test_proxy_does_not_override_netrc( script.assert_installed(simple="3.0") +@pytest.mark.xfail( + sys.version_info >= (3, 14), + reason="Access logs are blank intermittently on 3.14", + strict=False, +) @pytest.mark.network def test_build_deps_use_proxy_from_cli( script: PipTestEnvironment, capfd: pytest.CaptureFixture[str], data: TestData diff --git a/tests/unit/test_req.py b/tests/unit/test_req.py index 0547131134e..a2c4cf243ca 100644 --- a/tests/unit/test_req.py +++ b/tests/unit/test_req.py @@ -51,6 +51,7 @@ handle_requirement_line, ) from pip._internal.resolution.legacy.resolver import Resolver +from pip._internal.utils.urls import path_to_url from tests.lib import TestData, make_test_finder, requirements_file, wheel @@ -224,16 +225,12 @@ def test_unsupported_hashes(self, data: TestData) -> None: dir_path = data.packages.joinpath("FSPkg") reqset.add_unnamed_requirement( get_processed_req_from_line( - f"file://{dir_path}", + path_to_url(str(dir_path)), lineno=2, ) ) finder = make_test_finder(find_links=[data.find_links]) - sep = os.path.sep - if sep == "\\": - sep = "\\\\" # This needs to be escaped for the regex - with self._basic_resolver(finder, require_hashes=True) as resolver: with pytest.raises( HashErrors, @@ -244,7 +241,7 @@ def test_unsupported_hashes(self, data: TestData) -> None: r"file \(line 1\)\)\n" r"Can't verify hashes for these file:// requirements because " r"they point to directories:\n" - rf" file://.*{sep}data{sep}packages{sep}FSPkg " + r" file://.*/data/packages/FSPkg " r"\(from -r file \(line 2\)\)" ), ):