From 2c195f9c2ccf3a040cad185f5cb4f63795501f8e Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Wed, 26 Oct 2022 16:24:19 +0800 Subject: [PATCH] Fix multi-digit version in entry point replacement Previously, the special case to generate 'pip' and 'easy_install' entry points with the correct Python version (e.g. 'pip3.9' on Python 3.9) only accounted for single-digit version segments, and did not work correctly on Python 3.10 and up. This was missed when Python 3.10 was released because we (accidentally) generated wheels that did not need any such replacements, but was exposed in CPython 3.11.0 since it bundled pip 22.3 generated against Python 3.10. --- news/11547.bugfix.rst | 3 ++ src/pip/_internal/operations/install/wheel.py | 4 +-- tests/unit/test_wheel.py | 35 ++++++++++++++++++- 3 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 news/11547.bugfix.rst diff --git a/news/11547.bugfix.rst b/news/11547.bugfix.rst new file mode 100644 index 00000000000..05aa2d3176a --- /dev/null +++ b/news/11547.bugfix.rst @@ -0,0 +1,3 @@ +Fix entry point generation of ``pip.X``, ``pipX.Y``, and ``easy_install-X.Y`` +to correctly account for multi-digit Python version segments (e.g. the "11" +part 3.11). diff --git a/src/pip/_internal/operations/install/wheel.py b/src/pip/_internal/operations/install/wheel.py index 1650d59a374..c79941398a2 100644 --- a/src/pip/_internal/operations/install/wheel.py +++ b/src/pip/_internal/operations/install/wheel.py @@ -325,7 +325,7 @@ def get_console_script_specs(console: Dict[str, str]) -> List[str]: scripts_to_generate.append(f"pip{get_major_minor_version()} = {pip_script}") # Delete any other versioned pip entry points - pip_ep = [k for k in console if re.match(r"pip(\d(\.\d)?)?$", k)] + pip_ep = [k for k in console if re.match(r"pip(\d+(\.\d+)?)?$", k)] for k in pip_ep: del console[k] easy_install_script = console.pop("easy_install", None) @@ -340,7 +340,7 @@ def get_console_script_specs(console: Dict[str, str]) -> List[str]: ) # Delete any other versioned easy_install entry points easy_install_ep = [ - k for k in console if re.match(r"easy_install(-\d\.\d)?$", k) + k for k in console if re.match(r"easy_install(-\d+\.\d+)?$", k) ] for k in easy_install_ep: del console[k] diff --git a/tests/unit/test_wheel.py b/tests/unit/test_wheel.py index 6aec64702d2..d93d458d146 100644 --- a/tests/unit/test_wheel.py +++ b/tests/unit/test_wheel.py @@ -3,6 +3,7 @@ import logging import os import pathlib +import sys import textwrap from email import message_from_string from pathlib import Path @@ -22,7 +23,11 @@ from pip._internal.models.scheme import Scheme from pip._internal.operations.build.wheel_legacy import get_legacy_build_wheel_path from pip._internal.operations.install import wheel -from pip._internal.operations.install.wheel import InstalledCSVRow, RecordPath +from pip._internal.operations.install.wheel import ( + InstalledCSVRow, + RecordPath, + get_console_script_specs, +) from pip._internal.utils.compat import WINDOWS from pip._internal.utils.misc import hash_file from pip._internal.utils.unpacking import unpack_file @@ -681,3 +686,31 @@ def test_rehash(self, tmpdir: Path) -> None: h, length = wheel.rehash(os.fspath(self.test_file)) assert length == str(self.test_file_len) assert h == self.test_file_hash_encoded + + +def test_get_console_script_specs_replaces_python_version( + monkeypatch: pytest.MonkeyPatch, +) -> None: + # Fake Python version. + monkeypatch.setattr(sys, "version_info", (10, 11)) + + entry_points = { + "pip": "real_pip", + "pip99": "whatever", + "pip99.88": "whatever", + "easy_install": "real_easy_install", + "easy_install-99.88": "whatever", + # The followings shouldn't be replaced. + "not_pip_or_easy_install-99": "whatever", + "not_pip_or_easy_install-99.88": "whatever", + } + specs = get_console_script_specs(entry_points) + assert specs == [ + "pip = real_pip", + "pip10 = real_pip", + "pip10.11 = real_pip", + "easy_install = real_easy_install", + "easy_install-10.11 = real_easy_install", + "not_pip_or_easy_install-99 = whatever", + "not_pip_or_easy_install-99.88 = whatever", + ]