diff --git a/avoid-importing-distutils-globally.patch b/avoid-importing-distutils-globally.patch new file mode 100644 index 0000000..dfee223 --- /dev/null +++ b/avoid-importing-distutils-globally.patch @@ -0,0 +1,260 @@ +From 572694adc951836c60a92fe38c8612ad06a09da3 Mon Sep 17 00:00:00 2001 +From: Tzu-ping Chung +Date: Mon, 18 Jul 2022 04:48:31 +0800 +Subject: [PATCH] Avoid importing distutils globally +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The distutils module is deprecated in 3.11 so we should avoid importing +it unless absolutely necessary to avoid emitting superfulous warnings. + +Rebased from https://github.com/pypa/pip/commit/0e06452530 + +Also includes: Import distutils only if needed, but sooner + +Rebased from: https://github.com/pypa/pip/commit/db47515958 + +Co-Authored-By: Stéphane Bidoul +--- + src/pip/_internal/locations/__init__.py | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/src/pip/_internal/locations/__init__.py b/src/pip/_internal/locations/__init__.py +index dba182d..4cb45dc 100644 +--- a/src/pip/_internal/locations/__init__.py ++++ b/src/pip/_internal/locations/__init__.py +@@ -11,7 +11,7 @@ from pip._internal.utils.compat import WINDOWS + from pip._internal.utils.deprecation import deprecated + from pip._internal.utils.virtualenv import running_under_virtualenv + +-from . import _distutils, _sysconfig ++from . import _sysconfig + from .base import ( + USER_CACHE_DIR, + get_major_minor_version, +@@ -47,6 +47,12 @@ _PLATLIBDIR: str = getattr(sys, "platlibdir", "lib") + + _USE_SYSCONFIG = sys.version_info >= (3, 10) + ++if not _USE_SYSCONFIG: ++ # Import distutils lazily to avoid deprecation warnings, ++ # but import it soon enough that it is in memory and available during ++ # a pip reinstall. ++ from . import _distutils ++ + + def _looks_like_bpo_44860() -> bool: + """The resolution to bpo-44860 will change this incorrect platlib. +-- +2.38.1 + +From 942f43f0bab6f8245f2597a4fd376702bffb88e9 Mon Sep 17 00:00:00 2001 +From: Pradyun Gedam +Date: Fri, 17 Jun 2022 13:50:25 +0100 +Subject: [PATCH] Replace usage of `distutils.utils.change_root` with + copied-over logic + +This eliminates an import from distutils, by pulling in the relevant code +into pip itself. + +Rebased from https://github.com/pypa/pip/commit/c520ccf75d +--- + src/pip/_internal/locations/_sysconfig.py | 5 ++-- + src/pip/_internal/locations/base.py | 28 +++++++++++++++++++ + .../_internal/operations/install/legacy.py | 2 +- + 3 files changed, 31 insertions(+), 4 deletions(-) + +diff --git a/src/pip/_internal/locations/_sysconfig.py b/src/pip/_internal/locations/_sysconfig.py +index 5e141aa..0bbc928 100644 +--- a/src/pip/_internal/locations/_sysconfig.py ++++ b/src/pip/_internal/locations/_sysconfig.py +@@ -1,4 +1,3 @@ +-import distutils.util # FIXME: For change_root. + import logging + import os + import sys +@@ -9,7 +8,7 @@ from pip._internal.exceptions import InvalidSchemeCombination, UserInstallationI + from pip._internal.models.scheme import SCHEME_KEYS, Scheme + from pip._internal.utils.virtualenv import running_under_virtualenv + +-from .base import get_major_minor_version, is_osx_framework ++from .base import change_root, get_major_minor_version, is_osx_framework + + logger = logging.getLogger(__name__) + +@@ -194,7 +193,7 @@ def get_scheme( + ) + if root is not None: + for key in SCHEME_KEYS: +- value = distutils.util.change_root(root, getattr(scheme, key)) ++ value = change_root(root, getattr(scheme, key)) + setattr(scheme, key, value) + return scheme + +diff --git a/src/pip/_internal/locations/base.py b/src/pip/_internal/locations/base.py +index 86dad4a..d73676d 100644 +--- a/src/pip/_internal/locations/base.py ++++ b/src/pip/_internal/locations/base.py +@@ -5,6 +5,7 @@ import sys + import sysconfig + import typing + ++from pip._internal.exceptions import InstallationError + from pip._internal.utils import appdirs + from pip._internal.utils.virtualenv import running_under_virtualenv + +@@ -22,6 +23,33 @@ def get_major_minor_version() -> str: + """ + return "{}.{}".format(*sys.version_info) + ++def change_root(new_root: str, pathname: str) -> str: ++ """Return 'pathname' with 'new_root' prepended. ++ ++ If 'pathname' is relative, this is equivalent to os.path.join(new_root, pathname). ++ Otherwise, it requires making 'pathname' relative and then joining the ++ two, which is tricky on DOS/Windows and Mac OS. ++ ++ This is borrowed from Python's standard library's distutils module. ++ """ ++ if os.name == "posix": ++ if not os.path.isabs(pathname): ++ return os.path.join(new_root, pathname) ++ else: ++ return os.path.join(new_root, pathname[1:]) ++ ++ elif os.name == "nt": ++ (drive, path) = os.path.splitdrive(pathname) ++ if path[0] == "\\": ++ path = path[1:] ++ return os.path.join(new_root, path) ++ ++ else: ++ raise InstallationError( ++ f"Unknown platform: {os.name}\n" ++ "Can not change root path prefix on unknown platform." ++ ) ++ + + def get_src_prefix() -> str: + if running_under_virtualenv(): +diff --git a/src/pip/_internal/operations/install/legacy.py b/src/pip/_internal/operations/install/legacy.py +index 2206c93..4281cb0 100644 +--- a/src/pip/_internal/operations/install/legacy.py ++++ b/src/pip/_internal/operations/install/legacy.py +@@ -3,11 +3,11 @@ + + import logging + import os +-from distutils.util import change_root + from typing import List, Optional, Sequence + + from pip._internal.build_env import BuildEnvironment + from pip._internal.exceptions import InstallationError ++from pip._internal.locations.base import change_root + from pip._internal.models.scheme import Scheme + from pip._internal.utils.logging import indent_log + from pip._internal.utils.misc import ensure_dir +-- +2.38.1 + +From 4ef5c7eac10bb1d88568af53373491fe6febfa63 Mon Sep 17 00:00:00 2001 +From: Pradyun Gedam +Date: Fri, 17 Jun 2022 15:30:50 +0100 +Subject: [PATCH] Replace `distutils.fancy_getopt` with `getopt` + +This eliminates one location where distutils may be imported on +Python 3.12+, by replacing the logic with mostly equivalent logic. + +Rebased from: https://github.com/pypa/pip/commit/8cbb89b6cc +--- + src/pip/_internal/utils/distutils_args.py | 51 ++++++++++++----------- + tests/unit/test_utils_distutils_args.py | 2 +- + 2 files changed, 27 insertions(+), 26 deletions(-) + +diff --git a/src/pip/_internal/utils/distutils_args.py b/src/pip/_internal/utils/distutils_args.py +index e4aa5b8..2fd1862 100644 +--- a/src/pip/_internal/utils/distutils_args.py ++++ b/src/pip/_internal/utils/distutils_args.py +@@ -1,42 +1,43 @@ +-from distutils.errors import DistutilsArgError +-from distutils.fancy_getopt import FancyGetopt ++from getopt import GetoptError, getopt + from typing import Dict, List + + _options = [ +- ("exec-prefix=", None, ""), +- ("home=", None, ""), +- ("install-base=", None, ""), +- ("install-data=", None, ""), +- ("install-headers=", None, ""), +- ("install-lib=", None, ""), +- ("install-platlib=", None, ""), +- ("install-purelib=", None, ""), +- ("install-scripts=", None, ""), +- ("prefix=", None, ""), +- ("root=", None, ""), +- ("user", None, ""), ++ "exec-prefix=", ++ "home=", ++ "install-base=", ++ "install-data=", ++ "install-headers=", ++ "install-lib=", ++ "install-platlib=", ++ "install-purelib=", ++ "install-scripts=", ++ "prefix=", ++ "root=", ++ "user", + ] + + +-# typeshed doesn't permit Tuple[str, None, str], see python/typeshed#3469. +-_distutils_getopt = FancyGetopt(_options) # type: ignore +- +- + def parse_distutils_args(args: List[str]) -> Dict[str, str]: +- """Parse provided arguments, returning an object that has the +- matched arguments. ++ """Parse provided arguments, returning an object that has the matched arguments. + + Any unknown arguments are ignored. + """ + result = {} + for arg in args: + try: +- _, match = _distutils_getopt.getopt(args=[arg]) +- except DistutilsArgError: ++ parsed_opt, _ = getopt(args=[arg], shortopts="", longopts=_options) ++ except GetoptError: + # We don't care about any other options, which here may be + # considered unrecognized since our option list is not + # exhaustive. +- pass +- else: +- result.update(match.__dict__) ++ continue ++ ++ if not parsed_opt: ++ continue ++ ++ option = parsed_opt[0] ++ name_from_parsed = option[0][2:].replace("-", "_") ++ value_from_parsed = option[1] or "true" ++ result[name_from_parsed] = value_from_parsed ++ + return result +diff --git a/tests/unit/test_utils_distutils_args.py b/tests/unit/test_utils_distutils_args.py +index e63c565..21f31e9 100644 +--- a/tests/unit/test_utils_distutils_args.py ++++ b/tests/unit/test_utils_distutils_args.py +@@ -60,4 +60,4 @@ def test_all_value_options_work(name: str, value: str) -> None: + + def test_user_option_works() -> None: + result = parse_distutils_args(["--user"]) +- assert result["user"] == 1 ++ assert result["user"] +-- +2.38.1 + diff --git a/python-pip.spec b/python-pip.spec index f6cc58c..935c1c0 100644 --- a/python-pip.spec +++ b/python-pip.spec @@ -21,7 +21,7 @@ Name: python-%{srcname} Version: %{base_version}%{?prerel:~%{prerel}} -Release: 2%{?dist} +Release: 4%{?dist} Summary: A tool for installing and managing Python packages # We bundle a lot of libraries with pip, which itself is under MIT license. @@ -86,6 +86,15 @@ Patch5: nowarn-pip._internal.main.patch # Upstream issue: https://github.com/pypa/packaging/issues/368 Patch6: no-version-warning.patch +# Avoid importing distutils globally +# This is needed to make the pip wheel usable with Python 3.12+ +# Backported from pip 22.3 +# https://github.com/pypa/pip/commit/0e06452530 +# https://github.com/pypa/pip/commit/db47515958 +# https://github.com/pypa/pip/commit/c520ccf75d +# https://github.com/pypa/pip/commit/8cbb89b6cc +Patch7: avoid-importing-distutils-globally.patch + # Downstream only patch # Users might have local installations of pip from using # `pip install --user --upgrade pip` on older/newer versions. @@ -203,10 +212,8 @@ Recommends: python%{python3_pkgversion}-setuptools Provides: pip = %{version}-%{release} Conflicts: python-pip < %{version}-%{release} -# The python3.10 version that added the rpm_prefix sysconfig install scheme -# This pip can also function with the previous version, -# but it would remove RPM-installed packages during sudo pip install --upgrade. -Requires: python3-libs >= 3.10.0-2 +# The python3.10 version that stopped using the rpm_prefix scheme +Requires: python3-libs >= 3.10.6-2 %{crypt_compat_recommends 3} @@ -402,6 +409,13 @@ pytest_k='not completion and %{python_wheel_dir}/%{python_wheel_name} %changelog +* Wed Nov 16 2022 Miro Hrončok - 21.3.1-4 +- Make python-pip-wheel compatible with Python 3.12.0a2+ + +* Tue Sep 06 2022 Miro Hrončok - 21.3.1-3 +- No longer use the rpm_install prefix to determine RPM-installed packages +- Related: rhbz#2026979 + * Fri Jan 21 2022 Fedora Release Engineering - 21.3.1-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild diff --git a/remove-existing-dist-only-if-path-conflicts.patch b/remove-existing-dist-only-if-path-conflicts.patch index 7ff95e5..a1265a0 100644 --- a/remove-existing-dist-only-if-path-conflicts.patch +++ b/remove-existing-dist-only-if-path-conflicts.patch @@ -103,8 +103,8 @@ index 766dc26..c8c1cd8 100644 + # Prevent uninstalling packages from /usr + try: + if dist_location(dist._dist) in ( -+ sysconfig.get_path('purelib', scheme='rpm_prefix', vars={'base': sys.base_prefix}), -+ sysconfig.get_path('platlib', scheme='rpm_prefix', vars={'base': sys.base_prefix}), ++ sysconfig.get_path('purelib', scheme='posix_prefix', vars={'base': sys.base_prefix}), ++ sysconfig.get_path('platlib', scheme='posix_prefix', vars={'platbase': sys.base_prefix}), + ): + return None + except KeyError: # this Python doesn't have 'rpm_prefix' scheme yet diff --git a/tests/tests.yml b/tests/tests.yml index a543138..65e165e 100644 --- a/tests/tests.yml +++ b/tests/tests.yml @@ -31,6 +31,9 @@ - smoke311: dir: python/smoke run: VERSION=3.11 ./venv.sh + - smoke312: + dir: python/smoke + run: VERSION=3.12 ./venv.sh - smoke27: dir: python/smoke run: VERSION=2.7 METHOD=virtualenv ./venv.sh @@ -55,6 +58,9 @@ - smoke311_virtualenv: dir: python/smoke run: VERSION=3.11 METHOD=virtualenv ./venv.sh + - smoke312_virtualenv: + dir: python/smoke + run: VERSION=3.12 METHOD=virtualenv ./venv.sh - pipenv: run: pipenv --three && pipenv install six - pyproject_pytest: @@ -80,6 +86,7 @@ - python3.9 - python3.10 - python3.11 + - python3.12-devel - python2-devel - python3-devel - python3-tox