Support recursive extras (#1435)

## Summary

We had a guard in the resolve to avoid "self-dependencies" (as in
`gps3==0.33.3`), but this guard was _unintentionally_ filtering out
recursive extras.

Closes https://github.com/astral-sh/uv/issues/1342.

## Test Plan

Taken from https://github.com/astral-sh/uv/pull/1352.
This commit is contained in:
Charlie Marsh 2024-02-16 11:42:04 -05:00 committed by GitHub
parent e6c4c77ba1
commit f25781ff6c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 97 additions and 19 deletions

View file

@ -21,22 +21,16 @@ impl PubGrubDependencies {
requirements: &[Requirement],
constraints: &[Requirement],
overrides: &Overrides,
extra: Option<&ExtraName>,
source: Option<&PackageName>,
source_name: Option<&PackageName>,
source_extra: Option<&ExtraName>,
env: &MarkerEnvironment,
) -> Result<Self, ResolveError> {
let mut dependencies = DependencyConstraints::<PubGrubPackage, Range<Version>>::default();
// Iterate over all declared requirements.
for requirement in overrides.apply(requirements) {
// Avoid self-dependencies.
if source.is_some_and(|source| source == &requirement.name) {
warn!("{} has a dependency on itself", requirement.name);
continue;
}
// If the requirement isn't relevant for the current platform, skip it.
if let Some(extra) = extra {
if let Some(extra) = source_extra {
if !requirement.evaluate_markers(env, std::slice::from_ref(extra)) {
continue;
}
@ -56,6 +50,16 @@ impl PubGrubDependencies {
) {
let (package, version) = result?;
// Ignore self-dependencies.
if let PubGrubPackage::Package(name, extra, None) = &package {
if source_name.is_some_and(|source_name| source_name == name)
&& source_extra == extra.as_ref()
{
warn!("{name} has a dependency on itself");
continue;
}
}
if let Some(entry) = dependencies.get_key_value(&package) {
// Merge the versions.
let version = merge_versions(&package, entry.1, &version)?;
@ -80,14 +84,8 @@ impl PubGrubDependencies {
continue;
}
// Avoid self-dependencies.
if source.is_some_and(|source| source == &constraint.name) {
warn!("{} has a dependency on itself", constraint.name);
continue;
}
// If the requirement isn't relevant for the current platform, skip it.
if let Some(extra) = extra {
if let Some(extra) = source_extra {
if !constraint.evaluate_markers(env, std::slice::from_ref(extra)) {
continue;
}
@ -107,6 +105,16 @@ impl PubGrubDependencies {
) {
let (package, version) = result?;
// Ignore self-dependencies.
if let PubGrubPackage::Package(name, extra, None) = &package {
if source_name.is_some_and(|source_name| source_name == name)
&& source_extra == extra.as_ref()
{
warn!("{name} has a dependency on itself");
continue;
}
}
if let Some(entry) = dependencies.get_key_value(&package) {
// Merge the versions.
let version = merge_versions(&package, entry.1, &version)?;

View file

@ -861,8 +861,8 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
&metadata.requires_dist,
&self.constraints,
&self.overrides,
extra.as_ref(),
Some(package_name),
extra.as_ref(),
self.markers,
)?;