From e086c06ccdd8e4b1dc9841dc8fd7234fd2036f7a Mon Sep 17 00:00:00 2001 From: Mathieu Kniewallner Date: Wed, 15 Jan 2025 00:10:07 +0100 Subject: [PATCH 1/3] feat: add `--no-groups` flag --- crates/uv-cli/src/lib.rs | 16 +++++ crates/uv-configuration/src/dev.rs | 25 +++++-- crates/uv/src/settings.rs | 12 ++-- crates/uv/tests/it/sync.rs | 101 +++++++++++++++++++++++++++++ docs/reference/cli.md | 8 +++ 5 files changed, 153 insertions(+), 9 deletions(-) diff --git a/crates/uv-cli/src/lib.rs b/crates/uv-cli/src/lib.rs index 2b9ff90f5d14..bfd88adee65a 100644 --- a/crates/uv-cli/src/lib.rs +++ b/crates/uv-cli/src/lib.rs @@ -2707,6 +2707,10 @@ pub struct RunArgs { #[arg(long)] pub no_group: Vec, + /// Exclude dependencies from all dependency groups. + #[arg(long, conflicts_with_all = ["group", "no_group", "only_group"])] + pub no_groups: bool, + /// Only include dependencies from the specified dependency group. /// /// May be provided multiple times. @@ -2972,6 +2976,10 @@ pub struct SyncArgs { #[arg(long)] pub no_group: Vec, + /// Exclude dependencies from all dependency groups. + #[arg(long, conflicts_with_all = ["group", "no_group", "only_group"])] + pub no_groups: bool, + /// Only include dependencies from the specified dependency group. /// /// May be provided multiple times. @@ -3417,6 +3425,10 @@ pub struct TreeArgs { #[arg(long)] pub no_group: Vec, + /// Exclude dependencies from all dependency groups. + #[arg(long, conflicts_with_all = ["group", "no_group", "only_group"])] + pub no_groups: bool, + /// Only include dependencies from the specified dependency group. /// /// May be provided multiple times. @@ -3581,6 +3593,10 @@ pub struct ExportArgs { #[arg(long)] pub no_group: Vec, + /// Exclude dependencies from all dependency groups. + #[arg(long, conflicts_with_all = ["group", "no_group", "only_group"])] + pub no_groups: bool, + /// Only include dependencies from the specified dependency group. /// /// May be provided multiple times. diff --git a/crates/uv-configuration/src/dev.rs b/crates/uv-configuration/src/dev.rs index 3a94c6f4be16..22c99fe4fb70 100644 --- a/crates/uv-configuration/src/dev.rs +++ b/crates/uv-configuration/src/dev.rs @@ -1,5 +1,5 @@ +use either::Either; use std::borrow::Cow; - use uv_normalize::{GroupName, DEV_DEPENDENCIES}; #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] @@ -73,6 +73,8 @@ pub enum GroupsSpecification { include: Vec, exclude: Vec, }, + /// Exclude dependencies from all groups. + Exclude, } impl GroupsSpecification { @@ -86,7 +88,7 @@ impl GroupsSpecification { /// Returns `true` if the specification allows for production dependencies. pub fn prod(&self) -> bool { - matches!(self, Self::Include { .. }) + matches!(self, Self::Include { .. } | Self::Exclude) } /// Returns `true` if the specification is limited to a select set of groups. @@ -118,6 +120,7 @@ impl GroupsSpecification { [group] => Some(Cow::Owned(format!("--only-group {group}"))), [..] => Some(Cow::Borrowed("--only-group")), }, + Self::Exclude => Some(Cow::Borrowed("--no-groups")), } } @@ -125,9 +128,12 @@ impl GroupsSpecification { pub fn names(&self) -> impl Iterator { match self { GroupsSpecification::Include { include, exclude } => { - include.names().chain(exclude.iter()) + Either::Left(include.names().chain(exclude.iter())) + } + GroupsSpecification::Only { include, exclude } => { + Either::Left(include.iter().chain(exclude.iter())) } - GroupsSpecification::Only { include, exclude } => include.iter().chain(exclude.iter()), + GroupsSpecification::Exclude => Either::Right(std::iter::empty()), } } @@ -139,6 +145,7 @@ impl GroupsSpecification { include.contains(group) && !exclude.contains(group) } GroupsSpecification::Only { include, .. } => include.contains(group), + GroupsSpecification::Exclude => false, } } } @@ -178,6 +185,7 @@ impl DevGroupsSpecification { only_dev: bool, mut group: Vec, no_group: Vec, + no_groups: bool, mut only_group: Vec, all_groups: bool, ) -> Self { @@ -191,7 +199,9 @@ impl DevGroupsSpecification { None }; - let groups = if all_groups { + let groups = if no_groups { + Some(GroupsSpecification::Exclude) + } else if all_groups { Some(GroupsSpecification::Include { include: IncludeGroups::All, exclude: no_group, @@ -376,6 +386,11 @@ impl DevGroupsManifest { }; } + // If `--no-groups` was provided, exclude all groups. + if matches!(self.spec.groups(), Some(GroupsSpecification::Exclude)) { + return false; + } + // If `--no-group` was provided, exclude the group from the list of defaults. if let Some(GroupsSpecification::Include { include: _, diff --git a/crates/uv/src/settings.rs b/crates/uv/src/settings.rs index c135845d6c7f..40c88848353a 100644 --- a/crates/uv/src/settings.rs +++ b/crates/uv/src/settings.rs @@ -300,6 +300,7 @@ impl RunSettings { no_dev, group, no_group, + no_groups, only_group, all_groups, module: _, @@ -343,7 +344,7 @@ impl RunSettings { extra.unwrap_or_default(), ), dev: DevGroupsSpecification::from_args( - dev, no_dev, only_dev, group, no_group, only_group, all_groups, + dev, no_dev, only_dev, group, no_group, no_groups, only_group, all_groups, ), editable: EditableMode::from_args(no_editable), modifications: if flag(exact, inexact).unwrap_or(false) { @@ -960,6 +961,7 @@ impl SyncSettings { only_dev, group, no_group, + no_groups, only_group, all_groups, no_editable, @@ -996,7 +998,7 @@ impl SyncSettings { extra.unwrap_or_default(), ), dev: DevGroupsSpecification::from_args( - dev, no_dev, only_dev, group, no_group, only_group, all_groups, + dev, no_dev, only_dev, group, no_group, no_groups, only_group, all_groups, ), editable: EditableMode::from_args(no_editable), install_options: InstallOptions::new( @@ -1316,6 +1318,7 @@ impl TreeSettings { no_dev, group, no_group, + no_groups, only_group, all_groups, locked, @@ -1334,7 +1337,7 @@ impl TreeSettings { Self { dev: DevGroupsSpecification::from_args( - dev, no_dev, only_dev, group, no_group, only_group, all_groups, + dev, no_dev, only_dev, group, no_group, no_groups, only_group, all_groups, ), locked, frozen, @@ -1397,6 +1400,7 @@ impl ExportSettings { only_dev, group, no_group, + no_groups, only_group, all_groups, header, @@ -1432,7 +1436,7 @@ impl ExportSettings { extra.unwrap_or_default(), ), dev: DevGroupsSpecification::from_args( - dev, no_dev, only_dev, group, no_group, only_group, all_groups, + dev, no_dev, only_dev, group, no_group, no_groups, only_group, all_groups, ), editable: EditableMode::from_args(no_editable), hashes: flag(hashes, no_hashes).unwrap_or(true), diff --git a/crates/uv/tests/it/sync.rs b/crates/uv/tests/it/sync.rs index e4a663362d9b..9af8fb2f7765 100644 --- a/crates/uv/tests/it/sync.rs +++ b/crates/uv/tests/it/sync.rs @@ -1259,6 +1259,20 @@ fn sync_dev() -> Result<()> { + sniffio==1.3.1 "###); + // Using `--no-groups` should remove dev dependencies + uv_snapshot!(context.filters(), context.sync().arg("--no-groups"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 5 packages in [TIME] + Uninstalled 3 packages in [TIME] + - anyio==4.3.0 + - idna==3.6 + - sniffio==1.3.1 + "###); + Ok(()) } @@ -1427,6 +1441,42 @@ fn sync_group() -> Result<()> { Audited 1 package in [TIME] "###); + uv_snapshot!(context.filters(), context.sync().arg("--all-groups"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 10 packages in [TIME] + Installed 8 packages in [TIME] + + anyio==4.3.0 + + certifi==2024.2.2 + + charset-normalizer==3.3.2 + + idna==3.6 + + iniconfig==2.0.0 + + requests==2.31.0 + + sniffio==1.3.1 + + urllib3==2.2.1 + "###); + + uv_snapshot!(context.filters(), context.sync().arg("--no-groups"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 10 packages in [TIME] + Uninstalled 8 packages in [TIME] + - anyio==4.3.0 + - certifi==2024.2.2 + - charset-normalizer==3.3.2 + - idna==3.6 + - iniconfig==2.0.0 + - requests==2.31.0 + - sniffio==1.3.1 + - urllib3==2.2.1 + "###); + Ok(()) } @@ -1528,6 +1578,20 @@ fn sync_include_group() -> Result<()> { + typing-extensions==4.10.0 "###); + uv_snapshot!(context.filters(), context.sync().arg("--no-groups"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 6 packages in [TIME] + Uninstalled 4 packages in [TIME] + - anyio==4.3.0 + - idna==3.6 + - iniconfig==2.0.0 + - sniffio==1.3.1 + "###); + Ok(()) } @@ -1923,6 +1987,43 @@ fn sync_default_groups() -> Result<()> { - urllib3==2.2.1 "###); + uv_snapshot!(context.filters(), context.sync().arg("--all-groups"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 10 packages in [TIME] + Installed 8 packages in [TIME] + + anyio==4.3.0 + + certifi==2024.2.2 + + charset-normalizer==3.3.2 + + idna==3.6 + + requests==2.31.0 + + sniffio==1.3.1 + + typing-extensions==4.10.0 + + urllib3==2.2.1 + "###); + + // Using `--no-groups` should exclude all groups + uv_snapshot!(context.filters(), context.sync().arg("--no-groups"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 10 packages in [TIME] + Uninstalled 8 packages in [TIME] + - anyio==4.3.0 + - certifi==2024.2.2 + - charset-normalizer==3.3.2 + - idna==3.6 + - iniconfig==2.0.0 + - requests==2.31.0 + - sniffio==1.3.1 + - urllib3==2.2.1 + "###); + Ok(()) } diff --git a/docs/reference/cli.md b/docs/reference/cli.md index 69367800eeb4..e6981c04f263 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -339,6 +339,8 @@ uv run [OPTIONS] [COMMAND]

May be provided multiple times.

+
--no-groups

Exclude dependencies from all dependency groups

+
--no-index

Ignore the registry index (e.g., PyPI), instead relying on direct URL dependencies and those provided via --find-links

--no-progress

Hide all progress outputs.

@@ -1699,6 +1701,8 @@ uv sync [OPTIONS]

May be provided multiple times.

+
--no-groups

Exclude dependencies from all dependency groups

+
--no-index

Ignore the registry index (e.g., PyPI), instead relying on direct URL dependencies and those provided via --find-links

--no-install-package no-install-package

Do not install the given package(s).

@@ -2417,6 +2421,8 @@ uv export [OPTIONS]

May be provided multiple times.

+
--no-groups

Exclude dependencies from all dependency groups

+
--no-hashes

Omit hashes in the generated output

--no-header

Exclude the comment header at the top of the generated output file

@@ -2773,6 +2779,8 @@ uv tree [OPTIONS]

May be provided multiple times.

+
--no-groups

Exclude dependencies from all dependency groups

+
--no-index

Ignore the registry index (e.g., PyPI), instead relying on direct URL dependencies and those provided via --find-links

--no-progress

Hide all progress outputs.

From 8265ef7c83f64ec3a17453e04f15864081fa416e Mon Sep 17 00:00:00 2001 From: Mathieu Kniewallner Date: Wed, 15 Jan 2025 01:52:19 +0100 Subject: [PATCH 2/3] feat: use `--no-default-groups` instead of `--no-groups` --- crates/uv-cli/src/lib.rs | 32 ++++++---- crates/uv-configuration/src/dev.rs | 31 ++++++---- crates/uv/src/settings.rs | 44 ++++++++++--- crates/uv/tests/it/sync.rs | 99 ++++++++++++++++++++++++++++-- docs/reference/cli.md | 24 +++++--- 5 files changed, 184 insertions(+), 46 deletions(-) diff --git a/crates/uv-cli/src/lib.rs b/crates/uv-cli/src/lib.rs index bfd88adee65a..2b5c6b63e768 100644 --- a/crates/uv-cli/src/lib.rs +++ b/crates/uv-cli/src/lib.rs @@ -2707,9 +2707,11 @@ pub struct RunArgs { #[arg(long)] pub no_group: Vec, - /// Exclude dependencies from all dependency groups. - #[arg(long, conflicts_with_all = ["group", "no_group", "only_group"])] - pub no_groups: bool, + /// Exclude dependencies from default groups. + /// + /// `--group` can be used to include specific groups. + #[arg(long, conflicts_with_all = ["no_group", "only_group"])] + pub no_default_groups: bool, /// Only include dependencies from the specified dependency group. /// @@ -2976,9 +2978,11 @@ pub struct SyncArgs { #[arg(long)] pub no_group: Vec, - /// Exclude dependencies from all dependency groups. - #[arg(long, conflicts_with_all = ["group", "no_group", "only_group"])] - pub no_groups: bool, + /// Exclude dependencies from default groups. + /// + /// `--group` can be used to include specific groups. + #[arg(long, conflicts_with_all = ["no_group", "only_group"])] + pub no_default_groups: bool, /// Only include dependencies from the specified dependency group. /// @@ -3425,9 +3429,11 @@ pub struct TreeArgs { #[arg(long)] pub no_group: Vec, - /// Exclude dependencies from all dependency groups. - #[arg(long, conflicts_with_all = ["group", "no_group", "only_group"])] - pub no_groups: bool, + /// Exclude dependencies from default groups. + /// + /// `--group` can be used to include specific groups. + #[arg(long, conflicts_with_all = ["no_group", "only_group"])] + pub no_default_groups: bool, /// Only include dependencies from the specified dependency group. /// @@ -3593,9 +3599,11 @@ pub struct ExportArgs { #[arg(long)] pub no_group: Vec, - /// Exclude dependencies from all dependency groups. - #[arg(long, conflicts_with_all = ["group", "no_group", "only_group"])] - pub no_groups: bool, + /// Exclude dependencies from default groups. + /// + /// `--group` can be used to include specific groups. + #[arg(long, conflicts_with_all = ["no_group", "only_group"])] + pub no_default_groups: bool, /// Only include dependencies from the specified dependency group. /// diff --git a/crates/uv-configuration/src/dev.rs b/crates/uv-configuration/src/dev.rs index 22c99fe4fb70..85f8589aac06 100644 --- a/crates/uv-configuration/src/dev.rs +++ b/crates/uv-configuration/src/dev.rs @@ -65,6 +65,10 @@ pub enum GroupsSpecification { include: IncludeGroups, exclude: Vec, }, + /// Explicitly include dependencies from the specified groups. + /// + /// If the list is empty, no group will be included. + IncludeExplicitly(Vec), /// Only include dependencies from the specified groups, exclude all other dependencies. /// /// The `include` list is guaranteed to omit groups in the `exclude` list (i.e., they have an @@ -73,8 +77,6 @@ pub enum GroupsSpecification { include: Vec, exclude: Vec, }, - /// Exclude dependencies from all groups. - Exclude, } impl GroupsSpecification { @@ -88,7 +90,7 @@ impl GroupsSpecification { /// Returns `true` if the specification allows for production dependencies. pub fn prod(&self) -> bool { - matches!(self, Self::Include { .. } | Self::Exclude) + matches!(self, Self::Include { .. } | Self::IncludeExplicitly(_)) } /// Returns `true` if the specification is limited to a select set of groups. @@ -120,7 +122,11 @@ impl GroupsSpecification { [group] => Some(Cow::Owned(format!("--only-group {group}"))), [..] => Some(Cow::Borrowed("--only-group")), }, - Self::Exclude => Some(Cow::Borrowed("--no-groups")), + Self::IncludeExplicitly(include) => match include.as_slice() { + [] => Some(Cow::Borrowed("--no-default-groups")), + [group] => Some(Cow::Owned(format!("--group {group}"))), + [..] => Some(Cow::Borrowed("--group")), + }, } } @@ -133,7 +139,7 @@ impl GroupsSpecification { GroupsSpecification::Only { include, exclude } => { Either::Left(include.iter().chain(exclude.iter())) } - GroupsSpecification::Exclude => Either::Right(std::iter::empty()), + GroupsSpecification::IncludeExplicitly(include) => Either::Right(include.iter()), } } @@ -145,7 +151,7 @@ impl GroupsSpecification { include.contains(group) && !exclude.contains(group) } GroupsSpecification::Only { include, .. } => include.contains(group), - GroupsSpecification::Exclude => false, + GroupsSpecification::IncludeExplicitly(include) => include.contains(group), } } } @@ -185,7 +191,7 @@ impl DevGroupsSpecification { only_dev: bool, mut group: Vec, no_group: Vec, - no_groups: bool, + no_default_groups: bool, mut only_group: Vec, all_groups: bool, ) -> Self { @@ -199,8 +205,8 @@ impl DevGroupsSpecification { None }; - let groups = if no_groups { - Some(GroupsSpecification::Exclude) + let groups = if no_default_groups { + Some(GroupsSpecification::IncludeExplicitly(group)) } else if all_groups { Some(GroupsSpecification::Include { include: IncludeGroups::All, @@ -386,9 +392,10 @@ impl DevGroupsManifest { }; } - // If `--no-groups` was provided, exclude all groups. - if matches!(self.spec.groups(), Some(GroupsSpecification::Exclude)) { - return false; + // If `--no-default-groups` was provided, only include group if it's explicitly + // included with `--group `. + if let Some(GroupsSpecification::IncludeExplicitly(include)) = self.spec.groups() { + return include.contains(group); } // If `--no-group` was provided, exclude the group from the list of defaults. diff --git a/crates/uv/src/settings.rs b/crates/uv/src/settings.rs index 40c88848353a..2637fff91e8d 100644 --- a/crates/uv/src/settings.rs +++ b/crates/uv/src/settings.rs @@ -300,7 +300,7 @@ impl RunSettings { no_dev, group, no_group, - no_groups, + no_default_groups, only_group, all_groups, module: _, @@ -344,7 +344,14 @@ impl RunSettings { extra.unwrap_or_default(), ), dev: DevGroupsSpecification::from_args( - dev, no_dev, only_dev, group, no_group, no_groups, only_group, all_groups, + dev, + no_dev, + only_dev, + group, + no_group, + no_default_groups, + only_group, + all_groups, ), editable: EditableMode::from_args(no_editable), modifications: if flag(exact, inexact).unwrap_or(false) { @@ -961,7 +968,7 @@ impl SyncSettings { only_dev, group, no_group, - no_groups, + no_default_groups, only_group, all_groups, no_editable, @@ -998,7 +1005,14 @@ impl SyncSettings { extra.unwrap_or_default(), ), dev: DevGroupsSpecification::from_args( - dev, no_dev, only_dev, group, no_group, no_groups, only_group, all_groups, + dev, + no_dev, + only_dev, + group, + no_group, + no_default_groups, + only_group, + all_groups, ), editable: EditableMode::from_args(no_editable), install_options: InstallOptions::new( @@ -1318,7 +1332,7 @@ impl TreeSettings { no_dev, group, no_group, - no_groups, + no_default_groups, only_group, all_groups, locked, @@ -1337,7 +1351,14 @@ impl TreeSettings { Self { dev: DevGroupsSpecification::from_args( - dev, no_dev, only_dev, group, no_group, no_groups, only_group, all_groups, + dev, + no_dev, + only_dev, + group, + no_group, + no_default_groups, + only_group, + all_groups, ), locked, frozen, @@ -1400,7 +1421,7 @@ impl ExportSettings { only_dev, group, no_group, - no_groups, + no_default_groups, only_group, all_groups, header, @@ -1436,7 +1457,14 @@ impl ExportSettings { extra.unwrap_or_default(), ), dev: DevGroupsSpecification::from_args( - dev, no_dev, only_dev, group, no_group, no_groups, only_group, all_groups, + dev, + no_dev, + only_dev, + group, + no_group, + no_default_groups, + only_group, + all_groups, ), editable: EditableMode::from_args(no_editable), hashes: flag(hashes, no_hashes).unwrap_or(true), diff --git a/crates/uv/tests/it/sync.rs b/crates/uv/tests/it/sync.rs index 9af8fb2f7765..7209e42b88c2 100644 --- a/crates/uv/tests/it/sync.rs +++ b/crates/uv/tests/it/sync.rs @@ -1259,8 +1259,8 @@ fn sync_dev() -> Result<()> { + sniffio==1.3.1 "###); - // Using `--no-groups` should remove dev dependencies - uv_snapshot!(context.filters(), context.sync().arg("--no-groups"), @r###" + // Using `--no-default-groups` should remove dev dependencies + uv_snapshot!(context.filters(), context.sync().arg("--no-default-groups"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -1459,7 +1459,8 @@ fn sync_group() -> Result<()> { + urllib3==2.2.1 "###); - uv_snapshot!(context.filters(), context.sync().arg("--no-groups"), @r###" + // Using `--no-default-groups` should exclude all groups + uv_snapshot!(context.filters(), context.sync().arg("--no-default-groups"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -1477,6 +1478,37 @@ fn sync_group() -> Result<()> { - urllib3==2.2.1 "###); + uv_snapshot!(context.filters(), context.sync().arg("--all-groups"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 10 packages in [TIME] + Installed 8 packages in [TIME] + + anyio==4.3.0 + + certifi==2024.2.2 + + charset-normalizer==3.3.2 + + idna==3.6 + + iniconfig==2.0.0 + + requests==2.31.0 + + sniffio==1.3.1 + + urllib3==2.2.1 + "###); + + // Using `--no-default-groups` with `--group foo` and `--group bar` should include those groups, + // excluding the remaining `dev` group. + uv_snapshot!(context.filters(), context.sync().arg("--no-default-groups").arg("--group").arg("foo").arg("--group").arg("bar"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 10 packages in [TIME] + Uninstalled 1 package in [TIME] + - iniconfig==2.0.0 + "###); + Ok(()) } @@ -1578,7 +1610,7 @@ fn sync_include_group() -> Result<()> { + typing-extensions==4.10.0 "###); - uv_snapshot!(context.filters(), context.sync().arg("--no-groups"), @r###" + uv_snapshot!(context.filters(), context.sync().arg("--no-default-groups"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -1592,6 +1624,30 @@ fn sync_include_group() -> Result<()> { - sniffio==1.3.1 "###); + uv_snapshot!(context.filters(), context.sync().arg("--all-groups"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 6 packages in [TIME] + Installed 4 packages in [TIME] + + anyio==4.3.0 + + idna==3.6 + + iniconfig==2.0.0 + + sniffio==1.3.1 + "###); + + uv_snapshot!(context.filters(), context.sync().arg("--no-default-groups").arg("--group").arg("foo"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 6 packages in [TIME] + Audited 5 packages in [TIME] + "###); + Ok(()) } @@ -2005,8 +2061,8 @@ fn sync_default_groups() -> Result<()> { + urllib3==2.2.1 "###); - // Using `--no-groups` should exclude all groups - uv_snapshot!(context.filters(), context.sync().arg("--no-groups"), @r###" + // Using `--no-default-groups` should exclude all groups + uv_snapshot!(context.filters(), context.sync().arg("--no-default-groups"), @r###" success: true exit_code: 0 ----- stdout ----- @@ -2024,6 +2080,37 @@ fn sync_default_groups() -> Result<()> { - urllib3==2.2.1 "###); + uv_snapshot!(context.filters(), context.sync().arg("--all-groups"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 10 packages in [TIME] + Installed 8 packages in [TIME] + + anyio==4.3.0 + + certifi==2024.2.2 + + charset-normalizer==3.3.2 + + idna==3.6 + + iniconfig==2.0.0 + + requests==2.31.0 + + sniffio==1.3.1 + + urllib3==2.2.1 + "###); + + // Using `--no-default-groups` with `--group foo` and `--group bar` should include those groups, + // excluding the remaining `dev` group. + uv_snapshot!(context.filters(), context.sync().arg("--no-default-groups").arg("--group").arg("foo").arg("--group").arg("bar"), @r###" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + Resolved 10 packages in [TIME] + Uninstalled 1 package in [TIME] + - iniconfig==2.0.0 + "###); + Ok(()) } diff --git a/docs/reference/cli.md b/docs/reference/cli.md index e6981c04f263..a33bcda08bc9 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -320,6 +320,10 @@ uv run [OPTIONS] [COMMAND]

Normally, configuration files are discovered in the current directory, parent directories, or user configuration directories.

May also be set with the UV_NO_CONFIG environment variable.

+
--no-default-groups

Exclude dependencies from default groups.

+ +

--group can be used to include specific groups.

+
--no-dev

Omit the development dependency group.

This option is an alias of --no-group dev.

@@ -339,8 +343,6 @@ uv run [OPTIONS] [COMMAND]

May be provided multiple times.

-
--no-groups

Exclude dependencies from all dependency groups

-
--no-index

Ignore the registry index (e.g., PyPI), instead relying on direct URL dependencies and those provided via --find-links

--no-progress

Hide all progress outputs.

@@ -1687,6 +1689,10 @@ uv sync [OPTIONS]

Normally, configuration files are discovered in the current directory, parent directories, or user configuration directories.

May also be set with the UV_NO_CONFIG environment variable.

+
--no-default-groups

Exclude dependencies from default groups.

+ +

--group can be used to include specific groups.

+
--no-dev

Omit the development dependency group.

This option is an alias for --no-group dev.

@@ -1701,8 +1707,6 @@ uv sync [OPTIONS]

May be provided multiple times.

-
--no-groups

Exclude dependencies from all dependency groups

-
--no-index

Ignore the registry index (e.g., PyPI), instead relying on direct URL dependencies and those provided via --find-links

--no-install-package no-install-package

Do not install the given package(s).

@@ -2395,6 +2399,10 @@ uv export [OPTIONS]

Normally, configuration files are discovered in the current directory, parent directories, or user configuration directories.

May also be set with the UV_NO_CONFIG environment variable.

+
--no-default-groups

Exclude dependencies from default groups.

+ +

--group can be used to include specific groups.

+
--no-dev

Omit the development dependency group.

This option is an alias for --no-group dev.

@@ -2421,8 +2429,6 @@ uv export [OPTIONS]

May be provided multiple times.

-
--no-groups

Exclude dependencies from all dependency groups

-
--no-hashes

Omit hashes in the generated output

--no-header

Exclude the comment header at the top of the generated output file

@@ -2771,6 +2777,10 @@ uv tree [OPTIONS]

May also be set with the UV_NO_CONFIG environment variable.

--no-dedupe

Do not de-duplicate repeated dependencies. Usually, when a package has already displayed its dependencies, further occurrences will not re-display its dependencies, and will include a (*) to indicate it has already been shown. This flag will cause those duplicates to be repeated

+
--no-default-groups

Exclude dependencies from default groups.

+ +

--group can be used to include specific groups.

+
--no-dev

Omit the development dependency group.

This option is an alias for --no-group dev.

@@ -2779,8 +2789,6 @@ uv tree [OPTIONS]

May be provided multiple times.

-
--no-groups

Exclude dependencies from all dependency groups

-
--no-index

Ignore the registry index (e.g., PyPI), instead relying on direct URL dependencies and those provided via --find-links

--no-progress

Hide all progress outputs.

From 94be11590d4756909a0b7c0151f0d5a211ec4645 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Tue, 21 Jan 2025 17:51:23 -0500 Subject: [PATCH 3/3] Small tweaks --- crates/uv-configuration/src/dev.rs | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/crates/uv-configuration/src/dev.rs b/crates/uv-configuration/src/dev.rs index 85f8589aac06..8a2a43d2ce11 100644 --- a/crates/uv-configuration/src/dev.rs +++ b/crates/uv-configuration/src/dev.rs @@ -1,5 +1,7 @@ -use either::Either; use std::borrow::Cow; + +use either::Either; + use uv_normalize::{GroupName, DEV_DEPENDENCIES}; #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] @@ -57,7 +59,8 @@ pub struct DevGroupsSpecification { #[derive(Debug, Clone)] pub enum GroupsSpecification { - /// Include dependencies from the specified groups. + /// Include dependencies from the specified groups alongside the default groups (omitting + /// those default groups that are explicitly excluded). /// /// If the `include` is `IncludeGroups::Some`, it is guaranteed to omit groups in the `exclude` /// list (i.e., they have an empty intersection). @@ -65,10 +68,10 @@ pub enum GroupsSpecification { include: IncludeGroups, exclude: Vec, }, - /// Explicitly include dependencies from the specified groups. + /// Include dependencies from the specified groups, omitting any default groups. /// /// If the list is empty, no group will be included. - IncludeExplicitly(Vec), + Explicit { include: Vec }, /// Only include dependencies from the specified groups, exclude all other dependencies. /// /// The `include` list is guaranteed to omit groups in the `exclude` list (i.e., they have an @@ -90,7 +93,7 @@ impl GroupsSpecification { /// Returns `true` if the specification allows for production dependencies. pub fn prod(&self) -> bool { - matches!(self, Self::Include { .. } | Self::IncludeExplicitly(_)) + matches!(self, Self::Include { .. } | Self::Explicit { .. }) } /// Returns `true` if the specification is limited to a select set of groups. @@ -122,7 +125,7 @@ impl GroupsSpecification { [group] => Some(Cow::Owned(format!("--only-group {group}"))), [..] => Some(Cow::Borrowed("--only-group")), }, - Self::IncludeExplicitly(include) => match include.as_slice() { + Self::Explicit { include } => match include.as_slice() { [] => Some(Cow::Borrowed("--no-default-groups")), [group] => Some(Cow::Owned(format!("--group {group}"))), [..] => Some(Cow::Borrowed("--group")), @@ -139,7 +142,7 @@ impl GroupsSpecification { GroupsSpecification::Only { include, exclude } => { Either::Left(include.iter().chain(exclude.iter())) } - GroupsSpecification::IncludeExplicitly(include) => Either::Right(include.iter()), + GroupsSpecification::Explicit { include } => Either::Right(include.iter()), } } @@ -151,7 +154,7 @@ impl GroupsSpecification { include.contains(group) && !exclude.contains(group) } GroupsSpecification::Only { include, .. } => include.contains(group), - GroupsSpecification::IncludeExplicitly(include) => include.contains(group), + GroupsSpecification::Explicit { include } => include.contains(group), } } } @@ -206,7 +209,10 @@ impl DevGroupsSpecification { }; let groups = if no_default_groups { - Some(GroupsSpecification::IncludeExplicitly(group)) + // Remove groups specified with `--no-group`. + group.retain(|group| !no_group.contains(group)); + + Some(GroupsSpecification::Explicit { include: group }) } else if all_groups { Some(GroupsSpecification::Include { include: IncludeGroups::All, @@ -394,7 +400,7 @@ impl DevGroupsManifest { // If `--no-default-groups` was provided, only include group if it's explicitly // included with `--group `. - if let Some(GroupsSpecification::IncludeExplicitly(include)) = self.spec.groups() { + if let Some(GroupsSpecification::Explicit { include }) = self.spec.groups() { return include.contains(group); }