mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-24 13:43:45 +00:00
uv-resolver: remove the conservative checking of unconditional extras
This removes the error that was causing folks problems. This does result in some snapshot updates that are arguably wrong, or at least sub-optimal. However, it's actually intended. Because the approach we're going to take is going to permit the creation of uninstallable lock files as a side effect. In the future, we will modify this test to check that, while `uv lock` succeeds, `uv sync` will always fail.
This commit is contained in:
parent
183fe403c6
commit
ae9c5c849d
3 changed files with 10 additions and 57 deletions
|
@ -12,7 +12,7 @@ use tracing::trace;
|
|||
use uv_distribution_types::{
|
||||
DerivationChain, DistErrorKind, IndexCapabilities, IndexLocations, IndexUrl, RequestedDist,
|
||||
};
|
||||
use uv_normalize::{ExtraName, PackageName};
|
||||
use uv_normalize::PackageName;
|
||||
use uv_pep440::{LocalVersionSlice, Version};
|
||||
use uv_platform_tags::Tags;
|
||||
use uv_static::EnvVars;
|
||||
|
@ -48,13 +48,6 @@ pub enum ResolveError {
|
|||
#[error("Attempted to wait on an unregistered task: `{_0}`")]
|
||||
UnregisteredTask(String),
|
||||
|
||||
#[error("Found conflicting extra `{extra}` unconditionally enabled in `{requirement}`")]
|
||||
ConflictingExtra {
|
||||
// Boxed because `Requirement` is large.
|
||||
requirement: Box<uv_pypi_types::Requirement>,
|
||||
extra: ExtraName,
|
||||
},
|
||||
|
||||
#[error(
|
||||
"Requirements contain conflicting URLs for package `{package_name}`{}:\n- {}",
|
||||
if env.marker_environment().is_some() {
|
||||
|
|
|
@ -1682,16 +1682,6 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
|
|||
}
|
||||
};
|
||||
|
||||
if let Some(err) = find_conflicting_extra(&self.conflicts, &metadata.requires_dist)
|
||||
{
|
||||
return Err(err);
|
||||
}
|
||||
for dependencies in metadata.dependency_groups.values() {
|
||||
if let Some(err) = find_conflicting_extra(&self.conflicts, dependencies) {
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
|
||||
let requirements = self.flatten_requirements(
|
||||
&metadata.requires_dist,
|
||||
&metadata.dependency_groups,
|
||||
|
@ -3610,36 +3600,6 @@ pub(crate) struct VersionFork {
|
|||
version: Option<Version>,
|
||||
}
|
||||
|
||||
/// Returns an error if a conflicting extra is found in the given requirements.
|
||||
///
|
||||
/// Specifically, if there is any conflicting extra (just one is enough) that
|
||||
/// is unconditionally enabled as part of a dependency specification, then this
|
||||
/// returns an error.
|
||||
///
|
||||
/// The reason why we're so conservative here is because it avoids us needing
|
||||
/// the look at the entire dependency tree at once.
|
||||
///
|
||||
/// For example, consider packages `root`, `a`, `b` and `c`, where `c` has
|
||||
/// declared conflicting extras of `x1` and `x2`.
|
||||
///
|
||||
/// Now imagine `root` depends on `a` and `b`, `a` depends on `c[x1]` and `b`
|
||||
/// depends on `c[x2]`. That's a conflict, but not easily detectable unless
|
||||
/// you reject either `c[x1]` or `c[x2]` on the grounds that `x1` and `x2` are
|
||||
/// conflicting and thus cannot be enabled unconditionally.
|
||||
fn find_conflicting_extra(conflicting: &Conflicts, reqs: &[Requirement]) -> Option<ResolveError> {
|
||||
for req in reqs {
|
||||
for extra in &req.extras {
|
||||
if conflicting.contains(&req.name, extra) {
|
||||
return Some(ResolveError::ConflictingExtra {
|
||||
requirement: Box::new(req.clone()),
|
||||
extra: extra.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
struct ConflictTracker {
|
||||
/// How often a decision on the package was discarded due to another package decided earlier.
|
||||
|
|
|
@ -1047,12 +1047,12 @@ fn extra_unconditional() -> Result<()> {
|
|||
)?;
|
||||
|
||||
uv_snapshot!(context.filters(), context.lock(), @r###"
|
||||
success: false
|
||||
exit_code: 2
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
error: Found conflicting extra `extra1` unconditionally enabled in `proxy1[extra1,extra2] @ file://[TEMP_DIR]/proxy1`
|
||||
Resolved 6 packages in [TIME]
|
||||
"###);
|
||||
|
||||
// An error should occur even when only one conflicting extra is enabled.
|
||||
|
@ -1078,12 +1078,12 @@ fn extra_unconditional() -> Result<()> {
|
|||
"#,
|
||||
)?;
|
||||
uv_snapshot!(context.filters(), context.lock(), @r###"
|
||||
success: false
|
||||
exit_code: 2
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
error: Found conflicting extra `extra1` unconditionally enabled in `proxy1[extra1] @ file://[TEMP_DIR]/proxy1`
|
||||
Resolved 6 packages in [TIME]
|
||||
"###);
|
||||
|
||||
// And same thing for the other extra.
|
||||
|
@ -1110,12 +1110,12 @@ fn extra_unconditional() -> Result<()> {
|
|||
"#,
|
||||
)?;
|
||||
uv_snapshot!(context.filters(), context.lock(), @r###"
|
||||
success: false
|
||||
exit_code: 2
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
error: Found conflicting extra `extra2` unconditionally enabled in `proxy1[extra2] @ file://[TEMP_DIR]/proxy1`
|
||||
Resolved 6 packages in [TIME]
|
||||
"###);
|
||||
|
||||
Ok(())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue