Respect constraints on editable dependencies (#3554)

## Summary

Ensures that constraints are enforced for editable requirements.

Closes #3548.
This commit is contained in:
Charlie Marsh 2024-05-13 13:06:27 -04:00 committed by GitHub
parent 10ec48299e
commit 44363d25c2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 101 additions and 5 deletions

View File

@ -183,9 +183,9 @@ impl From<PubGrubDependencies> for Vec<(PubGrubPackage, Range<Version>)> {
/// A PubGrub-compatible package and version range.
#[derive(Debug, Clone)]
struct PubGrubRequirement {
package: PubGrubPackage,
version: Range<Version>,
pub(crate) struct PubGrubRequirement {
pub(crate) package: PubGrubPackage,
pub(crate) version: Range<Version>,
}
impl PubGrubRequirement {

View File

@ -1,4 +1,4 @@
pub(crate) use crate::pubgrub::dependencies::PubGrubDependencies;
pub(crate) use crate::pubgrub::dependencies::{PubGrubDependencies, PubGrubRequirement};
pub(crate) use crate::pubgrub::distribution::PubGrubDistribution;
pub(crate) use crate::pubgrub::package::{PubGrubPackage, PubGrubPython};
pub(crate) use crate::pubgrub::priority::{PubGrubPriorities, PubGrubPriority};

View File

@ -43,7 +43,7 @@ use crate::pins::FilePins;
use crate::preferences::Preferences;
use crate::pubgrub::{
PubGrubDependencies, PubGrubDistribution, PubGrubPackage, PubGrubPriorities, PubGrubPython,
PubGrubSpecifier,
PubGrubRequirement, PubGrubSpecifier,
};
use crate::python_requirement::PythonRequirement;
use crate::resolution::ResolutionGraph;
@ -931,6 +931,19 @@ impl<'a, Provider: ResolverProvider, InstalledPackages: InstalledPackagesProvide
Range::singleton(metadata.version.clone()),
);
}
// Add any constraints.
for constraint in self.constraints.get(&metadata.name).into_iter().flatten() {
if constraint.evaluate_markers(self.markers, &[]) {
let PubGrubRequirement { package, version } =
PubGrubRequirement::from_constraint(
constraint,
&self.urls,
&self.locals,
)?;
dependencies.push(package, version);
}
}
}
Ok(Dependencies::Available(dependencies.into()))

View File

@ -957,6 +957,89 @@ fn install_editable_no_binary() {
);
}
#[test]
fn install_editable_compatible_constraint() -> Result<()> {
let context = TestContext::new("3.12");
let constraints_txt = context.temp_dir.child("constraints.txt");
constraints_txt.write_str("black==0.1.0")?;
// Install the editable package with a compatible constraint.
uv_snapshot!(context.filters(), context.install()
.arg("-e")
.arg(context.workspace_root.join("scripts/packages/black_editable"))
.arg("--constraint")
.arg("constraints.txt"), @r###"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Built 1 editable in [TIME]
Resolved 1 package in [TIME]
Installed 1 package in [TIME]
+ black==0.1.0 (from file://[WORKSPACE]/scripts/packages/black_editable)
"###
);
Ok(())
}
#[test]
fn install_editable_incompatible_constraint_version() -> Result<()> {
let context = TestContext::new("3.12");
let constraints_txt = context.temp_dir.child("constraints.txt");
constraints_txt.write_str("black>0.1.0")?;
// Install the editable package with an incompatible constraint.
uv_snapshot!(context.filters(), context.install()
.arg("-e")
.arg(context.workspace_root.join("scripts/packages/black_editable"))
.arg("--constraint")
.arg("constraints.txt"), @r###"
success: false
exit_code: 1
----- stdout -----
----- stderr -----
Built 1 editable in [TIME]
× No solution found when resolving dependencies:
Because you require black==0.1.0 and black>0.1.0, we can conclude that the requirements are unsatisfiable.
"###
);
Ok(())
}
#[test]
fn install_editable_incompatible_constraint_url() -> Result<()> {
let context = TestContext::new("3.12");
let constraints_txt = context.temp_dir.child("constraints.txt");
constraints_txt.write_str("black @ https://files.pythonhosted.org/packages/0f/89/294c9a6b6c75a08da55e9d05321d0707e9418735e3062b12ef0f54c33474/black-24.4.2-py3-none-any.whl")?;
// Install the editable package with an incompatible constraint.
uv_snapshot!(context.filters(), context.install()
.arg("-e")
.arg(context.workspace_root.join("scripts/packages/black_editable"))
.arg("--constraint")
.arg("constraints.txt"), @r###"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
Built 1 editable in [TIME]
error: Requirements contain conflicting URLs for package `black`:
- [WORKSPACE]/scripts/packages/black_editable
- https://files.pythonhosted.org/packages/0f/89/294c9a6b6c75a08da55e9d05321d0707e9418735e3062b12ef0f54c33474/black-24.4.2-py3-none-any.whl
"###
);
Ok(())
}
/// Install a source distribution that uses the `flit` build system, along with `flit`
/// at the top-level, along with `--reinstall` to force a re-download after resolution, to ensure
/// that the `flit` install and the source distribution build don't conflict.