Read all extras directly from lockfile (#4033)

## Summary
We now pass `ExtrasSpecification` to the lock routine.
This commit is contained in:
Charlie Marsh 2024-06-04 21:03:55 -04:00 committed by GitHub
parent 1b3200b2af
commit 8de3e38b94
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 29 additions and 48 deletions

View file

@ -10,7 +10,7 @@ use tracing::{debug, trace};
use pep508_rs::VerbatimUrl; use pep508_rs::VerbatimUrl;
use pypi_types::{Requirement, RequirementSource}; use pypi_types::{Requirement, RequirementSource};
use uv_fs::{absolutize_path, Simplified}; use uv_fs::{absolutize_path, Simplified};
use uv_normalize::{ExtraName, PackageName}; use uv_normalize::PackageName;
use uv_warnings::warn_user; use uv_warnings::warn_user;
use crate::pyproject::{PyProjectToml, Source, ToolUvWorkspace}; use crate::pyproject::{PyProjectToml, Source, ToolUvWorkspace};
@ -134,21 +134,9 @@ impl Workspace {
/// Returns `None` if the package is not part of the workspace. /// Returns `None` if the package is not part of the workspace.
pub fn with_current_project(self, package_name: PackageName) -> Option<ProjectWorkspace> { pub fn with_current_project(self, package_name: PackageName) -> Option<ProjectWorkspace> {
let member = self.packages.get(&package_name)?; let member = self.packages.get(&package_name)?;
let extras = member
.pyproject_toml
.project
.as_ref()
.and_then(|project| project.optional_dependencies.as_ref())
.map(|optional_dependencies| {
let mut extras = optional_dependencies.keys().cloned().collect::<Vec<_>>();
extras.sort_unstable();
extras
})
.unwrap_or_default();
Some(ProjectWorkspace { Some(ProjectWorkspace {
project_root: member.root().clone(), project_root: member.root().clone(),
project_name: package_name, project_name: package_name,
extras,
workspace: self, workspace: self,
}) })
} }
@ -393,8 +381,6 @@ pub struct ProjectWorkspace {
project_root: PathBuf, project_root: PathBuf,
/// The name of the package. /// The name of the package.
project_name: PackageName, project_name: PackageName,
/// The extras available in the project.
extras: Vec<ExtraName>,
/// The workspace the project is part of. /// The workspace the project is part of.
workspace: Workspace, workspace: Workspace,
} }
@ -496,11 +482,6 @@ impl ProjectWorkspace {
&self.project_name &self.project_name
} }
/// Returns the extras available in the project.
pub fn project_extras(&self) -> &[ExtraName] {
&self.extras
}
/// Returns the [`Workspace`] containing the current project. /// Returns the [`Workspace`] containing the current project.
pub fn workspace(&self) -> &Workspace { pub fn workspace(&self) -> &Workspace {
&self.workspace &self.workspace
@ -516,7 +497,15 @@ impl ProjectWorkspace {
pub fn requirements(&self) -> Vec<Requirement> { pub fn requirements(&self) -> Vec<Requirement> {
vec![Requirement { vec![Requirement {
name: self.project_name.clone(), name: self.project_name.clone(),
extras: self.extras.clone(), extras: self.workspace().packages[&self.project_name]
.pyproject_toml
.project
.as_ref()
.and_then(|project| project.optional_dependencies.as_ref())
.map(|optional_dependencies| {
optional_dependencies.keys().cloned().collect::<Vec<_>>()
})
.unwrap_or_default(),
marker: None, marker: None,
source: RequirementSource::Path { source: RequirementSource::Path {
path: self.project_root.clone(), path: self.project_root.clone(),
@ -538,18 +527,6 @@ impl ProjectWorkspace {
.map_err(WorkspaceError::Normalize)? .map_err(WorkspaceError::Normalize)?
.to_path_buf(); .to_path_buf();
// Extract the extras available in the project.
let extras = project
.project
.as_ref()
.and_then(|project| project.optional_dependencies.as_ref())
.map(|optional_dependencies| {
let mut extras = optional_dependencies.keys().cloned().collect::<Vec<_>>();
extras.sort_unstable();
extras
})
.unwrap_or_default();
// Check if the current project is also an explicit workspace root. // Check if the current project is also an explicit workspace root.
let mut workspace = project let mut workspace = project
.tool .tool
@ -579,7 +556,6 @@ impl ProjectWorkspace {
return Ok(Self { return Ok(Self {
project_root: project_path.clone(), project_root: project_path.clone(),
project_name: project_name.clone(), project_name: project_name.clone(),
extras,
workspace: Workspace { workspace: Workspace {
root: project_path.clone(), root: project_path.clone(),
packages: current_project_as_members, packages: current_project_as_members,
@ -607,7 +583,6 @@ impl ProjectWorkspace {
Ok(Self { Ok(Self {
project_root: project_path, project_root: project_path,
project_name, project_name,
extras,
workspace, workspace,
}) })
} }
@ -838,7 +813,6 @@ mod tests {
{ {
"project_root": "[ROOT]/albatross-in-example/examples/bird-feeder", "project_root": "[ROOT]/albatross-in-example/examples/bird-feeder",
"project_name": "bird-feeder", "project_name": "bird-feeder",
"extras": [],
"workspace": { "workspace": {
"root": "[ROOT]/albatross-in-example/examples/bird-feeder", "root": "[ROOT]/albatross-in-example/examples/bird-feeder",
"packages": { "packages": {
@ -869,7 +843,6 @@ mod tests {
{ {
"project_root": "[ROOT]/albatross-project-in-excluded/excluded/bird-feeder", "project_root": "[ROOT]/albatross-project-in-excluded/excluded/bird-feeder",
"project_name": "bird-feeder", "project_name": "bird-feeder",
"extras": [],
"workspace": { "workspace": {
"root": "[ROOT]/albatross-project-in-excluded/excluded/bird-feeder", "root": "[ROOT]/albatross-project-in-excluded/excluded/bird-feeder",
"packages": { "packages": {
@ -899,7 +872,6 @@ mod tests {
{ {
"project_root": "[ROOT]/albatross-root-workspace", "project_root": "[ROOT]/albatross-root-workspace",
"project_name": "albatross", "project_name": "albatross",
"extras": [],
"workspace": { "workspace": {
"root": "[ROOT]/albatross-root-workspace", "root": "[ROOT]/albatross-root-workspace",
"packages": { "packages": {
@ -943,7 +915,6 @@ mod tests {
{ {
"project_root": "[ROOT]/albatross-virtual-workspace/packages/albatross", "project_root": "[ROOT]/albatross-virtual-workspace/packages/albatross",
"project_name": "albatross", "project_name": "albatross",
"extras": [],
"workspace": { "workspace": {
"root": "[ROOT]/albatross-virtual-workspace", "root": "[ROOT]/albatross-virtual-workspace",
"packages": { "packages": {
@ -981,7 +952,6 @@ mod tests {
{ {
"project_root": "[ROOT]/albatross-just-project", "project_root": "[ROOT]/albatross-just-project",
"project_name": "albatross", "project_name": "albatross",
"extras": [],
"workspace": { "workspace": {
"root": "[ROOT]/albatross-just-project", "root": "[ROOT]/albatross-just-project",
"packages": { "packages": {

View file

@ -24,6 +24,7 @@ use pep440_rs::Version;
use pep508_rs::{MarkerEnvironment, MarkerTree, VerbatimUrl}; use pep508_rs::{MarkerEnvironment, MarkerTree, VerbatimUrl};
use platform_tags::{TagCompatibility, TagPriority, Tags}; use platform_tags::{TagCompatibility, TagPriority, Tags};
use pypi_types::{HashDigest, ParsedArchiveUrl, ParsedGitUrl}; use pypi_types::{HashDigest, ParsedArchiveUrl, ParsedGitUrl};
use uv_configuration::ExtrasSpecification;
use uv_git::{GitReference, GitSha, RepositoryReference, ResolvedRepositoryReference}; use uv_git::{GitReference, GitSha, RepositoryReference, ResolvedRepositoryReference};
use uv_normalize::{ExtraName, PackageName}; use uv_normalize::{ExtraName, PackageName};
@ -110,7 +111,7 @@ impl Lock {
marker_env: &MarkerEnvironment, marker_env: &MarkerEnvironment,
tags: &Tags, tags: &Tags,
root_name: &PackageName, root_name: &PackageName,
extras: &[ExtraName], extras: &ExtrasSpecification,
) -> Resolution { ) -> Resolution {
let mut queue: VecDeque<(&Distribution, Option<&ExtraName>)> = VecDeque::new(); let mut queue: VecDeque<(&Distribution, Option<&ExtraName>)> = VecDeque::new();
@ -119,8 +120,23 @@ impl Lock {
.find_by_name(root_name) .find_by_name(root_name)
.expect("found too many distributions matching root") .expect("found too many distributions matching root")
.expect("could not find root"); .expect("could not find root");
for extra in std::iter::once(None).chain(extras.iter().map(Some)) {
queue.push_back((root, extra)); // Add the base package.
queue.push_back((root, None));
// Add any extras.
match extras {
ExtrasSpecification::None => {}
ExtrasSpecification::All => {
for extra in root.optional_dependencies.keys() {
queue.push_back((root, Some(extra)));
}
}
ExtrasSpecification::Some(extras) => {
for extra in extras {
queue.push_back((root, Some(extra)));
}
}
} }
let mut map = BTreeMap::default(); let mut map = BTreeMap::default();

View file

@ -80,11 +80,6 @@ pub(super) async fn do_sync(
let tags = venv.interpreter().tags()?; let tags = venv.interpreter().tags()?;
// Read the lockfile. // Read the lockfile.
let extras = match extras {
ExtrasSpecification::None => vec![],
ExtrasSpecification::All => project.project_extras().to_vec(),
ExtrasSpecification::Some(extras) => extras,
};
let resolution = lock.to_resolution(markers, tags, project.project_name(), &extras); let resolution = lock.to_resolution(markers, tags, project.project_name(), &extras);
// Initialize the registry client. // Initialize the registry client.