mirror of https://github.com/astral-sh/uv
Avoid erroring on omitted wheel-only packages in `pylock.toml` (#13132)
## Summary Closes https://github.com/astral-sh/uv/issues/13127.
This commit is contained in:
parent
1cafcd0ad9
commit
17b4ebed8e
|
|
@ -62,6 +62,8 @@ pub enum PylockTomlError {
|
|||
"Package `{0}` must include one of: `wheels`, `directory`, `archive`, `sdist`, or `vcs`"
|
||||
)]
|
||||
MissingSource(PackageName),
|
||||
#[error("Package `{0}` does not include a compatible wheel for the current platform")]
|
||||
MissingWheel(PackageName),
|
||||
#[error("`packages.wheel` entry for `{0}` must have a `path` or `url`")]
|
||||
WheelMissingPathUrl(PackageName),
|
||||
#[error("`packages.sdist` entry for `{0}` must have a `path` or `url`")]
|
||||
|
|
@ -863,6 +865,11 @@ impl<'lock> PylockToml {
|
|||
let root = graph.add_node(Node::Root);
|
||||
|
||||
for package in self.packages {
|
||||
// Omit packages that aren't relevant to the current environment.
|
||||
if !package.marker.evaluate(markers, &[]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
match (
|
||||
package.wheels.is_some(),
|
||||
package.sdist.is_some(),
|
||||
|
|
@ -901,12 +908,12 @@ impl<'lock> PylockToml {
|
|||
(_, _, _, true, true) => {
|
||||
return Err(PylockTomlError::VcsWithArchive(package.name.clone()));
|
||||
}
|
||||
(false, false, false, false, false) => {
|
||||
return Err(PylockTomlError::MissingSource(package.name.clone()));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// Omit packages that aren't relevant to the current environment.
|
||||
let install = package.marker.evaluate(markers, &[]);
|
||||
|
||||
// Search for a matching wheel.
|
||||
let dist = if let Some(best_wheel) = package.find_best_wheel(tags) {
|
||||
let hashes = HashDigests::from(best_wheel.hashes.clone());
|
||||
|
|
@ -926,7 +933,7 @@ impl<'lock> PylockToml {
|
|||
Node::Dist {
|
||||
dist,
|
||||
hashes,
|
||||
install,
|
||||
install: true,
|
||||
}
|
||||
} else if let Some(sdist) = package.sdist.as_ref() {
|
||||
let hashes = HashDigests::from(sdist.hashes.clone());
|
||||
|
|
@ -943,7 +950,7 @@ impl<'lock> PylockToml {
|
|||
Node::Dist {
|
||||
dist,
|
||||
hashes,
|
||||
install,
|
||||
install: true,
|
||||
}
|
||||
} else if let Some(sdist) = package.directory.as_ref() {
|
||||
let hashes = HashDigests::empty();
|
||||
|
|
@ -957,7 +964,7 @@ impl<'lock> PylockToml {
|
|||
Node::Dist {
|
||||
dist,
|
||||
hashes,
|
||||
install,
|
||||
install: true,
|
||||
}
|
||||
} else if let Some(sdist) = package.vcs.as_ref() {
|
||||
let hashes = HashDigests::empty();
|
||||
|
|
@ -971,7 +978,7 @@ impl<'lock> PylockToml {
|
|||
Node::Dist {
|
||||
dist,
|
||||
hashes,
|
||||
install,
|
||||
install: true,
|
||||
}
|
||||
} else if let Some(dist) = package.archive.as_ref() {
|
||||
let hashes = HashDigests::from(dist.hashes.clone());
|
||||
|
|
@ -983,10 +990,16 @@ impl<'lock> PylockToml {
|
|||
Node::Dist {
|
||||
dist,
|
||||
hashes,
|
||||
install,
|
||||
install: true,
|
||||
}
|
||||
} else {
|
||||
return Err(PylockTomlError::MissingSource(package.name.clone()));
|
||||
// This is only reachable if the package contains a `wheels` entry (and nothing
|
||||
// else), but there are no wheels available for the current environment. (If the
|
||||
// package doesn't contain _any_ of `wheels`, `sdist`, etc., then we error in the
|
||||
// match above.)
|
||||
//
|
||||
// TODO(charlie): Include a hint, like in `uv.lock`.
|
||||
return Err(PylockTomlError::MissingWheel(package.name.clone()));
|
||||
};
|
||||
|
||||
let index = graph.add_node(dist);
|
||||
|
|
|
|||
|
|
@ -5822,3 +5822,78 @@ fn pep_751() -> Result<()> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Avoid erroring for packages that only include wheels, and _don't_ include a wheel for the
|
||||
/// current platform, but are omitted by markers anyway.
|
||||
///
|
||||
/// See: <https://github.com/astral-sh/uv/issues/13127>
|
||||
#[test]
|
||||
fn pep_751_wheel_only() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
r#"
|
||||
[project]
|
||||
name = "project"
|
||||
version = "0.1.0"
|
||||
requires-python = ">=3.12.0"
|
||||
dependencies = ["torch"]
|
||||
"#,
|
||||
)?;
|
||||
|
||||
context
|
||||
.export()
|
||||
.arg("-o")
|
||||
.arg("pylock.toml")
|
||||
.assert()
|
||||
.success();
|
||||
|
||||
// If there's no compatible wheel for a package we _don't_ need to install (e.g., anything
|
||||
// CUDA-related), succeed.
|
||||
uv_snapshot!(context.filters(), context.pip_sync()
|
||||
.arg("--preview")
|
||||
.arg("pylock.toml")
|
||||
.arg("--dry-run")
|
||||
.arg("--python-platform")
|
||||
.arg("macos"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Would download 9 packages
|
||||
Would install 9 packages
|
||||
+ filelock==3.13.1
|
||||
+ fsspec==2024.3.1
|
||||
+ jinja2==3.1.3
|
||||
+ markupsafe==2.1.5
|
||||
+ mpmath==1.3.0
|
||||
+ networkx==3.2.1
|
||||
+ sympy==1.12
|
||||
+ torch==2.2.1
|
||||
+ typing-extensions==4.10.0
|
||||
"
|
||||
);
|
||||
|
||||
// However, if there's no compatible wheel for a package that we _do_ need to install, we should
|
||||
// error
|
||||
uv_snapshot!(context.filters(), context.pip_sync()
|
||||
.arg("--preview")
|
||||
.arg("pylock.toml")
|
||||
.arg("--dry-run")
|
||||
.arg("--python-platform")
|
||||
.arg("macos")
|
||||
.arg("--python-version")
|
||||
.arg("3.8"), @r"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
error: Package `torch` does not include a compatible wheel for the current platform
|
||||
"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue