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

Refactor editables for supporting them in bluejay commands #3639

Merged
merged 1 commit into from
May 20, 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
4 changes: 4 additions & 0 deletions crates/uv-installer/src/site_packages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -548,4 +548,8 @@ impl InstalledPackagesProvider for SitePackages {
fn get_packages(&self, name: &PackageName) -> Vec<&InstalledDist> {
self.get_packages(name)
}

fn get_editables(&self, url: &Url) -> Vec<&InstalledDist> {
self.get_editables(url)
}
}
29 changes: 12 additions & 17 deletions crates/uv-requirements/src/lookahead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,14 @@ use rustc_hash::FxHashSet;
use thiserror::Error;

use distribution_types::{
BuiltDist, Dist, DistributionMetadata, GitSourceDist, LocalEditable, Requirement,
RequirementSource, Requirements, SourceDist,
BuiltDist, Dist, DistributionMetadata, GitSourceDist, Requirement, RequirementSource,
SourceDist,
};
use pep508_rs::MarkerEnvironment;
use pypi_types::Metadata23;
use uv_configuration::{Constraints, Overrides};
use uv_distribution::{DistributionDatabase, Reporter};
use uv_git::GitUrl;
use uv_resolver::{InMemoryIndex, MetadataResponse};
use uv_resolver::{BuiltEditableMetadata, InMemoryIndex, MetadataResponse};
use uv_types::{BuildContext, HashStrategy, RequestedRequirements};

