From 11ed4f7183cc25a00f23e86bd264d4055645eed2 Mon Sep 17 00:00:00 2001 From: konsti Date: Fri, 23 Feb 2024 19:01:31 +0100 Subject: [PATCH] Generate versioned pip launchers (#1918) Users expect pip to have `pip`, `pip3` and `pip3.x` entrypoints. But pip is a universal wheel, so it contains the `pip3.x` entrypoint where it was built on. To fix this, pip special cases itself when installing (https://github.com/pypa/pip/blob/3898741e29b7279e7bffe044ecfbe20f6a438b1e/src/pip/_internal/operations/install/wheel.py#L283), replacing the wheel entrypoint with one for the current version. We now do the same. Fixes #1593 --- crates/install-wheel-rs/src/linker.rs | 29 +++++------------- crates/install-wheel-rs/src/script.rs | 41 +++++++++++++++++++++++++- crates/install-wheel-rs/src/wheel.rs | 34 +++++++--------------- crates/uv/tests/pip_sync.rs | 42 +++++++++++++++++++++++++++ 4 files changed, 100 insertions(+), 46 deletions(-) diff --git a/crates/install-wheel-rs/src/linker.rs b/crates/install-wheel-rs/src/linker.rs index 6275994f9..36facd2bd 100644 --- a/crates/install-wheel-rs/src/linker.rs +++ b/crates/install-wheel-rs/src/linker.rs @@ -4,7 +4,6 @@ use std::path::Path; use std::str::FromStr; -use configparser::ini::Ini; use fs_err as fs; use fs_err::{DirEntry, File}; use reflink_copy as reflink; @@ -17,9 +16,9 @@ use pypi_types::DirectUrl; use uv_normalize::PackageName; use crate::install_location::InstallLocation; +use crate::script::scripts_from_ini; use crate::wheel::{ - extra_dist_info, install_data, parse_metadata, parse_wheel_version, read_scripts_from_section, - write_script_entrypoints, + extra_dist_info, install_data, parse_metadata, parse_wheel_version, write_script_entrypoints, }; use crate::{read_record_file, Error, Script}; @@ -99,7 +98,8 @@ pub fn install_wheel( let mut record = read_record_file(&mut record_file)?; debug!(name, "Writing entrypoints"); - let (console_scripts, gui_scripts) = parse_scripts(&wheel, &dist_info_prefix, None)?; + let (console_scripts, gui_scripts) = + parse_scripts(&wheel, &dist_info_prefix, None, location.python_version().1)?; write_script_entrypoints( &site_packages, location, @@ -200,11 +200,12 @@ fn dist_info_metadata(dist_info_prefix: &str, wheel: impl AsRef) -> Result /// /// Returns (`script_name`, module, function) /// -/// Extras are supposed to be ignored, which happens if you pass None for extras +/// Extras are supposed to be ignored, which happens if you pass None for extras. fn parse_scripts( wheel: impl AsRef, dist_info_prefix: &str, extras: Option<&[String]>, + python_minor: u8, ) -> Result<(Vec