mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-04 19:08:04 +00:00
Avoid lingering dev and optional dependencies in uv tree
(#5766)
## Summary Dev and optional dependencies were appearing at the top-level.
This commit is contained in:
parent
a9a535da14
commit
7567039b80
2 changed files with 82 additions and 8 deletions
|
@ -2631,6 +2631,8 @@ fn each_element_on_its_line_array(elements: impl Iterator<Item = impl Into<Value
|
|||
pub struct TreeDisplay<'env> {
|
||||
/// The underlying [`Lock`] to display.
|
||||
lock: &'env Lock,
|
||||
/// The root nodes in the [`Lock`].
|
||||
roots: Vec<&'env DistributionId>,
|
||||
/// The edges in the [`Lock`].
|
||||
///
|
||||
/// While the dependencies exist on the [`Lock`] directly, if `--invert` is enabled, the
|
||||
|
@ -2656,8 +2658,10 @@ impl<'env> TreeDisplay<'env> {
|
|||
no_dedupe: bool,
|
||||
invert: bool,
|
||||
) -> Self {
|
||||
let mut non_roots = FxHashSet::default();
|
||||
let mut edges: FxHashMap<_, Vec<_>> =
|
||||
FxHashMap::with_capacity_and_hasher(lock.by_id.len(), FxBuildHasher);
|
||||
|
||||
for distribution in &lock.distributions {
|
||||
for dependency in &distribution.dependencies {
|
||||
let parent = if invert {
|
||||
|
@ -2670,11 +2674,47 @@ impl<'env> TreeDisplay<'env> {
|
|||
} else {
|
||||
&dependency.distribution_id
|
||||
};
|
||||
|
||||
// Mark the dependency as a non-root node.
|
||||
non_roots.insert(child);
|
||||
|
||||
edges.entry(parent).or_default().push(child);
|
||||
}
|
||||
|
||||
for dependency in distribution.dev_dependencies.values().flatten() {
|
||||
let child = if invert {
|
||||
&distribution.id
|
||||
} else {
|
||||
&dependency.distribution_id
|
||||
};
|
||||
|
||||
// Mark the dependency as a non-root node.
|
||||
non_roots.insert(child);
|
||||
}
|
||||
|
||||
for dependency in distribution.optional_dependencies.values().flatten() {
|
||||
let child = if invert {
|
||||
&distribution.id
|
||||
} else {
|
||||
&dependency.distribution_id
|
||||
};
|
||||
|
||||
// Mark the dependency as a non-root node.
|
||||
non_roots.insert(child);
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the root nodes.
|
||||
let roots = lock
|
||||
.distributions
|
||||
.iter()
|
||||
.map(|dist| &dist.id)
|
||||
.filter(|id| !non_roots.contains(id))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Self {
|
||||
lock,
|
||||
roots,
|
||||
edges,
|
||||
depth,
|
||||
prune,
|
||||
|
@ -2774,14 +2814,9 @@ impl<'env> TreeDisplay<'env> {
|
|||
let mut lines: Vec<String> = Vec::new();
|
||||
|
||||
if self.package.is_empty() {
|
||||
// Identify all the root nodes by identifying all the distribution IDs that appear as
|
||||
// dependencies.
|
||||
let children: FxHashSet<_> = self.edges.values().flatten().collect();
|
||||
for id in self.lock.by_id.keys() {
|
||||
if !children.contains(&id) {
|
||||
path.clear();
|
||||
lines.extend(self.visit(id, &mut visited, &mut path));
|
||||
}
|
||||
for id in &self.roots {
|
||||
path.clear();
|
||||
lines.extend(self.visit(id, &mut visited, &mut path));
|
||||
}
|
||||
} else {
|
||||
// Index all the IDs by package.
|
||||
|
|
|
@ -347,3 +347,42 @@ fn repeated_version() -> Result<()> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dev_dependencies() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
|
||||
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||
pyproject_toml.write_str(
|
||||
r#"
|
||||
[project]
|
||||
name = "project"
|
||||
version = "0.1.0"
|
||||
# ...
|
||||
requires-python = ">=3.12"
|
||||
dependencies = ["iniconfig"]
|
||||
[tool.uv]
|
||||
dev-dependencies = ["anyio"]
|
||||
"#,
|
||||
)?;
|
||||
|
||||
// Dev dependencies should be omitted.
|
||||
uv_snapshot!(context.filters(), context.tree(), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
project v0.1.0
|
||||
└── iniconfig v2.0.0
|
||||
|
||||
----- stderr -----
|
||||
warning: `uv tree` is experimental and may change without warning
|
||||
Resolved 5 packages in [TIME]
|
||||
"###
|
||||
);
|
||||
|
||||
// `uv tree` should update the lockfile
|
||||
let lock = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?;
|
||||
assert!(!lock.is_empty());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue