Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consolidate UnusableDependencies into a generic Unavailable incompatibility #1088

Merged
merged 1 commit into from
Jan 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ owo-colors = { version = "3.5.0" }
petgraph = { version = "0.6.4" }
platform-info = { version = "2.0.2" }
plist = { version = "1.6.0" }
pubgrub = { git = "https://github.com/zanieb/pubgrub", rev = "0e02ea9fc8d021fb6a6b9e77b09ade4332068f42" }
pubgrub = { git = "https://github.com/zanieb/pubgrub", rev = "7a573e3902ff338abdcf3b87682e4c6d04845f2f" }
pyo3 = { version = "0.20.2" }
pyo3-log = { version = "0.9.0"}
pyproject-toml = { version = "0.8.1" }
Expand Down
4 changes: 2 additions & 2 deletions crates/puffin-resolver/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ pub enum ResolveError {
#[error("~= operator requires at least two release segments: {0}")]
InvalidTildeEquals(pep440_rs::VersionSpecifier),

#[error("Conflicting URLs for package `{0}`:\n- {1}\n- {2}")]
#[error("There are conflicting URLs for package `{0}`:\n- {1}\n- {2}")]
ConflictingUrls(PackageName, String, String),

#[error("Conflicting versions for `{0}`: {1}")]
#[error("There are conflicting versions for `{0}`: {1}")]
ConflictingVersions(String, String),

#[error("Package `{0}` attempted to resolve via URL: {1}. URL dependencies must be expressed as direct requirements or constraints. Consider adding `{0} @ {1}` to your dependencies or constraints file.")]
Expand Down
39 changes: 12 additions & 27 deletions crates/puffin-resolver/src/pubgrub/report.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,32 +96,18 @@ impl ReportFormatter<PubGrubPackage, Range<Version>> for PubGrubReportFormatter<
}
}
}
External::UnavailableDependencies(package, set) => {
let set = self.simplify_set(set, package);
format!(
"dependencies of {}are unavailable",
Padded::new("", &PackageRange::compatibility(package, &set), " ")
)
}
External::UnusableDependencies(package, set, reason) => {
if let Some(reason) = reason {
if matches!(package, PubGrubPackage::Root(_)) {
format!("{package} dependencies are unusable: {reason}")
} else {
let set = self.simplify_set(set, package);
format!(
"dependencies of {}are unusable: {reason}",
Padded::new("", &PackageRange::compatibility(package, &set), " ")
)
}
} else {
let set = self.simplify_set(set, package);
format!(
"dependencies of {}are unusable",
Padded::new("", &PackageRange::compatibility(package, &set), " ")
)
External::Unavailable(package, set, reason) => match package {
PubGrubPackage::Root(Some(name)) => {
format!("{name} cannot be used because {reason}")
}
}
PubGrubPackage::Root(None) => {
format!("your requirements cannot be used because {reason}")
}
_ => format!(
"{}is unusable because {reason}",
Padded::new("", &PackageRange::compatibility(package, set), " ")
),
},
External::FromDependencyOf(package, package_set, dependency, dependency_set) => {
let package_set = self.simplify_set(package_set, package);
let dependency_set = self.simplify_set(dependency_set, dependency);
Expand Down Expand Up @@ -403,8 +389,7 @@ impl PubGrubReportFormatter<'_> {
}
}
External::NotRoot(..) => {}
External::UnavailableDependencies(..) => {}
External::UnusableDependencies(..) => {}
External::Unavailable(..) => {}
External::FromDependencyOf(..) => {}
},
DerivationTree::Derived(derived) => {
Expand Down
44 changes: 31 additions & 13 deletions crates/puffin-resolver/src/resolver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,22 +335,30 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
.get_dependencies(package, &version, &mut priorities, request_sink)
.await?
{
Dependencies::Unusable(reason) => {
state.add_incompatibility(Incompatibility::unusable_dependencies(
Dependencies::Unavailable(reason) => {
let message = {
if matches!(package, PubGrubPackage::Root(_)) {
// Including front-matter for the root package is redundant
reason.clone()
} else {
format!("its dependencies are unusable because {reason}")
}
};
state.add_incompatibility(Incompatibility::unavailable(
package.clone(),
version.clone(),
reason.clone(),
message,
));
continue;
}
Dependencies::Known(constraints) if constraints.contains_key(package) => {
Dependencies::Available(constraints) if constraints.contains_key(package) => {
return Err(PubGrubError::SelfDependency {
package: package.clone(),
version: version.clone(),
}
.into());
}
Dependencies::Known(constraints) => constraints,
Dependencies::Available(constraints) => constraints,
};

// Add that package and version if the dependencies are not problematic.
Expand Down Expand Up @@ -588,7 +596,7 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
| ResolveError::ConflictingUrls(..)),
) = constraints
{
return Ok(Dependencies::Unusable(Some(err.to_string())));
return Ok(Dependencies::Unavailable(uncapitalize(err.to_string())));
}
let mut constraints = constraints?;

Expand All @@ -610,10 +618,12 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
);
}

Ok(Dependencies::Known(constraints.into()))
Ok(Dependencies::Available(constraints.into()))
}

