From 0a8331ee38193e965f51b0c798f02def913228a6 Mon Sep 17 00:00:00 2001 From: enoekki Date: Thu, 15 Aug 2024 14:33:21 -0400 Subject: [PATCH] Fix issue 12890 --- news/12890.bugfix.rst | 1 + src/pip/_internal/commands/install.py | 26 +++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 news/12890.bugfix.rst diff --git a/news/12890.bugfix.rst b/news/12890.bugfix.rst new file mode 100644 index 00000000000..731e50b5f16 --- /dev/null +++ b/news/12890.bugfix.rst @@ -0,0 +1 @@ +Fix the incorrect version displayed with pip list when using --target and PYTHONPATH. diff --git a/src/pip/_internal/commands/install.py b/src/pip/_internal/commands/install.py index ad45a2f2a57..fa444ee4caa 100644 --- a/src/pip/_internal/commands/install.py +++ b/src/pip/_internal/commands/install.py @@ -2,6 +2,7 @@ import json import operator import os +import re import shutil import site from optparse import SUPPRESS_HELP, Values @@ -574,7 +575,15 @@ def _handle_target_dir( shutil.rmtree(target_item_dir) else: os.remove(target_item_dir) - + if item.endswith((".dist-info", ".egg-info")): + matched_info_dir = _contain_info_dir(item, target_dir) + if matched_info_dir: + if not upgrade: + continue + else: + info_dir = os.path.join(target_dir, matched_info_dir) + if os.path.exists(info_dir): + shutil.rmtree(info_dir) shutil.move(os.path.join(lib_dir, item), target_item_dir) def _determine_conflicts( @@ -781,3 +790,18 @@ def create_os_error_message( ) return "".join(parts).strip() + "\n" + + +def _contain_info_dir(item: str, target_dir: str) -> Optional[str]: + """Determine whether the item is a metadata_location + (.dist-info or egg-info for legacy). + If there is another metadata_location for the package in the 'target_dir', + return found metadata_location that has been found. + """ + raw_name = item.rpartition(".")[0].partition("-")[0] + dist_info_re = re.compile(rf"{raw_name}-[a-z0-9_.!+-]+\.dist-info$", re.IGNORECASE) + egg_info_re = re.compile(rf"{raw_name}[^\s/\\]*\.egg-info$", re.IGNORECASE) + for path in os.listdir(target_dir): + if dist_info_re.match(path) or egg_info_re.match(path): + return path + return None