Skip to content

Commit e086c06

Browse files
committed
feat: add --no-groups flag
1 parent 9e06aa8 commit e086c06

File tree

5 files changed

+153
-9
lines changed

5 files changed

+153
-9
lines changed

crates/uv-cli/src/lib.rs

+16
Original file line numberDiff line numberDiff line change
@@ -2707,6 +2707,10 @@ pub struct RunArgs {
27072707
#[arg(long)]
27082708
pub no_group: Vec<GroupName>,
27092709

2710+
/// Exclude dependencies from all dependency groups.
2711+
#[arg(long, conflicts_with_all = ["group", "no_group", "only_group"])]
2712+
pub no_groups: bool,
2713+
27102714
/// Only include dependencies from the specified dependency group.
27112715
///
27122716
/// May be provided multiple times.
@@ -2972,6 +2976,10 @@ pub struct SyncArgs {
29722976
#[arg(long)]
29732977
pub no_group: Vec<GroupName>,
29742978

2979+
/// Exclude dependencies from all dependency groups.
2980+
#[arg(long, conflicts_with_all = ["group", "no_group", "only_group"])]
2981+
pub no_groups: bool,
2982+
29752983
/// Only include dependencies from the specified dependency group.
29762984
///
29772985
/// May be provided multiple times.
@@ -3417,6 +3425,10 @@ pub struct TreeArgs {
34173425
#[arg(long)]
34183426
pub no_group: Vec<GroupName>,
34193427

3428+
/// Exclude dependencies from all dependency groups.
3429+
#[arg(long, conflicts_with_all = ["group", "no_group", "only_group"])]
3430+
pub no_groups: bool,
3431+
34203432
/// Only include dependencies from the specified dependency group.
34213433
///
34223434
/// May be provided multiple times.
@@ -3581,6 +3593,10 @@ pub struct ExportArgs {
35813593
#[arg(long)]
35823594
pub no_group: Vec<GroupName>,
35833595

3596+
/// Exclude dependencies from all dependency groups.
3597+
#[arg(long, conflicts_with_all = ["group", "no_group", "only_group"])]
3598+
pub no_groups: bool,
3599+
35843600
/// Only include dependencies from the specified dependency group.
35853601
///
35863602
/// May be provided multiple times.

crates/uv-configuration/src/dev.rs

+20-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
use either::Either;
12
use std::borrow::Cow;
2-
33
use uv_normalize::{GroupName, DEV_DEPENDENCIES};
44

55
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
@@ -73,6 +73,8 @@ pub enum GroupsSpecification {
7373
include: Vec<GroupName>,
7474
exclude: Vec<GroupName>,
7575
},
76+
/// Exclude dependencies from all groups.
77+
Exclude,
7678
}
7779

7880
impl GroupsSpecification {
@@ -86,7 +88,7 @@ impl GroupsSpecification {
8688

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

9294
/// Returns `true` if the specification is limited to a select set of groups.
@@ -118,16 +120,20 @@ impl GroupsSpecification {
118120
[group] => Some(Cow::Owned(format!("--only-group {group}"))),
119121
[..] => Some(Cow::Borrowed("--only-group")),
120122
},
123+
Self::Exclude => Some(Cow::Borrowed("--no-groups")),
121124
}
122125
}
123126

124127
/// Iterate over all groups referenced in the [`DevGroupsSpecification`].
125128
pub fn names(&self) -> impl Iterator<Item = &GroupName> {
126129
match self {
127130
GroupsSpecification::Include { include, exclude } => {
128-
include.names().chain(exclude.iter())
131+
Either::Left(include.names().chain(exclude.iter()))
132+
}
133+
GroupsSpecification::Only { include, exclude } => {
134+
Either::Left(include.iter().chain(exclude.iter()))
129135
}
130-
GroupsSpecification::Only { include, exclude } => include.iter().chain(exclude.iter()),
136+
GroupsSpecification::Exclude => Either::Right(std::iter::empty()),
131137
}
132138
}
133139

@@ -139,6 +145,7 @@ impl GroupsSpecification {
139145
include.contains(group) && !exclude.contains(group)
140146
}
141147
GroupsSpecification::Only { include, .. } => include.contains(group),
148+
GroupsSpecification::Exclude => false,
142149
}
143150
}
144151
}
@@ -178,6 +185,7 @@ impl DevGroupsSpecification {
178185
only_dev: bool,
179186
mut group: Vec<GroupName>,
180187
no_group: Vec<GroupName>,
188+
no_groups: bool,
181189
mut only_group: Vec<GroupName>,
182190
all_groups: bool,
183191
) -> Self {
@@ -191,7 +199,9 @@ impl DevGroupsSpecification {
191199
None
192200
};
193201

194-
let groups = if all_groups {
202+
let groups = if no_groups {
203+
Some(GroupsSpecification::Exclude)
204+
} else if all_groups {
195205
Some(GroupsSpecification::Include {
196206
include: IncludeGroups::All,
197207
exclude: no_group,
@@ -376,6 +386,11 @@ impl DevGroupsManifest {
376386
};
377387
}
378388

389+
// If `--no-groups` was provided, exclude all groups.
390+
if matches!(self.spec.groups(), Some(GroupsSpecification::Exclude)) {
391+
return false;
392+
}
393+
379394
// If `--no-group` was provided, exclude the group from the list of defaults.
380395
if let Some(GroupsSpecification::Include {
381396
include: _,

crates/uv/src/settings.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ impl RunSettings {
300300
no_dev,
301301
group,
302302
no_group,
303+
no_groups,
303304
only_group,
304305
all_groups,
305306
module: _,
@@ -343,7 +344,7 @@ impl RunSettings {
343344
extra.unwrap_or_default(),
344345
),
345346
dev: DevGroupsSpecification::from_args(
346-
dev, no_dev, only_dev, group, no_group, only_group, all_groups,
347+
dev, no_dev, only_dev, group, no_group, no_groups, only_group, all_groups,
347348
),
348349
editable: EditableMode::from_args(no_editable),
349350
modifications: if flag(exact, inexact).unwrap_or(false) {
@@ -960,6 +961,7 @@ impl SyncSettings {
960961
only_dev,
961962
group,
962963
no_group,
964+
no_groups,
963965
only_group,
964966
all_groups,
965967
no_editable,
@@ -996,7 +998,7 @@ impl SyncSettings {
996998
extra.unwrap_or_default(),
997999
),
9981000
dev: DevGroupsSpecification::from_args(
999-
dev, no_dev, only_dev, group, no_group, only_group, all_groups,
1001+
dev, no_dev, only_dev, group, no_group, no_groups, only_group, all_groups,
10001002
),
10011003
editable: EditableMode::from_args(no_editable),
10021004
install_options: InstallOptions::new(
@@ -1316,6 +1318,7 @@ impl TreeSettings {
13161318
no_dev,
13171319
group,
13181320
no_group,
1321+
no_groups,
13191322
only_group,
13201323
all_groups,
13211324
locked,
@@ -1334,7 +1337,7 @@ impl TreeSettings {
13341337

13351338
Self {
13361339
dev: DevGroupsSpecification::from_args(
1337-
dev, no_dev, only_dev, group, no_group, only_group, all_groups,
1340+
dev, no_dev, only_dev, group, no_group, no_groups, only_group, all_groups,
13381341
),
13391342
locked,
13401343
frozen,
@@ -1397,6 +1400,7 @@ impl ExportSettings {
13971400
only_dev,
13981401
group,
13991402
no_group,
1403+
no_groups,
14001404
only_group,
14011405
all_groups,
14021406
header,
@@ -1432,7 +1436,7 @@ impl ExportSettings {
14321436
extra.unwrap_or_default(),
14331437
),
14341438
dev: DevGroupsSpecification::from_args(
1435-
dev, no_dev, only_dev, group, no_group, only_group, all_groups,
1439+
dev, no_dev, only_dev, group, no_group, no_groups, only_group, all_groups,
14361440
),
14371441
editable: EditableMode::from_args(no_editable),
14381442
hashes: flag(hashes, no_hashes).unwrap_or(true),

crates/uv/tests/it/sync.rs

+101
Original file line numberDiff line numberDiff line change
@@ -1259,6 +1259,20 @@ fn sync_dev() -> Result<()> {
12591259
+ sniffio==1.3.1
12601260
"###);
12611261

1262+
// Using `--no-groups` should remove dev dependencies
1263+
uv_snapshot!(context.filters(), context.sync().arg("--no-groups"), @r###"
1264+
success: true
1265+
exit_code: 0
1266+
----- stdout -----
1267+
1268+
----- stderr -----
1269+
Resolved 5 packages in [TIME]
1270+
Uninstalled 3 packages in [TIME]
1271+
- anyio==4.3.0
1272+
- idna==3.6
1273+
- sniffio==1.3.1
1274+
"###);
1275+
12621276
Ok(())
12631277
}
12641278

@@ -1427,6 +1441,42 @@ fn sync_group() -> Result<()> {
14271441
Audited 1 package in [TIME]
14281442
"###);
14291443

1444+
uv_snapshot!(context.filters(), context.sync().arg("--all-groups"), @r###"
1445+
success: true
1446+
exit_code: 0
1447+
----- stdout -----
1448+
1449+
----- stderr -----
1450+
Resolved 10 packages in [TIME]
1451+
Installed 8 packages in [TIME]
1452+
+ anyio==4.3.0
1453+
+ certifi==2024.2.2
1454+
+ charset-normalizer==3.3.2
1455+
+ idna==3.6
1456+
+ iniconfig==2.0.0
1457+
+ requests==2.31.0
1458+
+ sniffio==1.3.1
1459+
+ urllib3==2.2.1
1460+
"###);
1461+
1462+
uv_snapshot!(context.filters(), context.sync().arg("--no-groups"), @r###"
1463+
success: true
1464+
exit_code: 0
1465+
----- stdout -----
1466+
1467+
----- stderr -----
1468+
Resolved 10 packages in [TIME]
1469+
Uninstalled 8 packages in [TIME]
1470+
- anyio==4.3.0
1471+
- certifi==2024.2.2
1472+
- charset-normalizer==3.3.2
1473+
- idna==3.6
1474+
- iniconfig==2.0.0
1475+
- requests==2.31.0
1476+
- sniffio==1.3.1
1477+
- urllib3==2.2.1
1478+
"###);
1479+
14301480
Ok(())
14311481
}
14321482

@@ -1528,6 +1578,20 @@ fn sync_include_group() -> Result<()> {
15281578
+ typing-extensions==4.10.0
15291579
"###);
15301580

1581+
uv_snapshot!(context.filters(), context.sync().arg("--no-groups"), @r###"
1582+
success: true
1583+
exit_code: 0
1584+
----- stdout -----
1585+
1586+
----- stderr -----
1587+
Resolved 6 packages in [TIME]
1588+
Uninstalled 4 packages in [TIME]
1589+
- anyio==4.3.0
1590+
- idna==3.6
1591+
- iniconfig==2.0.0
1592+
- sniffio==1.3.1
1593+
"###);
1594+
15311595
Ok(())
15321596
}
15331597

@@ -1923,6 +1987,43 @@ fn sync_default_groups() -> Result<()> {
19231987
- urllib3==2.2.1
19241988
"###);
19251989

1990+
uv_snapshot!(context.filters(), context.sync().arg("--all-groups"), @r###"
1991+
success: true
1992+
exit_code: 0
1993+
----- stdout -----
1994+
1995+
----- stderr -----
1996+
Resolved 10 packages in [TIME]
1997+
Installed 8 packages in [TIME]
1998+
+ anyio==4.3.0
1999+
+ certifi==2024.2.2
2000+
+ charset-normalizer==3.3.2
2001+
+ idna==3.6
2002+
+ requests==2.31.0
2003+
+ sniffio==1.3.1
2004+
+ typing-extensions==4.10.0
2005+
+ urllib3==2.2.1
2006+
"###);
2007+
2008+
// Using `--no-groups` should exclude all groups
2009+
uv_snapshot!(context.filters(), context.sync().arg("--no-groups"), @r###"
2010+
success: true
2011+
exit_code: 0
2012+
----- stdout -----
2013+
2014+
----- stderr -----
2015+
Resolved 10 packages in [TIME]
2016+
Uninstalled 8 packages in [TIME]
2017+
- anyio==4.3.0
2018+
- certifi==2024.2.2
2019+
- charset-normalizer==3.3.2
2020+
- idna==3.6
2021+
- iniconfig==2.0.0
2022+
- requests==2.31.0
2023+
- sniffio==1.3.1
2024+
- urllib3==2.2.1
2025+
"###);
2026+
19262027
Ok(())
19272028
}
19282029

docs/reference/cli.md

+8
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,8 @@ uv run [OPTIONS] [COMMAND]
339339

340340
<p>May be provided multiple times.</p>
341341

342+
</dd><dt><code>--no-groups</code></dt><dd><p>Exclude dependencies from all dependency groups</p>
343+
342344
</dd><dt><code>--no-index</code></dt><dd><p>Ignore the registry index (e.g., PyPI), instead relying on direct URL dependencies and those provided via <code>--find-links</code></p>
343345

344346
</dd><dt><code>--no-progress</code></dt><dd><p>Hide all progress outputs.</p>
@@ -1699,6 +1701,8 @@ uv sync [OPTIONS]
16991701

17001702
<p>May be provided multiple times.</p>
17011703

1704+
</dd><dt><code>--no-groups</code></dt><dd><p>Exclude dependencies from all dependency groups</p>
1705+
17021706
</dd><dt><code>--no-index</code></dt><dd><p>Ignore the registry index (e.g., PyPI), instead relying on direct URL dependencies and those provided via <code>--find-links</code></p>
17031707

17041708
</dd><dt><code>--no-install-package</code> <i>no-install-package</i></dt><dd><p>Do not install the given package(s).</p>
@@ -2417,6 +2421,8 @@ uv export [OPTIONS]
24172421

24182422
<p>May be provided multiple times.</p>
24192423

2424+
</dd><dt><code>--no-groups</code></dt><dd><p>Exclude dependencies from all dependency groups</p>
2425+
24202426
</dd><dt><code>--no-hashes</code></dt><dd><p>Omit hashes in the generated output</p>
24212427

24222428
</dd><dt><code>--no-header</code></dt><dd><p>Exclude the comment header at the top of the generated output file</p>
@@ -2773,6 +2779,8 @@ uv tree [OPTIONS]
27732779

27742780
<p>May be provided multiple times.</p>
27752781

2782+
</dd><dt><code>--no-groups</code></dt><dd><p>Exclude dependencies from all dependency groups</p>
2783+
27762784
</dd><dt><code>--no-index</code></dt><dd><p>Ignore the registry index (e.g., PyPI), instead relying on direct URL dependencies and those provided via <code>--find-links</code></p>
27772785

27782786
</dd><dt><code>--no-progress</code></dt><dd><p>Hide all progress outputs.</p>

0 commit comments

Comments
 (0)