PubGrubPackage::Python(_) => Ok(Dependencies::Known(DependencyConstraints::default())),
PubGrubPackage::Python(_) => {
Ok(Dependencies::Available(DependencyConstraints::default()))
}

PubGrubPackage::Package(package_name, extra, url) => {
// Wait for the metadata to be available.
Expand All @@ -640,7 +650,7 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
version.clone(),
);
constraints.insert(PubGrubPackage::Python(PubGrubPython::Target), version);
return Ok(Dependencies::Known(constraints));
return Ok(Dependencies::Available(constraints));
}

let entry = self.index.distributions.wait(&package_id).await?;
Expand Down Expand Up @@ -670,7 +680,7 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
);
}

Ok(Dependencies::Known(constraints.into()))
Ok(Dependencies::Available(constraints.into()))
}
}
}
Expand Down Expand Up @@ -877,8 +887,16 @@ enum Response {
/// For each [Package] there is a set of versions allowed as a dependency.
#[derive(Clone)]
enum Dependencies {
/// Package dependencies are not usable
Unusable(Option<String>),
/// Package dependencies are not available.
Unavailable(String),
/// Container for all available package versions.
Known(DependencyConstraints<PubGrubPackage, Range<Version>>),
Available(DependencyConstraints<PubGrubPackage, Range<Version>>),
}

fn uncapitalize<T: AsRef<str>>(string: T) -> String {
let mut chars = string.as_ref().chars();
match chars.next() {
None => String::new(),
Some(first) => first.to_lowercase().chain(chars).collect(),
}
}
10 changes: 6 additions & 4 deletions crates/puffin/tests/pip_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1516,7 +1516,8 @@ fn conflicting_repeated_url_dependency_version_mismatch() -> Result<()> {

----- stderr -----
× No solution found when resolving dependencies:
╰─▶ root dependencies are unusable: Conflicting URLs for package `werkzeug`:
╰─▶ your requirements cannot be used because there are conflicting URLs for
package `werkzeug`:
- https://files.pythonhosted.org/packages/bd/24/11c3ea5a7e866bf2d97f0501d0b4b1c9bbeade102bb4b588f0d2919a5212/Werkzeug-2.0.1-py3-none-any.whl
- https://files.pythonhosted.org/packages/ff/1d/960bb4017c68674a1cb099534840f18d3def3ce44aed12b5ed8b78e0153e/Werkzeug-2.0.0-py3-none-any.whl
"###);
Expand Down Expand Up @@ -1556,7 +1557,8 @@ fn conflicting_repeated_url_dependency_version_match() -> Result<()> {

----- stderr -----
× No solution found when resolving dependencies:
╰─▶ root dependencies are unusable: Conflicting URLs for package `werkzeug`:
╰─▶ your requirements cannot be used because there are conflicting URLs for
package `werkzeug`:
- git+https://github.com/pallets/[email protected]
- https://files.pythonhosted.org/packages/ff/1d/960bb4017c68674a1cb099534840f18d3def3ce44aed12b5ed8b78e0153e/Werkzeug-2.0.0-py3-none-any.whl
"###);
Expand Down Expand Up @@ -1900,8 +1902,8 @@ dependencies = ["django==5.0b1", "django==5.0a1"]

----- stderr -----
× No solution found when resolving dependencies:
╰─▶ my-project dependencies are unusable: Conflicting versions for `django`:
`django==5.0b1` does not intersect with `django==5.0a1`
╰─▶ my-project cannot be used because there are conflicting versions for
`django`: `django==5.0b1` does not intersect with `django==5.0a1`
"###);
});

Expand Down
2 changes: 1 addition & 1 deletion crates/puffin/tests/pip_install_scenarios.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1245,7 +1245,7 @@ fn direct_incompatible_versions() -> Result<()> {

----- stderr -----
× No solution found when resolving dependencies:
╰─▶ root dependencies are unusable: Conflicting versions for `albatross`: `albatross==1.0.0` does not intersect with `albatross==2.0.0`
╰─▶ your requirements cannot be used because there are conflicting versions for `albatross`: `albatross==1.0.0` does not intersect with `albatross==2.0.0`
"###);
});

Expand Down