diff --git a/downstream-remove-pytest-subket.patch b/downstream-remove-pytest-subket.patch new file mode 100644 index 0000000..564794c --- /dev/null +++ b/downstream-remove-pytest-subket.patch @@ -0,0 +1,54 @@ +From 35378ae02912d704d466e4809070e17a8d13ad0a Mon Sep 17 00:00:00 2001 +From: Karolina Surma +Date: Thu, 7 Aug 2025 15:05:34 +0200 +Subject: [PATCH] Downstream-Only: Remove pytest-subket from tests + +--- + tests/conftest.py | 17 ----------------- + 1 file changed, 17 deletions(-) + +diff --git a/tests/conftest.py b/tests/conftest.py +index c98b871..ada7a7e 100644 +--- a/tests/conftest.py ++++ b/tests/conftest.py +@@ -451,18 +451,6 @@ def coverage_install( + return _common_wheel_editable_install(tmpdir_factory, common_wheels, "coverage") + + +-@pytest.fixture(scope="session") +-def socket_install(tmpdir_factory: pytest.TempPathFactory, common_wheels: Path) -> Path: +- lib_dir = _common_wheel_editable_install( +- tmpdir_factory, common_wheels, "pytest_subket" +- ) +- # pytest-subket is only included so it can intercept and block unexpected +- # network requests. It should NOT be visible to the pip under test. +- dist_info = next(lib_dir.glob("*.dist-info")) +- shutil.rmtree(dist_info) +- return lib_dir +- +- + def install_pth_link( + venv: VirtualEnvironment, project_name: str, lib_dir: Path + ) -> None: +@@ -480,7 +468,6 @@ def virtualenv_template( + setuptools_install: Path, + wheel_install: Path, + coverage_install: Path, +- socket_install: Path, + ) -> VirtualEnvironment: + venv_type: VirtualEnvironmentType + if request.config.getoption("--use-venv"): +@@ -495,10 +482,6 @@ def virtualenv_template( + # Install setuptools, wheel, pytest-subket, and pip. + install_pth_link(venv, "setuptools", setuptools_install) + install_pth_link(venv, "wheel", wheel_install) +- install_pth_link(venv, "pytest_subket", socket_install) +- # Also copy pytest-subket's .pth file so it can intercept socket calls. +- with open(venv.site / "pytest_socket.pth", "w") as f: +- f.write(socket_install.joinpath("pytest_socket.pth").read_text()) + + pth, dist_info = pip_editable_parts + +-- +2.50.1 + diff --git a/dummy-certifi.patch b/dummy-certifi.patch index 01e8756..ce34415 100644 --- a/dummy-certifi.patch +++ b/dummy-certifi.patch @@ -1,17 +1,17 @@ -From 0741e5a665308184ddbd20900f92e4417204092f Mon Sep 17 00:00:00 2001 +From 7b5fbac83944e3a0dd975ff17b69358791b68721 Mon Sep 17 00:00:00 2001 From: Karolina Surma Date: Thu, 27 Jun 2024 10:38:53 +0200 Subject: [PATCH] Dummy certifi patch --- - src/pip/_vendor/certifi/core.py | 110 ++------------------------------ - 1 file changed, 6 insertions(+), 104 deletions(-) + src/pip/_vendor/certifi/core.py | 80 +++------------------------------ + 1 file changed, 6 insertions(+), 74 deletions(-) diff --git a/src/pip/_vendor/certifi/core.py b/src/pip/_vendor/certifi/core.py -index 70e0c3b..eaf4210 100644 +index 2f2f7e0..bec6595 100644 --- a/src/pip/_vendor/certifi/core.py +++ b/src/pip/_vendor/certifi/core.py -@@ -4,111 +4,13 @@ certifi.py +@@ -4,80 +4,12 @@ certifi.py This module returns the installation location of cacert.pem or its contents. """ @@ -20,13 +20,13 @@ index 70e0c3b..eaf4210 100644 -def exit_cacert_ctx() -> None: - _CACERT_CTX.__exit__(None, None, None) # type: ignore[union-attr] - +# The RPM-packaged certifi always uses the system certificates +def where() -> str: + return '/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem' --if sys.version_info >= (3, 11): +-if sys.version_info >= (3, 11): +- - from importlib.resources import as_file, files - - _CACERT_CTX = None @@ -60,7 +60,7 @@ index 70e0c3b..eaf4210 100644 - def contents() -> str: - return files("pip._vendor.certifi").joinpath("cacert.pem").read_text(encoding="ascii") - --elif sys.version_info >= (3, 7): +-else: - - from importlib.resources import path as get_path, read_text - @@ -95,40 +95,9 @@ index 70e0c3b..eaf4210 100644 - - def contents() -> str: - return read_text("pip._vendor.certifi", "cacert.pem", encoding="ascii") -- --else: -- import os -- import types -- from typing import Union -- -- Package = Union[types.ModuleType, str] -- Resource = Union[str, "os.PathLike"] -- -- # This fallback will work for Python versions prior to 3.7 that lack the -- # importlib.resources module but relies on the existing `where` function -- # so won't address issues with environments like PyOxidizer that don't set -- # __file__ on modules. -- def read_text( -- package: Package, -- resource: Resource, -- encoding: str = 'utf-8', -- errors: str = 'strict' -- ) -> str: -- with open(where(), encoding=encoding) as data: -- return data.read() -- -- # If we don't have importlib.resources, then we will just do the old logic -- # of assuming we're on the filesystem and munge the path directly. -- def where() -> str: -- f = os.path.dirname(__file__) -- -- return os.path.join(f, "cacert.pem") -- -- def contents() -> str: -- return read_text("pip._vendor.certifi", "cacert.pem", encoding="ascii") +def contents() -> str: + with open(where(), encoding='utf=8') as data: + return data.read() -- -2.45.1 +2.50.1 diff --git a/nowarn-pip._internal.main.patch b/nowarn-pip._internal.main.patch deleted file mode 100644 index c8c98ed..0000000 --- a/nowarn-pip._internal.main.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 9d1e0a0e91cad143702b3a2d8c54bd765a5d9eb2 Mon Sep 17 00:00:00 2001 -From: Karolina Surma -Date: Thu, 27 Jun 2024 10:48:03 +0200 -Subject: [PATCH] Don't warn the user about pip._internal.main() entrypoint - -In Fedora, we use that in ensurepip and users cannot do anything about it, -this warning is juts moot. Also, the warning breaks CPython test suite. - -Co-Authored-By: =?UTF-8?q?Miro=20Hron=C4=8Dok?= ---- - src/pip/_internal/__init__.py | 2 +- - src/pip/_internal/utils/entrypoints.py | 19 ++++++++++--------- - tests/functional/test_cli.py | 3 ++- - 3 files changed, 13 insertions(+), 11 deletions(-) - -diff --git a/src/pip/_internal/__init__.py b/src/pip/_internal/__init__.py -index 1a5b7f8..682b9e4 100755 ---- a/src/pip/_internal/__init__.py -+++ b/src/pip/_internal/__init__.py -@@ -15,4 +15,4 @@ def main(args: Optional[List[str]] = None) -> int: - """ - from pip._internal.utils.entrypoints import _wrapper - -- return _wrapper(args) -+ return _wrapper(args, _nowarn=True) -diff --git a/src/pip/_internal/utils/entrypoints.py b/src/pip/_internal/utils/entrypoints.py -index 1501369..70034eb 100644 ---- a/src/pip/_internal/utils/entrypoints.py -+++ b/src/pip/_internal/utils/entrypoints.py -@@ -20,7 +20,7 @@ if WINDOWS: - ] - - --def _wrapper(args: Optional[List[str]] = None) -> int: -+def _wrapper(args: Optional[List[str]] = None, _nowarn: bool = False) -> int: - """Central wrapper for all old entrypoints. - - Historically pip has had several entrypoints defined. Because of issues -@@ -32,14 +32,15 @@ def _wrapper(args: Optional[List[str]] = None) -> int: - directing them to an appropriate place for help, we now define all of - our old entrypoints as wrappers for the current one. - """ -- sys.stderr.write( -- "WARNING: pip is being invoked by an old script wrapper. This will " -- "fail in a future version of pip.\n" -- "Please see https://github.com/pypa/pip/issues/5599 for advice on " -- "fixing the underlying issue.\n" -- "To avoid this problem you can invoke Python with '-m pip' instead of " -- "running pip directly.\n" -- ) -+ if not _nowarn: -+ sys.stderr.write( -+ "WARNING: pip is being invoked by an old script wrapper. This will " -+ "fail in a future version of pip.\n" -+ "Please see https://github.com/pypa/pip/issues/5599 for advice on " -+ "fixing the underlying issue.\n" -+ "To avoid this problem you can invoke Python with '-m pip' instead of " -+ "running pip directly.\n" -+ ) - return main(args) - - -diff --git a/tests/functional/test_cli.py b/tests/functional/test_cli.py -index e1ccf04..30b8f74 100644 ---- a/tests/functional/test_cli.py -+++ b/tests/functional/test_cli.py -@@ -49,7 +49,8 @@ def test_entrypoints_work(entrypoint: str, script: PipTestEnvironment) -> None: - result = script.pip("-V") - result2 = script.run("fake_pip", "-V", allow_stderr_warning=True) - assert result.stdout == result2.stdout -- assert "old script wrapper" in result2.stderr -+ if entrypoint[0] != "fake_pip = pip._internal:main": -+ assert "old script wrapper" in result2.stderr - - - @pytest.mark.parametrize( --- -2.45.1 - diff --git a/python3.14-file-urls.patch b/python3.14-file-urls.patch deleted file mode 100644 index 77e89de..0000000 --- a/python3.14-file-urls.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 03b4b94a0338d80d1f45697a5ea083a5e5c937db Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= -Date: Thu, 12 Jun 2025 23:36:24 +0200 -Subject: [PATCH] Adjust path_to_url et al. to produce the same results on - Python 3.14+ - -See https://github.com/python/cpython/issues/125974 -and https://github.com/pypa/pip/pull/13138#issuecomment-2567715303 ---- - src/pip/_internal/models/link.py | 6 +++++- - src/pip/_internal/utils/urls.py | 2 +- - tests/unit/test_urls.py | 2 +- - 3 files changed, 7 insertions(+), 3 deletions(-) - -diff --git a/src/pip/_internal/models/link.py b/src/pip/_internal/models/link.py -index f0560f6..38423d1 100644 ---- a/src/pip/_internal/models/link.py -+++ b/src/pip/_internal/models/link.py -@@ -4,6 +4,7 @@ import logging - import os - import posixpath - import re -+import sys - import urllib.parse - from dataclasses import dataclass - from typing import ( -@@ -134,7 +135,10 @@ def _clean_file_url_path(part: str) -> str: - # should not be quoted. On Linux where drive letters do not - # exist, the colon should be quoted. We rely on urllib.request - # to do the right thing here. -- return urllib.request.pathname2url(urllib.request.url2pathname(part)) -+ ret = urllib.request.pathname2url(urllib.request.url2pathname(part)) -+ if sys.version_info >= (3, 14): -+ ret = ret.removeprefix("//") -+ return ret - - - # percent-encoded: / -diff --git a/src/pip/_internal/utils/urls.py b/src/pip/_internal/utils/urls.py -index 9f34f88..e951a5e 100644 ---- a/src/pip/_internal/utils/urls.py -+++ b/src/pip/_internal/utils/urls.py -@@ -12,7 +12,7 @@ def path_to_url(path: str) -> str: - quoted path parts. - """ - path = os.path.normpath(os.path.abspath(path)) -- url = urllib.parse.urljoin("file:", urllib.request.pathname2url(path)) -+ url = urllib.parse.urljoin("file://", urllib.request.pathname2url(path)) - return url - - -diff --git a/tests/unit/test_urls.py b/tests/unit/test_urls.py -index 0c14525..2a56e45 100644 ---- a/tests/unit/test_urls.py -+++ b/tests/unit/test_urls.py -@@ -11,7 +11,7 @@ from pip._internal.utils.urls import path_to_url, url_to_path - def test_path_to_url_unix() -> None: - assert path_to_url("/tmp/file") == "file:///tmp/file" - path = os.path.join(os.getcwd(), "file") -- assert path_to_url("file") == "file://" + urllib.request.pathname2url(path) -+ assert path_to_url("file") == "file://" + path - - - @pytest.mark.skipif("sys.platform != 'win32'") --- -2.49.0 - diff --git a/python3.14-pip.spec b/python3.14-pip.spec index cfcec54..ee60cbd 100644 --- a/python3.14-pip.spec +++ b/python3.14-pip.spec @@ -8,7 +8,7 @@ %bcond man 1 %global srcname pip -%global base_version 25.1.1 +%global base_version 25.2 %global upstream_version %{base_version}%{?prerel} %global python_wheel_name %{srcname}-%{upstream_version}-py3-none-any.whl @@ -38,7 +38,6 @@ Summary: A tool for installing and managing Python packages # truststore: MIT # tomli: MIT # tomli-w: MIT -# typing-extensions: Python-2.0.1 # urllib3: MIT License: MIT AND Python-2.0.1 AND Apache-2.0 AND BSD-2-Clause AND BSD-3-Clause AND ISC AND MPL-2.0 AND (Apache-2.0 OR BSD-2-Clause) @@ -96,19 +95,15 @@ Patch: remove-existing-dist-only-if-path-conflicts.patch # The same patch is a part of the RPM-packaged python-certifi Patch: dummy-certifi.patch -# Don't warn the user about pip._internal.main() entrypoint -# In Fedora, we use that in ensurepip and users cannot do anything about it, -# this warning is juts moot. Also, the warning breaks CPython test suite. -Patch: nowarn-pip._internal.main.patch - -# Adjust path_to_url et al. to produce the same results on Python 3.14+ -# https://github.com/pypa/pip/pull/13423 -Patch: python3.14-file-urls.patch - # https://fedoraproject.org/wiki/Changes/dropingOfCertPemFile # https://github.com/sethmlarson/truststore/pull/183 Patch: truststore-pem-path.patch +# pytest-subket has been introduced to intercept network calls +# https://github.com/pypa/pip/commit/a4b40f62332ccb3228b12cc5ae1493c75177247a +# We don't need a layer to check that, as we're by default in an offline environment +Patch: downstream-remove-pytest-subket.patch + # Remove -s from Python shebang - ensure that packages installed with pip # to user locations are seen by pip itself %undefine _py3_shebang_s @@ -118,25 +113,24 @@ Patch: truststore-pem-path.patch # You can generate it with: # %%{_rpmconfigdir}/pythonbundles.py --namespace 'python%%{1}dist' src/pip/_vendor/vendor.txt %global bundled() %{expand: -Provides: bundled(python%{1}dist(cachecontrol)) = 0.14.2 -Provides: bundled(python%{1}dist(certifi)) = 2025.1.31 +Provides: bundled(python%{1}dist(cachecontrol)) = 0.14.3 +Provides: bundled(python%{1}dist(certifi)) = 2025.7.14 Provides: bundled(python%{1}dist(dependency-groups)) = 1.3.1 -Provides: bundled(python%{1}dist(distlib)) = 0.3.9 +Provides: bundled(python%{1}dist(distlib)) = 0.4 Provides: bundled(python%{1}dist(distro)) = 1.9 Provides: bundled(python%{1}dist(idna)) = 3.10 -Provides: bundled(python%{1}dist(msgpack)) = 1.1 +Provides: bundled(python%{1}dist(msgpack)) = 1.1.1 Provides: bundled(python%{1}dist(packaging)) = 25 -Provides: bundled(python%{1}dist(platformdirs)) = 4.3.7 -Provides: bundled(python%{1}dist(pygments)) = 2.19.1 +Provides: bundled(python%{1}dist(platformdirs)) = 4.3.8 +Provides: bundled(python%{1}dist(pygments)) = 2.19.2 Provides: bundled(python%{1}dist(pyproject-hooks)) = 1.2 -Provides: bundled(python%{1}dist(requests)) = 2.32.3 -Provides: bundled(python%{1}dist(resolvelib)) = 1.1 -Provides: bundled(python%{1}dist(rich)) = 14 +Provides: bundled(python%{1}dist(requests)) = 2.32.4 +Provides: bundled(python%{1}dist(resolvelib)) = 1.2 +Provides: bundled(python%{1}dist(rich)) = 14.1 Provides: bundled(python%{1}dist(setuptools)) = 70.3 Provides: bundled(python%{1}dist(tomli)) = 2.2.1 Provides: bundled(python%{1}dist(tomli-w)) = 1.2 Provides: bundled(python%{1}dist(truststore)) = 0.10.1 -Provides: bundled(python%{1}dist(typing-extensions)) = 4.13.2 Provides: bundled(python%{1}dist(urllib3)) = 1.26.20 } @@ -214,7 +208,10 @@ rm -v src/pip/_vendor/distlib/*.exe sed -i '/\.exe/d' pyproject.toml # Remove unused test requirements -sed -Ei '/(pytest-(cov|xdist|rerunfailures)|proxy\.py)/d' tests/requirements.txt +sed -Ei '/(pytest-(cov|xdist|rerunfailures|subket)|proxy\.py)/d' pyproject.toml + +# Remove unused pytest-subket options +sed -Ei '/(--disable-socket|--allow-unix-socket|--allow-hosts=localhost)/d' pyproject.toml %if %{with tests} # tests expect wheels in here @@ -227,7 +224,7 @@ cp -a %{SOURCE1} %{SOURCE2} %{SOURCE3} tests/data/common_wheels %generate_buildrequires # we only use this to generate test requires # the "pyproject" part is explicitly disabled as it generates a requirement on pip -%pyproject_buildrequires -N tests/requirements.txt +%pyproject_buildrequires -N -g test %endif diff --git a/remove-existing-dist-only-if-path-conflicts.patch b/remove-existing-dist-only-if-path-conflicts.patch index 20e5f28..d280f34 100644 --- a/remove-existing-dist-only-if-path-conflicts.patch +++ b/remove-existing-dist-only-if-path-conflicts.patch @@ -1,8 +1,11 @@ -From 9020f56e88a7dbaef688c147c281909f95b4e1d1 Mon Sep 17 00:00:00 2001 +From d5cb806a14bb50a96484bca6536e81f2ac316b9d Mon Sep 17 00:00:00 2001 From: Karolina Surma Date: Wed, 16 Feb 2022 08:36:21 +0100 Subject: [PATCH] Prevent removing of the system packages installed under /usr/lib when pip install --upgrade is executed. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit Resolves: rhbz#1550368 @@ -12,7 +15,6 @@ Co-Authored-By: Petr Viktorin Co-Authored-By: Lumir Balhar Co-Authored-By: Miro HronĨok Co-Authored-By: Karolina Surma - --- src/pip/_internal/metadata/base.py | 12 +++++++++++- src/pip/_internal/req/req_install.py | 2 +- @@ -21,10 +23,10 @@ Co-Authored-By: Karolina Surma 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/pip/_internal/metadata/base.py b/src/pip/_internal/metadata/base.py -index 9eabcdb..9816691 100644 +index 230e114..8bd5d31 100644 --- a/src/pip/_internal/metadata/base.py +++ b/src/pip/_internal/metadata/base.py -@@ -28,7 +28,7 @@ from pip._vendor.packaging.utils import NormalizedName, canonicalize_name +@@ -23,7 +23,7 @@ from pip._vendor.packaging.utils import NormalizedName, canonicalize_name from pip._vendor.packaging.version import Version from pip._internal.exceptions import NoneMetadataError @@ -33,7 +35,7 @@ index 9eabcdb..9816691 100644 from pip._internal.models.direct_url import ( DIRECT_URL_METADATA_NAME, DirectUrl, -@@ -578,6 +578,16 @@ class BaseDistribution(Protocol): +@@ -575,6 +575,16 @@ class BaseDistribution(Protocol): for extra in self._iter_egg_info_extras(): metadata["Provides-Extra"] = extra @@ -51,10 +53,10 @@ index 9eabcdb..9816691 100644 class BaseEnvironment: """An environment containing distributions to introspect.""" diff --git a/src/pip/_internal/req/req_install.py b/src/pip/_internal/req/req_install.py -index 2132785..0340890 100644 +index c9f6bff..c101826 100644 --- a/src/pip/_internal/req/req_install.py +++ b/src/pip/_internal/req/req_install.py -@@ -449,7 +449,7 @@ class InstallRequirement: +@@ -453,7 +453,7 @@ class InstallRequirement: f"lack sys.path precedence to {existing_dist.raw_name} " f"in {existing_dist.location}" ) @@ -64,10 +66,10 @@ index 2132785..0340890 100644 else: if self.editable: diff --git a/src/pip/_internal/resolution/legacy/resolver.py b/src/pip/_internal/resolution/legacy/resolver.py -index 1dd0d70..414bdbe 100644 +index 33a4fdc..1fe886e 100644 --- a/src/pip/_internal/resolution/legacy/resolver.py +++ b/src/pip/_internal/resolution/legacy/resolver.py -@@ -319,7 +319,9 @@ class Resolver(BaseResolver): +@@ -322,7 +322,9 @@ class Resolver(BaseResolver): # Don't uninstall the conflict if doing a user install and the # conflict is not a user install. assert req.satisfied_by is not None @@ -79,19 +81,19 @@ index 1dd0d70..414bdbe 100644 req.satisfied_by = None diff --git a/src/pip/_internal/resolution/resolvelib/factory.py b/src/pip/_internal/resolution/resolvelib/factory.py -index 1f31d83..3804774 100644 +index f23e4cd..1bada79 100644 --- a/src/pip/_internal/resolution/resolvelib/factory.py +++ b/src/pip/_internal/resolution/resolvelib/factory.py -@@ -1,6 +1,8 @@ +@@ -3,6 +3,8 @@ from __future__ import annotations import contextlib import functools import logging +import sys +import sysconfig + from collections.abc import Iterable, Iterator, Mapping, Sequence from typing import ( TYPE_CHECKING, - Callable, -@@ -617,6 +619,16 @@ class Factory: +@@ -615,6 +617,16 @@ class Factory: if dist is None: # Not installed, no uninstallation required. return None @@ -109,5 +111,5 @@ index 1f31d83..3804774 100644 # be uninstalled, no matter it's in global or user site, because the # user site installation has precedence over global. -- -2.45.1 +2.50.1 diff --git a/sources b/sources index 4c3846d..7230ff9 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ -SHA512 (pip-25.1.1.tar.gz) = ce61c9861265139b3c5ea9be9dc246097cd75c21687cf8301f80a377d02420c4524f0d6307d2ca0232ff8715b1105343bcfdb9cac6b69503780ab2c4645558dc +SHA512 (pip-25.2.tar.gz) = 5cc65c9091fdda7905e26ce32ddaa3a1c2fd287d69fd3da67c814ba7e8e5be59301d8327c06cdca78c1b95f4a5b5f75c87f36a549022408cc0e8f9411c0db11e SHA512 (setuptools-79.0.1-py3-none-any.whl) = fef6cfc6f95a5bb7320f1680e1c665cb8d9a4e4227cde4d8aab8a50bed4bcf04320085b9d7d5343359f887008db5c5a861e57f3d08b7b0b2311a28adaeee6b4a SHA512 (wheel-0.45.1-py3-none-any.whl) = 86c16248ec804ee0ac95d43b03d47351dceb534d0cdc4025ca1eb073e39e539de44c870b9261f0373144e1537f0e42675a759a318a8d5d346bbd9efcb704061d SHA512 (coverage-0-py3-none-any.whl) = e734192565347010efe68f8ba600254259c9b647f3c553fd4e5d87b1d7f955cb15d6f7d807716f4a6415d239beed945fbec7210feaf502e9cc849c332845926e