Allow prereleases, locals, and URLs in non-editable path requirements (#2671)

## Summary

This PR enables the resolver to "accept" URLs, prereleases, and local
version specifiers for direct dependencies of path dependencies. As a
result, `uv pip install .` and `uv pip install -e .` now behave
identically, in that neither has a restriction on URL dependencies and
the like.

Closes https://github.com/astral-sh/uv/issues/2643.
Closes https://github.com/astral-sh/uv/issues/1853.
This commit is contained in:
Charlie Marsh 2024-03-27 18:17:09 -04:00 committed by GitHub
parent 4b69ad4281
commit cf30932831
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 484 additions and 77 deletions

View file

@ -1,7 +1,7 @@
use rustc_hash::{FxHashMap, FxHashSet};
use pep440_rs::Version;
use pep508_rs::MarkerEnvironment;
use pep508_rs::{MarkerEnvironment, VersionOrUrl};
use uv_normalize::PackageName;
use crate::preferences::Preference;
@ -15,22 +15,26 @@ pub struct AllowedYanks(FxHashMap<PackageName, FxHashSet<Version>>);
impl AllowedYanks {
pub fn from_manifest(manifest: &Manifest, markers: &MarkerEnvironment) -> Self {
let mut allowed_yanks = FxHashMap::<PackageName, FxHashSet<Version>>::default();
for requirement in manifest
.requirements
.iter()
.chain(manifest.constraints.iter())
.chain(manifest.overrides.iter())
.chain(manifest.preferences.iter().map(Preference::requirement))
.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))
}))
for requirement in
manifest
.requirements
.iter()
.chain(manifest.constraints.iter())
.chain(manifest.overrides.iter())
.chain(manifest.preferences.iter().map(Preference::requirement))
.filter(|requirement| requirement.evaluate_markers(markers, &[]))
.chain(manifest.lookaheads.iter().flat_map(|lookahead| {
lookahead.requirements().iter().filter(|requirement| {
requirement.evaluate_markers(markers, lookahead.extras())
})
}))
.chain(manifest.editables.iter().flat_map(|(editable, metadata)| {
metadata.requires_dist.iter().filter(|requirement| {
requirement.evaluate_markers(markers, &editable.extras)
})
}))
{
let Some(pep508_rs::VersionOrUrl::VersionSpecifier(specifiers)) =
&requirement.version_or_url
let Some(VersionOrUrl::VersionSpecifier(specifiers)) = &requirement.version_or_url
else {
continue;
};