mirror of
https://github.com/astral-sh/uv.git
synced 2025-11-03 13:14:41 +00:00
Implement uv tree --no-dev (#8109)
## Summary Allow pruning dev-dependencies in uv tree. This is not inherently in conflict with --invert, but this pruning is not yet implemented there.
This commit is contained in:
parent
a3b11dacb8
commit
e67d87301a
7 changed files with 43 additions and 3 deletions
|
|
@ -3070,6 +3070,17 @@ pub struct TreeArgs {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub tree: DisplayTreeArgs,
|
pub tree: DisplayTreeArgs,
|
||||||
|
|
||||||
|
/// Include development dependencies.
|
||||||
|
///
|
||||||
|
/// Development dependencies are defined via `tool.uv.dev-dependencies` in a
|
||||||
|
/// `pyproject.toml`.
|
||||||
|
#[arg(long, overrides_with("no_dev"), hide = true)]
|
||||||
|
pub dev: bool,
|
||||||
|
|
||||||
|
/// Omit development dependencies.
|
||||||
|
#[arg(long, overrides_with("dev"), conflicts_with = "invert")]
|
||||||
|
pub no_dev: bool,
|
||||||
|
|
||||||
/// Assert that the `uv.lock` will remain unchanged.
|
/// Assert that the `uv.lock` will remain unchanged.
|
||||||
///
|
///
|
||||||
/// Requires that the lockfile is up-to-date. If the lockfile is missing or
|
/// Requires that the lockfile is up-to-date. If the lockfile is missing or
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ use std::collections::BTreeSet;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
|
|
||||||
|
use uv_configuration::DevMode;
|
||||||
use uv_normalize::{ExtraName, GroupName, PackageName};
|
use uv_normalize::{ExtraName, GroupName, PackageName};
|
||||||
use uv_pypi_types::ResolverMarkerEnvironment;
|
use uv_pypi_types::ResolverMarkerEnvironment;
|
||||||
|
|
||||||
|
|
@ -22,8 +23,10 @@ pub struct TreeDisplay<'env> {
|
||||||
optional_dependencies:
|
optional_dependencies:
|
||||||
FxHashMap<&'env PackageId, FxHashMap<ExtraName, Vec<Cow<'env, Dependency>>>>,
|
FxHashMap<&'env PackageId, FxHashMap<ExtraName, Vec<Cow<'env, Dependency>>>>,
|
||||||
dev_dependencies: FxHashMap<&'env PackageId, FxHashMap<GroupName, Vec<Cow<'env, Dependency>>>>,
|
dev_dependencies: FxHashMap<&'env PackageId, FxHashMap<GroupName, Vec<Cow<'env, Dependency>>>>,
|
||||||
/// Maximum display depth of the dependency tree
|
/// Maximum display depth of the dependency tree.
|
||||||
depth: usize,
|
depth: usize,
|
||||||
|
/// Whether to include development dependencies in the display.
|
||||||
|
dev: DevMode,
|
||||||
/// Prune the given packages from the display of the dependency tree.
|
/// Prune the given packages from the display of the dependency tree.
|
||||||
prune: Vec<PackageName>,
|
prune: Vec<PackageName>,
|
||||||
/// Display only the specified packages.
|
/// Display only the specified packages.
|
||||||
|
|
@ -40,6 +43,7 @@ impl<'env> TreeDisplay<'env> {
|
||||||
depth: usize,
|
depth: usize,
|
||||||
prune: Vec<PackageName>,
|
prune: Vec<PackageName>,
|
||||||
packages: Vec<PackageName>,
|
packages: Vec<PackageName>,
|
||||||
|
dev: DevMode,
|
||||||
no_dedupe: bool,
|
no_dedupe: bool,
|
||||||
invert: bool,
|
invert: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
|
@ -180,6 +184,7 @@ impl<'env> TreeDisplay<'env> {
|
||||||
optional_dependencies,
|
optional_dependencies,
|
||||||
dev_dependencies,
|
dev_dependencies,
|
||||||
depth,
|
depth,
|
||||||
|
dev,
|
||||||
prune,
|
prune,
|
||||||
packages,
|
packages,
|
||||||
no_dedupe,
|
no_dedupe,
|
||||||
|
|
@ -231,12 +236,14 @@ impl<'env> TreeDisplay<'env> {
|
||||||
let dependencies: Vec<Node<'env>> = self
|
let dependencies: Vec<Node<'env>> = self
|
||||||
.dependencies
|
.dependencies
|
||||||
.get(node.package_id())
|
.get(node.package_id())
|
||||||
|
.filter(|_| self.dev != DevMode::Only)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten()
|
.flatten()
|
||||||
.map(|dep| Node::Dependency(dep.as_ref()))
|
.map(|dep| Node::Dependency(dep.as_ref()))
|
||||||
.chain(
|
.chain(
|
||||||
self.optional_dependencies
|
self.optional_dependencies
|
||||||
.get(node.package_id())
|
.get(node.package_id())
|
||||||
|
.filter(|_| self.dev != DevMode::Only)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten()
|
.flatten()
|
||||||
.flat_map(|(extra, deps)| {
|
.flat_map(|(extra, deps)| {
|
||||||
|
|
@ -247,6 +254,7 @@ impl<'env> TreeDisplay<'env> {
|
||||||
.chain(
|
.chain(
|
||||||
self.dev_dependencies
|
self.dev_dependencies
|
||||||
.get(node.package_id())
|
.get(node.package_id())
|
||||||
|
.filter(|_| self.dev != DevMode::Exclude)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten()
|
.flatten()
|
||||||
.flat_map(|(group, deps)| {
|
.flat_map(|(group, deps)| {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use std::path::Path;
|
||||||
|
|
||||||
use uv_cache::Cache;
|
use uv_cache::Cache;
|
||||||
use uv_client::Connectivity;
|
use uv_client::Connectivity;
|
||||||
use uv_configuration::{Concurrency, TargetTriple};
|
use uv_configuration::{Concurrency, DevMode, TargetTriple};
|
||||||
use uv_pep508::PackageName;
|
use uv_pep508::PackageName;
|
||||||
use uv_python::{PythonDownloads, PythonPreference, PythonRequest, PythonVersion};
|
use uv_python::{PythonDownloads, PythonPreference, PythonRequest, PythonVersion};
|
||||||
use uv_resolver::TreeDisplay;
|
use uv_resolver::TreeDisplay;
|
||||||
|
|
@ -21,6 +21,7 @@ use crate::settings::ResolverSettings;
|
||||||
#[allow(clippy::fn_params_excessive_bools)]
|
#[allow(clippy::fn_params_excessive_bools)]
|
||||||
pub(crate) async fn tree(
|
pub(crate) async fn tree(
|
||||||
project_dir: &Path,
|
project_dir: &Path,
|
||||||
|
dev: DevMode,
|
||||||
locked: bool,
|
locked: bool,
|
||||||
frozen: bool,
|
frozen: bool,
|
||||||
universal: bool,
|
universal: bool,
|
||||||
|
|
@ -89,6 +90,7 @@ pub(crate) async fn tree(
|
||||||
depth.into(),
|
depth.into(),
|
||||||
prune,
|
prune,
|
||||||
package,
|
package,
|
||||||
|
dev,
|
||||||
no_dedupe,
|
no_dedupe,
|
||||||
invert,
|
invert,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1444,6 +1444,7 @@ async fn run_project(
|
||||||
|
|
||||||
commands::tree(
|
commands::tree(
|
||||||
project_dir,
|
project_dir,
|
||||||
|
args.dev,
|
||||||
args.locked,
|
args.locked,
|
||||||
args.frozen,
|
args.frozen,
|
||||||
args.universal,
|
args.universal,
|
||||||
|
|
|
||||||
|
|
@ -936,6 +936,7 @@ impl RemoveSettings {
|
||||||
#[allow(clippy::struct_excessive_bools)]
|
#[allow(clippy::struct_excessive_bools)]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct TreeSettings {
|
pub(crate) struct TreeSettings {
|
||||||
|
pub(crate) dev: DevMode,
|
||||||
pub(crate) locked: bool,
|
pub(crate) locked: bool,
|
||||||
pub(crate) frozen: bool,
|
pub(crate) frozen: bool,
|
||||||
pub(crate) universal: bool,
|
pub(crate) universal: bool,
|
||||||
|
|
@ -956,6 +957,8 @@ impl TreeSettings {
|
||||||
let TreeArgs {
|
let TreeArgs {
|
||||||
tree,
|
tree,
|
||||||
universal,
|
universal,
|
||||||
|
dev,
|
||||||
|
no_dev,
|
||||||
locked,
|
locked,
|
||||||
frozen,
|
frozen,
|
||||||
build,
|
build,
|
||||||
|
|
@ -966,6 +969,7 @@ impl TreeSettings {
|
||||||
} = args;
|
} = args;
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
dev: DevMode::from_args(dev, no_dev, false),
|
||||||
locked,
|
locked,
|
||||||
frozen,
|
frozen,
|
||||||
universal,
|
universal,
|
||||||
|
|
|
||||||
|
|
@ -438,7 +438,7 @@ fn dev_dependencies() -> Result<()> {
|
||||||
"#,
|
"#,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
uv_snapshot!(context.filters(), context.tree().arg("--universal"), @r###"
|
uv_snapshot!(context.filters(), context.tree(), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
|
@ -453,6 +453,18 @@ fn dev_dependencies() -> Result<()> {
|
||||||
"###
|
"###
|
||||||
);
|
);
|
||||||
|
|
||||||
|
uv_snapshot!(context.filters(), context.tree().arg("--no-dev"), @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
project v0.1.0
|
||||||
|
└── iniconfig v2.0.0
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
Resolved 5 packages in [TIME]
|
||||||
|
"###
|
||||||
|
);
|
||||||
|
|
||||||
// `uv tree` should update the lockfile
|
// `uv tree` should update the lockfile
|
||||||
let lock = context.read("uv.lock");
|
let lock = context.read("uv.lock");
|
||||||
assert!(!lock.is_empty());
|
assert!(!lock.is_empty());
|
||||||
|
|
|
||||||
|
|
@ -2329,6 +2329,8 @@ uv tree [OPTIONS]
|
||||||
<p>May also be set with the <code>UV_NO_CONFIG</code> environment variable.</p>
|
<p>May also be set with the <code>UV_NO_CONFIG</code> environment variable.</p>
|
||||||
</dd><dt><code>--no-dedupe</code></dt><dd><p>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</p>
|
</dd><dt><code>--no-dedupe</code></dt><dd><p>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</p>
|
||||||
|
|
||||||
|
</dd><dt><code>--no-dev</code></dt><dd><p>Omit development dependencies</p>
|
||||||
|
|
||||||
</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>
|
</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>
|
||||||
|
|
||||||
</dd><dt><code>--no-progress</code></dt><dd><p>Hide all progress outputs.</p>
|
</dd><dt><code>--no-progress</code></dt><dd><p>Hide all progress outputs.</p>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue