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 development dependency configuration #8309

Merged
merged 1 commit into from
Oct 18, 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
147 changes: 102 additions & 45 deletions crates/uv-configuration/src/dev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,44 @@ pub enum DevMode {
}

impl DevMode {
/// Determine the [`DevMode`] policy from the command-line arguments.
pub fn from_args(dev: bool, no_dev: bool, only_dev: bool) -> Self {
if only_dev {
Self::Only
} else if no_dev {
Self::Exclude
} else if dev {
Self::Include
} else {
Self::default()
/// Iterate over the group names to include.
pub fn iter(&self) -> impl Iterator<Item = &GroupName> {
match self {
Self::Exclude => Either::Left(std::iter::empty()),
Self::Include | Self::Only => Either::Right(std::iter::once(&*DEV_DEPENDENCIES)),
}
}

/// Returns `true` if the specification allows for production dependencies.
pub fn prod(&self) -> bool {
matches!(self, Self::Exclude | Self::Include)
}
}

#[derive(Debug, Clone)]
pub enum DevSpecification {
/// Include dev dependencies from the specified group.
pub struct DevGroupsSpecification {
/// Legacy option for `dependency-group.dev` and `tool.uv.dev-dependencies`.
///
/// Requested via the `--dev`, `--no-dev`, and `--only-dev` flags.
dev: Option<DevMode>,

/// The groups to include.
///
/// Requested via the `--group` and `--only-group` options.
groups: GroupsSpecification,
}

#[derive(Debug, Clone)]
pub enum GroupsSpecification {
/// Include dependencies from the specified groups.
Include(Vec<GroupName>),
/// Do not include dev dependencies.
/// Do not include dependencies from groups.
Exclude,
/// Include dev dependencies from the specified groups, and exclude all non-dev dependencies.
/// Only include dependencies from the specified groups, exclude all other dependencies.
Only(Vec<GroupName>),
}

impl DevSpecification {
impl GroupsSpecification {
/// Returns an [`Iterator`] over the group names to include.
pub fn iter(&self) -> impl Iterator<Item = &GroupName> {
match self {
Expand All @@ -52,48 +65,92 @@ impl DevSpecification {
}
}

impl From<DevMode> for DevSpecification {
fn from(mode: DevMode) -> Self {
match mode {
DevMode::Include => Self::Include(vec![DEV_DEPENDENCIES.clone()]),
DevMode::Exclude => Self::Exclude,
DevMode::Only => Self::Only(vec![DEV_DEPENDENCIES.clone()]),
impl DevGroupsSpecification {
/// Returns an [`Iterator`] over the group names to include.
pub fn iter(&self) -> impl Iterator<Item = &GroupName> {
match self.dev {
None => Either::Left(self.groups.iter()),
Some(ref dev_mode) => Either::Right(self.groups.iter().chain(dev_mode.iter())),
}
}
}

impl DevSpecification {
/// Determine the [`DevSpecification`] policy from the command-line arguments.
/// Determine the [`DevGroupsSpecification`] policy from the command-line arguments.
pub fn from_args(
dev: bool,
no_dev: bool,
only_dev: bool,
group: Vec<GroupName>,
only_group: Vec<GroupName>,
) -> Self {
let from_mode = DevSpecification::from(DevMode::from_args(dev, no_dev, only_dev));
if !group.is_empty() {
match from_mode {
DevSpecification::Exclude => Self::Include(group),
DevSpecification::Include(dev) => {
Self::Include(group.into_iter().chain(dev).collect())
}
DevSpecification::Only(_) => {
unreachable!("cannot specify both `--only-dev` and `--group`")
}
}
let dev_mode = if only_dev {
Some(DevMode::Only)
} else if no_dev {
Some(DevMode::Exclude)
} else if dev {
Some(DevMode::Include)
} else {
None
};

let groups = if !group.is_empty() {
if matches!(dev_mode, Some(DevMode::Only)) {
unreachable!("cannot specify both `--only-dev` and `--group`")
};
GroupsSpecification::Include(group)
} else if !only_group.is_empty() {
match from_mode {
DevSpecification::Exclude => Self::Only(only_group),
DevSpecification::Only(dev) => {
Self::Only(only_group.into_iter().chain(dev).collect())
}
// TODO(zanieb): `dev` defaults to true we can't tell if `--dev` was provided in
// conflict with `--only-group` here
DevSpecification::Include(_) => Self::Only(only_group),
}
if matches!(dev_mode, Some(DevMode::Include)) {
unreachable!("cannot specify both `--dev` and `--only-group`")
};
GroupsSpecification::Only(only_group)
} else {
from_mode
GroupsSpecification::Exclude
};

Self {
dev: dev_mode,
groups,
}
}

/// Return a new [`DevGroupsSpecification`] with development dependencies included by default.
///
/// This is appropriate in projects, where the `dev` group is synced by default.
#[must_use]
pub fn with_default_dev(self) -> Self {
Comment on lines +115 to +119
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will become with_default_groups or something in the future.

match self.dev {
Some(_) => self,
None => match self.groups {
// Only include the default `dev` group if `--only-group` wasn't used
GroupsSpecification::Only(_) => self,
GroupsSpecification::Exclude | GroupsSpecification::Include(_) => Self {
dev: Some(DevMode::Include),
..self
},
},
}
}

/// Returns `true` if the specification allows for production dependencies.
pub fn prod(&self) -> bool {
(self.dev.is_none() || self.dev.as_ref().is_some_and(DevMode::prod)) && self.groups.prod()
}

pub fn dev_mode(&self) -> Option<&DevMode> {
self.dev.as_ref()
}
}

impl From<DevMode> for DevGroupsSpecification {
fn from(dev: DevMode) -> Self {
Self {
dev: Some(dev),
groups: GroupsSpecification::Exclude,
}
}
}

impl From<GroupsSpecification> for DevGroupsSpecification {
fn from(groups: GroupsSpecification) -> Self {
Self { dev: None, groups }
}
}
4 changes: 2 additions & 2 deletions crates/uv-resolver/src/lock/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use toml_edit::{value, Array, ArrayOfTables, InlineTable, Item, Table, Value};
use url::Url;

use uv_cache_key::RepositoryUrl;
use uv_configuration::{BuildOptions, DevSpecification, ExtrasSpecification, InstallOptions};
use uv_configuration::{BuildOptions, DevGroupsSpecification, ExtrasSpecification, InstallOptions};
use uv_distribution::DistributionDatabase;
use uv_distribution_filename::{DistExtension, ExtensionError, SourceDistExtension, WheelFilename};
use uv_distribution_types::{
Expand Down Expand Up @@ -550,7 +550,7 @@ impl Lock {
marker_env: &ResolverMarkerEnvironment,
tags: &Tags,
extras: &ExtrasSpecification,
dev: &DevSpecification,
dev: &DevGroupsSpecification,
build_options: &BuildOptions,
install_options: &InstallOptions,
) -> Result<Resolution, LockError> {
Expand Down
4 changes: 2 additions & 2 deletions crates/uv-resolver/src/lock/requirements_txt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use petgraph::{Directed, Graph};
use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet};
use url::Url;

use uv_configuration::{DevSpecification, EditableMode, ExtrasSpecification, InstallOptions};
use uv_configuration::{DevGroupsSpecification, EditableMode, ExtrasSpecification, InstallOptions};
use uv_distribution_filename::{DistExtension, SourceDistExtension};
use uv_fs::Simplified;
use uv_git::GitReference;
Expand Down Expand Up @@ -43,7 +43,7 @@ impl<'lock> RequirementsTxtExport<'lock> {
lock: &'lock Lock,
root_name: &PackageName,
extras: &ExtrasSpecification,
dev: &DevSpecification,
dev: &DevGroupsSpecification,
editable: EditableMode,
hashes: bool,
install_options: &'lock InstallOptions,
Expand Down
12 changes: 6 additions & 6 deletions crates/uv-resolver/src/lock/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::collections::BTreeSet;
use itertools::Itertools;
use rustc_hash::{FxHashMap, FxHashSet};

use uv_configuration::DevMode;
use uv_configuration::DevGroupsSpecification;
use uv_normalize::{ExtraName, GroupName, PackageName};
use uv_pypi_types::ResolverMarkerEnvironment;

Expand All @@ -26,7 +26,7 @@ pub struct TreeDisplay<'env> {
/// Maximum display depth of the dependency tree.
depth: usize,
/// Whether to include development dependencies in the display.
dev: DevMode,
dev: DevGroupsSpecification,
/// Prune the given packages from the display of the dependency tree.
prune: Vec<PackageName>,
/// Display only the specified packages.
Expand All @@ -43,7 +43,7 @@ impl<'env> TreeDisplay<'env> {
depth: usize,
prune: Vec<PackageName>,
packages: Vec<PackageName>,
dev: DevMode,
dev: DevGroupsSpecification,
no_dedupe: bool,
invert: bool,
) -> Self {
Expand Down Expand Up @@ -236,14 +236,14 @@ impl<'env> TreeDisplay<'env> {
let dependencies: Vec<Node<'env>> = self
.dependencies
.get(node.package_id())
.filter(|_| self.dev != DevMode::Only)
.filter(|_| self.dev.prod())
.into_iter()
.flatten()
.map(|dep| Node::Dependency(dep.as_ref()))
.chain(
self.optional_dependencies
.get(node.package_id())
.filter(|_| self.dev != DevMode::Only)
.filter(|_| self.dev.prod())
.into_iter()
.flatten()
.flat_map(|(extra, deps)| {
Expand All @@ -254,9 +254,9 @@ impl<'env> TreeDisplay<'env> {
.chain(
self.dev_dependencies
.get(node.package_id())
.filter(|_| self.dev != DevMode::Exclude)
.into_iter()
.flatten()
.filter(|(group, _)| self.dev.iter().contains(*group))
.flat_map(|(group, deps)| {
deps.iter().map(move |dep| Node::DevDependency(group, dep))
}),
Expand Down
15 changes: 9 additions & 6 deletions crates/uv/src/commands/project/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ use uv_cache::Cache;
use uv_cache_key::RepositoryUrl;
use uv_client::{BaseClientBuilder, Connectivity, FlatIndexClient, RegistryClientBuilder};
use uv_configuration::{
Concurrency, Constraints, DevMode, DevSpecification, EditableMode, ExtrasSpecification,
InstallOptions, LowerBound, SourceStrategy,
Concurrency, Constraints, DevGroupsSpecification, DevMode, EditableMode, ExtrasSpecification,
GroupsSpecification, InstallOptions, LowerBound, SourceStrategy,
};
use uv_dispatch::BuildDispatch;
use uv_distribution::DistributionDatabase;
Expand Down Expand Up @@ -807,22 +807,25 @@ async fn lock_and_sync(
let (extras, dev) = match dependency_type {
DependencyType::Production => {
let extras = ExtrasSpecification::None;
let dev = DevSpecification::from(DevMode::Exclude);
let dev = DevGroupsSpecification::from(DevMode::Exclude);
(extras, dev)
}
DependencyType::Dev => {
let extras = ExtrasSpecification::None;
let dev = DevSpecification::from(DevMode::Include);
let dev = DevGroupsSpecification::from(DevMode::Include);
(extras, dev)
}
DependencyType::Optional(ref extra_name) => {
let extras = ExtrasSpecification::Some(vec![extra_name.clone()]);
let dev = DevSpecification::from(DevMode::Exclude);
let dev = DevGroupsSpecification::from(DevMode::Exclude);
(extras, dev)
}
DependencyType::Group(ref group_name) => {
let extras = ExtrasSpecification::None;
let dev = DevSpecification::Include(vec![group_name.clone()]);
let dev =
DevGroupsSpecification::from(GroupsSpecification::Include(
vec![group_name.clone()],
));
(extras, dev)
}
};
Expand Down
6 changes: 3 additions & 3 deletions crates/uv/src/commands/project/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::path::{Path, PathBuf};
use uv_cache::Cache;
use uv_client::Connectivity;
use uv_configuration::{
Concurrency, DevMode, DevSpecification, EditableMode, ExportFormat, ExtrasSpecification,
Concurrency, DevGroupsSpecification, EditableMode, ExportFormat, ExtrasSpecification,
InstallOptions, LowerBound,
};
use uv_normalize::PackageName;
Expand All @@ -33,7 +33,7 @@ pub(crate) async fn export(
install_options: InstallOptions,
output_file: Option<PathBuf>,
extras: ExtrasSpecification,
dev: DevMode,
dev: DevGroupsSpecification,
editable: EditableMode,
locked: bool,
frozen: bool,
Expand Down Expand Up @@ -141,7 +141,7 @@ pub(crate) async fn export(
&lock,
project.project_name(),
&extras,
&DevSpecification::from(dev),
&dev.with_default_dev(),
editable,
hashes,
&install_options,
Expand Down
6 changes: 3 additions & 3 deletions crates/uv/src/commands/project/remove.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use owo_colors::OwoColorize;
use uv_cache::Cache;
use uv_client::Connectivity;
use uv_configuration::{
Concurrency, DevMode, DevSpecification, EditableMode, ExtrasSpecification, InstallOptions,
LowerBound,
Concurrency, DevGroupsSpecification, DevMode, EditableMode, ExtrasSpecification,
InstallOptions, LowerBound,
};
use uv_fs::Simplified;
use uv_pep508::PackageName;
Expand Down Expand Up @@ -215,7 +215,7 @@ pub(crate) async fn remove(
&venv,
&lock,
&extras,
&DevSpecification::from(dev),
&DevGroupsSpecification::from(dev),
EditableMode::Editable,
install_options,
Modifications::Exact,
Expand Down
Loading
Loading