Skip to content

Commit

Permalink
Future-proof pip entrypoints special case (#1982)
Browse files Browse the repository at this point in the history
Update #1918 to handle pypa/pip#12536, where pip
removed their python minor entrypoint. The pip test is semi-functional
since it builds pip from source instead of using a wheel with the wrong
entrypoint, we have to update it when this pip version has a release.

Closes #1593.
  • Loading branch information
konstin authored Mar 1, 2024
1 parent e811070 commit d0ffabd
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 36 deletions.
18 changes: 12 additions & 6 deletions crates/install-wheel-rs/src/script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,20 @@ pub(crate) fn scripts_from_ini(
// Special case to generate versioned pip launchers.
// https://github.com/pypa/pip/blob/3898741e29b7279e7bffe044ecfbe20f6a438b1e/src/pip/_internal/operations/install/wheel.py#L283
// https://github.com/astral-sh/uv/issues/1593
for script in &mut console_scripts {
// Older pip versions have a wrong `pip3.x` launcher we have to remove, while newer pip versions
// (post https://github.com/pypa/pip/pull/12536) don't, ...
console_scripts.retain(|script| {
let Some((left, right)) = script.name.split_once('.') else {
continue;
return true;
};
if left != "pip3" || right.parse::<u8>().is_err() {
continue;
}
script.name = format!("pip3.{python_minor}");
!(left == "pip3" || right.parse::<u8>().is_ok())
});
// ... either has a `pip3` launcher we can use as template for the `pip3.x` users expect.
if let Some(pip_script) = console_scripts.iter().find(|script| script.name == "pip3") {
console_scripts.push(Script {
name: format!("pip3.{python_minor}"),
..pip_script.clone()
});
}

Ok((console_scripts, gui_scripts))
Expand Down
57 changes: 27 additions & 30 deletions crates/uv/tests/pip_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::process::Command;

use anyhow::Result;
use assert_cmd::prelude::*;
use assert_fs::fixture::ChildPath;
use assert_fs::prelude::*;
use indoc::indoc;
use url::Url;
Expand Down Expand Up @@ -2780,36 +2781,32 @@ fn set_read_permissions() -> Result<()> {
fn pip_entrypoints() -> Result<()> {
let context = TestContext::new("3.12");

let requirements_txt = context.temp_dir.child("requirements.txt");
requirements_txt.touch()?;
requirements_txt.write_str("pip==24.0")?;

uv_snapshot!(command(&context)
.arg("requirements.txt")
.arg("--strict"), @r###"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved 1 package in [TIME]
Downloaded 1 package in [TIME]
Installed 1 package in [TIME]
+ pip==24.0
"###
);

let bin_dir = context.venv.join(if cfg!(unix) {
"bin"
} else if cfg!(windows) {
"Scripts"
} else {
unimplemented!("Only Windows and Unix are supported")
});
// Pip 24.0 contains a pip3.10 launcher.
// https://inspector.pypi.io/project/pip/24.0/packages/8a/6a/19e9fe04fca059ccf770861c7d5721ab4c2aebc539889e97c7977528a53b/pip-24.0-py3-none-any.whl/pip-24.0.dist-info/entry_points.txt
assert!(!bin_dir.join(format!("pip3.10{EXE_SUFFIX}")).exists());
assert!(bin_dir.join(format!("pip3.12{EXE_SUFFIX}")).exists());
// TODO(konstin): Remove git dep when the next pip version is released.
for pip_requirement in ["pip==24.0", "pip @ git+https://github.com/pypa/pip"] {
let requirements_txt = context.temp_dir.child("requirements.txt");
requirements_txt.touch()?;
requirements_txt.write_str(pip_requirement)?;

command(&context)
.arg("requirements.txt")
.arg("--strict")
.output()
.expect("Failed to install pip");

let bin_dir = context.venv.join(if cfg!(unix) {
"bin"
} else if cfg!(windows) {
"Scripts"
} else {
unimplemented!("Only Windows and Unix are supported")
});
// Pip 24.0 contains a pip3.10 launcher.
// https://inspector.pypi.io/project/pip/24.0/packages/8a/6a/19e9fe04fca059ccf770861c7d5721ab4c2aebc539889e97c7977528a53b/pip-24.0-py3-none-any.whl/pip-24.0.dist-info/entry_points.txt
ChildPath::new(bin_dir.join(format!("pip3.10{EXE_SUFFIX}")))
.assert(predicates::path::missing());
ChildPath::new(bin_dir.join(format!("pip3.12{EXE_SUFFIX}")))
.assert(predicates::path::exists());
}

Ok(())
}
Expand Down

0 comments on commit d0ffabd

Please sign in to comment.