Make direct dependency detection respect markers (#2207)

## Summary

When determining "direct" dependencies, we need to ensure that we
respect markers. In the linked issue, the user had an optional
dependency like:

```toml
[project.optional-dependencies]
dev = [
  "setuptools>=64",
  "setuptools_scm>=8"
]
```

By not respecting markers, we tried to resolve `setuptools` to the
lowest-available version. However, since `setuptools>=64` _isn't_
enabled (since it's optional), we won't respect _that_ constraint.

To be consistent, we need to omit optional dependencies just as we will
at resolution time.

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

## Test Plan

`cargo test`
This commit is contained in:
Charlie Marsh 2024-03-05 09:25:06 -08:00 committed by GitHub
parent 7f07ada24c
commit 8620b5a52f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 135 additions and 57 deletions

View file

@ -1,6 +1,6 @@
use rustc_hash::FxHashSet;
use pep508_rs::VersionOrUrl;
use pep508_rs::{MarkerEnvironment, VersionOrUrl};
use uv_normalize::PackageName;
use crate::Manifest;
@ -50,7 +50,11 @@ pub(crate) enum PreReleaseStrategy {
}
impl PreReleaseStrategy {
pub(crate) fn from_mode(mode: PreReleaseMode, manifest: &Manifest) -> Self {
pub(crate) fn from_mode(
mode: PreReleaseMode,
manifest: &Manifest,
markers: &MarkerEnvironment,
) -> Self {
match mode {
PreReleaseMode::Disallow => Self::Disallow,
PreReleaseMode::Allow => Self::Allow,
@ -61,12 +65,12 @@ impl PreReleaseStrategy {
.iter()
.chain(manifest.constraints.iter())
.chain(manifest.overrides.iter())
.chain(
manifest
.editables
.iter()
.flat_map(|(_editable, metadata)| metadata.requires_dist.iter()),
)
.filter(|requirement| requirement.evaluate_markers(markers, &[]))
.chain(manifest.editables.iter().flat_map(|(editable, metadata)| {
metadata.requires_dist.iter().filter(|requirement| {
requirement.evaluate_markers(markers, &editable.extras)
})
}))
.filter(|requirement| {
let Some(version_or_url) = &requirement.version_or_url else {
return false;
@ -90,12 +94,12 @@ impl PreReleaseStrategy {
.iter()
.chain(manifest.constraints.iter())
.chain(manifest.overrides.iter())
.chain(
manifest
.editables
.iter()
.flat_map(|(_editable, metadata)| metadata.requires_dist.iter()),
)
.filter(|requirement| requirement.evaluate_markers(markers, &[]))
.chain(manifest.editables.iter().flat_map(|(editable, metadata)| {
metadata.requires_dist.iter().filter(|requirement| {
requirement.evaluate_markers(markers, &editable.extras)
})
}))
.filter(|requirement| {
let Some(version_or_url) = &requirement.version_or_url else {
return false;