#[derive(Debug, Error)]
Expand Down Expand Up @@ -53,7 +52,7 @@ pub struct LookaheadResolver<'a, Context: BuildContext> {
/// The overrides for the project.
overrides: &'a Overrides,
/// The editable requirements for the project.
editables: &'a [(LocalEditable, Metadata23, Requirements)],
editables: &'a [BuiltEditableMetadata],
/// The required hashes for the project.
hasher: &'a HashStrategy,
/// The in-memory index for resolving dependencies.
Expand All @@ -69,7 +68,7 @@ impl<'a, Context: BuildContext> LookaheadResolver<'a, Context> {
requirements: &'a [Requirement],
constraints: &'a Constraints,
overrides: &'a Overrides,
editables: &'a [(LocalEditable, Metadata23, Requirements)],
editables: &'a [BuiltEditableMetadata],
hasher: &'a HashStrategy,
index: &'a InMemoryIndex,
database: DistributionDatabase<'a, Context>,
Expand Down Expand Up @@ -113,17 +112,13 @@ impl<'a, Context: BuildContext> LookaheadResolver<'a, Context> {
.constraints
.apply(self.overrides.apply(self.requirements))
.filter(|requirement| requirement.evaluate_markers(markers, &[]))
.chain(
self.editables
.iter()
.flat_map(|(editable, _metadata, requirements)| {
self.constraints
.apply(self.overrides.apply(&requirements.dependencies))
.filter(|requirement| {
requirement.evaluate_markers(markers, &editable.extras)
})
}),
)
.chain(self.editables.iter().flat_map(|editable| {
self.constraints
.apply(self.overrides.apply(&editable.requirements.dependencies))
.filter(|requirement| {
requirement.evaluate_markers(markers, &editable.built.extras)
})
}))
.cloned()
.collect();

Expand Down
38 changes: 18 additions & 20 deletions crates/uv-resolver/src/editables.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,34 @@
use std::hash::BuildHasherDefault;

use rustc_hash::FxHashMap;

use distribution_types::{LocalEditable, Requirements};
use pypi_types::Metadata23;
use uv_normalize::PackageName;

/// A built editable for which we know its dependencies and other static metadata.
#[derive(Debug, Clone)]
pub struct BuiltEditableMetadata {
pub built: LocalEditable,
pub metadata: Metadata23,
pub requirements: Requirements,
}

/// A set of editable packages, indexed by package name.
#[derive(Debug, Default, Clone)]
pub(crate) struct Editables(FxHashMap<PackageName, (LocalEditable, Metadata23, Requirements)>);
pub(crate) struct Editables(FxHashMap<PackageName, BuiltEditableMetadata>);

impl Editables {
/// Create a new set of editables from a set of requirements.
pub(crate) fn from_requirements(
requirements: Vec<(LocalEditable, Metadata23, Requirements)>,
) -> Self {
let mut editables =
FxHashMap::with_capacity_and_hasher(requirements.len(), BuildHasherDefault::default());
for (editable_requirement, metadata, requirements) in requirements {
editables.insert(
metadata.name.clone(),
(editable_requirement, metadata, requirements),
);
}
Self(editables)
pub(crate) fn from_requirements(requirements: Vec<BuiltEditableMetadata>) -> Self {
Self(
requirements
.into_iter()
.map(|editable| (editable.metadata.name.clone(), editable))
.collect(),
)
}

/// Get the editable for a package.
pub(crate) fn get(
&self,
name: &PackageName,
) -> Option<&(LocalEditable, Metadata23, Requirements)> {
pub(crate) fn get(&self, name: &PackageName) -> Option<&BuiltEditableMetadata> {
self.0.get(name)
}

Expand All @@ -40,7 +38,7 @@ impl Editables {
}

/// Iterate over all editables.
pub(crate) fn iter(&self) -> impl Iterator<Item = &(LocalEditable, Metadata23, Requirements)> {
pub(crate) fn iter(&self) -> impl Iterator<Item = &BuiltEditableMetadata> {
self.0.values()
}
}
1 change: 1 addition & 0 deletions crates/uv-resolver/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub use dependency_mode::DependencyMode;
pub use editables::BuiltEditableMetadata;
pub use error::ResolveError;
pub use exclude_newer::ExcludeNewer;
pub use exclusions::Exclusions;
Expand Down
31 changes: 15 additions & 16 deletions crates/uv-resolver/src/manifest.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use distribution_types::{LocalEditable, Requirement, Requirements};
use either::Either;

use distribution_types::Requirement;
use pep508_rs::MarkerEnvironment;
use pypi_types::Metadata23;
use uv_configuration::{Constraints, Overrides};
use uv_normalize::PackageName;
use uv_types::RequestedRequirements;

use crate::editables::BuiltEditableMetadata;
use crate::{preferences::Preference, DependencyMode, Exclusions};

/// A manifest of requirements, constraints, and preferences.
Expand Down Expand Up @@ -34,7 +35,7 @@ pub struct Manifest {
///
/// The requirements of the editables should be included in resolution as if they were
/// direct requirements in their own right.
pub(crate) editables: Vec<(LocalEditable, Metadata23, Requirements)>,
pub(crate) editables: Vec<BuiltEditableMetadata>,

/// The installed packages to exclude from consideration during resolution.
///
Expand All @@ -58,7 +59,7 @@ impl Manifest {
overrides: Overrides,
preferences: Vec<Preference>,
project: Option<PackageName>,
editables: Vec<(LocalEditable, Metadata23, Requirements)>,
editables: Vec<BuiltEditableMetadata>,
exclusions: Exclusions,
lookaheads: Vec<RequestedRequirements>,
) -> Self {
Expand Down Expand Up @@ -112,11 +113,11 @@ impl Manifest {
requirement.evaluate_markers(markers, lookahead.extras())
})
})
.chain(self.editables.iter().flat_map(move |(editable, _metadata, requirements)| {
.chain(self.editables.iter().flat_map(move |editable| {
self.overrides
.apply(&requirements.dependencies)
.apply(&editable.requirements.dependencies)
.filter(move |requirement| {
requirement.evaluate_markers(markers, &editable.extras)
requirement.evaluate_markers(markers, &editable.built.extras)
})
}))
.chain(
Expand Down Expand Up @@ -174,15 +175,13 @@ impl Manifest {
requirement.evaluate_markers(markers, lookahead.extras())
})
})
.chain(self.editables.iter().flat_map(
move |(editable, _metadata, uv_requirements)| {
self.overrides.apply(&uv_requirements.dependencies).filter(
move |requirement| {
requirement.evaluate_markers(markers, &editable.extras)
},
)
},
))
.chain(self.editables.iter().flat_map(move |editable| {
self.overrides
.apply(&editable.requirements.dependencies)
.filter(move |requirement| {
requirement.evaluate_markers(markers, &editable.built.extras)
})
}))
.chain(
self.overrides
.apply(&self.requirements)
Expand Down
4 changes: 2 additions & 2 deletions crates/uv-resolver/src/resolution/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@ impl std::fmt::Display for DisplayResolutionGraph<'_> {
return None;
}

let node = if let Some((editable, _, _)) = self.resolution.editables.get(name) {
Node::Editable(editable)
let node = if let Some(editable) = self.resolution.editables.get(name) {
Node::Editable(&editable.built)
} else {
Node::Distribution(dist)
};
Expand Down
18 changes: 10 additions & 8 deletions crates/uv-resolver/src/resolution/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,15 @@ impl ResolutionGraph {
}
}
PubGrubPackage::Package(package_name, Some(extra), Some(url)) => {
if let Some((editable, metadata, _)) = editables.get(package_name) {
if metadata.provides_extras.contains(extra) {
if let Some(editable) = editables.get(package_name) {
if editable.metadata.provides_extras.contains(extra) {
extras
.entry(package_name.clone())
.or_insert_with(Vec::new)
.push(extra.clone());
} else {
let dist = Dist::from_editable(package_name.clone(), editable.clone())?;
let dist =
Dist::from_editable(package_name.clone(), editable.built.clone())?;

diagnostics.push(Diagnostic::MissingExtra {
dist: dist.into(),
Expand Down Expand Up @@ -219,15 +220,16 @@ impl ResolutionGraph {
}
PubGrubPackage::Package(package_name, None, Some(url)) => {
// Create the distribution.
if let Some((editable, metadata, _)) = editables.get(package_name) {
let dist = Dist::from_editable(package_name.clone(), editable.clone())?;
if let Some(editable) = editables.get(package_name) {
let dist =
Dist::from_editable(package_name.clone(), editable.built.clone())?;

// Add the distribution to the graph.
let index = petgraph.add_node(AnnotatedDist {
dist: dist.into(),
extras: editable.extras.clone(),
extras: editable.built.extras.clone(),
hashes: vec![],
metadata: metadata.clone(),
metadata: editable.metadata.clone(),
});
inverse.insert(package_name, index);
} else {
Expand Down Expand Up @@ -487,7 +489,7 @@ impl ResolutionGraph {
manifest
.editables
.iter()
.flat_map(|(_, _, uv_requirements)| &uv_requirements.dependencies),
.flat_map(|editable| &editable.requirements.dependencies),
);
for direct_req in manifest.apply(direct_reqs) {
let Some(ref marker_tree) = direct_req.marker else {
Expand Down
35 changes: 22 additions & 13 deletions crates/uv-resolver/src/resolver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -728,16 +728,16 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
);

// If the dist is an editable, return the version from the editable metadata.
if let Some((_local, metadata, _)) = self.editables.get(package_name) {
let version = &metadata.version;
if let Some(editable) = self.editables.get(package_name) {
let version = &editable.metadata.version;

// The version is incompatible with the requirement.
if !range.contains(version) {
return Ok(None);
}

// The version is incompatible due to its Python requirement.
if let Some(requires_python) = metadata.requires_python.as_ref() {
if let Some(requires_python) = editable.metadata.requires_python.as_ref() {
let target = self.python_requirement.target();
if !requires_python.contains(target) {
return Ok(Some(ResolverVersion::Unavailable(
Expand Down Expand Up @@ -947,10 +947,13 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
}

// Add a dependency on each editable.
for (editable, metadata, _) in self.editables.iter() {
let package =
PubGrubPackage::from_package(metadata.name.clone(), None, &self.urls);
let version = Range::singleton(metadata.version.clone());
for editable in self.editables.iter() {
let package = PubGrubPackage::from_package(
editable.metadata.name.clone(),
None,
&self.urls,
);
let version = Range::singleton(editable.metadata.version.clone());

// Update the package priorities.
priorities.insert(&package, &version);
Expand All @@ -959,19 +962,24 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
dependencies.push(package, version);

// Add a dependency on each extra.
for extra in &editable.extras {
for extra in &editable.built.extras {
dependencies.push(
PubGrubPackage::from_package(
metadata.name.clone(),
editable.metadata.name.clone(),
Some(extra.clone()),
&self.urls,
),
Range::singleton(metadata.version.clone()),
Range::singleton(editable.metadata.version.clone()),
);
}

// Add any constraints.
for constraint in self.constraints.get(&metadata.name).into_iter().flatten() {
for constraint in self
.constraints
.get(&editable.metadata.name)
.into_iter()
.flatten()
{
if constraint.evaluate_markers(self.markers.as_ref(), &[]) {
let PubGrubRequirement { package, version } =
PubGrubRequirement::from_constraint(
Expand Down Expand Up @@ -1013,8 +1021,9 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
}

// Determine if the distribution is editable.
if let Some((_local, metadata, _)) = self.editables.get(package_name) {
let requirements: Vec<_> = metadata
if let Some(editable) = self.editables.get(package_name) {
let requirements: Vec<_> = editable
.metadata
.requires_dist
.iter()
.cloned()
Expand Down
14 changes: 8 additions & 6 deletions crates/uv-resolver/src/resolver/urls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,18 @@ impl Urls {
let mut urls: FxHashMap<PackageName, VerbatimParsedUrl> = FxHashMap::default();

// Add the editables themselves to the list of required URLs.
for (editable, metadata, _) in &manifest.editables {
for editable in &manifest.editables {
let editable_url = VerbatimParsedUrl {
parsed_url: ParsedUrl::Path(ParsedPathUrl {
url: editable.url.to_url(),
path: editable.path.clone(),
url: editable.built.url.to_url(),
path: editable.built.path.clone(),
editable: true,
}),
verbatim: editable.url.clone(),
verbatim: editable.built.url.clone(),
};
if let Some(previous) = urls.insert(metadata.name.clone(), editable_url.clone()) {
if let Some(previous) =
urls.insert(editable.metadata.name.clone(), editable_url.clone())
{
if !is_equal(&previous.verbatim, &editable_url.verbatim) {
if is_same_reference(&previous.verbatim, &editable_url.verbatim) {
debug!(
Expand All @@ -43,7 +45,7 @@ impl Urls {
);
} else {
return Err(ResolveError::ConflictingUrlsDirect(
metadata.name.clone(),
editable.metadata.name.clone(),
previous.verbatim.verbatim().to_string(),
editable_url.verbatim.verbatim().to_string(),
));
Expand Down
Loading
Loading