mirror of https://github.com/astral-sh/uv
Fix `uv tree --invert` for platform dependencies (#7808)
## Summary
`click` has one dependency of `colorama` only on Windows, `uv tree
--invert` should not include `colorama` on non-Windows platforms, but
currently:
```console
$ uv init
$ uv add click
$ uv tree --invert --python-platform macos
colorama v0.4.6
```
it should:
```console
$ uv tree --invert --python-platform macos
click v8.1.7
└── project v0.1.0
```
This commit is contained in:
parent
7435ee3b24
commit
da9e85cc6a
|
|
@ -27,7 +27,7 @@ pub struct TreeDisplay<'env> {
|
|||
/// Prune the given packages from the display of the dependency tree.
|
||||
prune: Vec<PackageName>,
|
||||
/// Display only the specified packages.
|
||||
package: Vec<PackageName>,
|
||||
packages: Vec<PackageName>,
|
||||
/// Whether to de-duplicate the displayed dependencies.
|
||||
no_dedupe: bool,
|
||||
}
|
||||
|
|
@ -39,7 +39,7 @@ impl<'env> TreeDisplay<'env> {
|
|||
markers: Option<&'env ResolverMarkerEnvironment>,
|
||||
depth: usize,
|
||||
prune: Vec<PackageName>,
|
||||
package: Vec<PackageName>,
|
||||
packages: Vec<PackageName>,
|
||||
no_dedupe: bool,
|
||||
invert: bool,
|
||||
) -> Self {
|
||||
|
|
@ -51,16 +51,27 @@ impl<'env> TreeDisplay<'env> {
|
|||
let mut optional_dependencies: FxHashMap<_, FxHashMap<_, Vec<_>>> = FxHashMap::default();
|
||||
let mut dev_dependencies: FxHashMap<_, FxHashMap<_, Vec<_>>> = FxHashMap::default();
|
||||
|
||||
for packages in &lock.packages {
|
||||
for dependency in &packages.dependencies {
|
||||
for package in &lock.packages {
|
||||
for dependency in &package.dependencies {
|
||||
// Skip dependencies that don't apply to the current environment.
|
||||
if let Some(environment_markers) = markers {
|
||||
if !dependency
|
||||
.complexified_marker
|
||||
.evaluate(environment_markers, &[])
|
||||
{
|
||||
non_roots.insert(dependency.package_id.clone());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let parent = if invert {
|
||||
&dependency.package_id
|
||||
} else {
|
||||
&packages.id
|
||||
&package.id
|
||||
};
|
||||
let child = if invert {
|
||||
Cow::Owned(Dependency {
|
||||
package_id: packages.id.clone(),
|
||||
package_id: package.id.clone(),
|
||||
extra: dependency.extra.clone(),
|
||||
simplified_marker: dependency.simplified_marker.clone(),
|
||||
complexified_marker: dependency.complexified_marker.clone(),
|
||||
|
|
@ -71,29 +82,30 @@ impl<'env> TreeDisplay<'env> {
|
|||
|
||||
non_roots.insert(child.package_id.clone());
|
||||
|
||||
// Skip dependencies that don't apply to the current environment.
|
||||
if let Some(environment_markers) = markers {
|
||||
if !dependency
|
||||
.complexified_marker
|
||||
.evaluate(environment_markers, &[])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
dependencies.entry(parent).or_default().push(child);
|
||||
}
|
||||
|
||||
for (extra, dependencies) in &packages.optional_dependencies {
|
||||
for (extra, dependencies) in &package.optional_dependencies {
|
||||
for dependency in dependencies {
|
||||
// Skip dependencies that don't apply to the current environment.
|
||||
if let Some(environment_markers) = markers {
|
||||
if !dependency
|
||||
.complexified_marker
|
||||
.evaluate(environment_markers, &[])
|
||||
{
|
||||
non_roots.insert(dependency.package_id.clone());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let parent = if invert {
|
||||
&dependency.package_id
|
||||
} else {
|
||||
&packages.id
|
||||
&package.id
|
||||
};
|
||||
let child = if invert {
|
||||
Cow::Owned(Dependency {
|
||||
package_id: packages.id.clone(),
|
||||
package_id: package.id.clone(),
|
||||
extra: dependency.extra.clone(),
|
||||
simplified_marker: dependency.simplified_marker.clone(),
|
||||
complexified_marker: dependency.complexified_marker.clone(),
|
||||
|
|
@ -104,16 +116,6 @@ impl<'env> TreeDisplay<'env> {
|
|||
|
||||
non_roots.insert(child.package_id.clone());
|
||||
|
||||
// Skip dependencies that don't apply to the current environment.
|
||||
if let Some(environment_markers) = markers {
|
||||
if !dependency
|
||||
.complexified_marker
|
||||
.evaluate(environment_markers, &[])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
optional_dependencies
|
||||
.entry(parent)
|
||||
.or_default()
|
||||
|
|
@ -123,16 +125,27 @@ impl<'env> TreeDisplay<'env> {
|
|||
}
|
||||
}
|
||||
|
||||
for (group, dependencies) in &packages.dev_dependencies {
|
||||
for (group, dependencies) in &package.dev_dependencies {
|
||||
for dependency in dependencies {
|
||||
// Skip dependencies that don't apply to the current environment.
|
||||
if let Some(environment_markers) = markers {
|
||||
if !dependency
|
||||
.complexified_marker
|
||||
.evaluate(environment_markers, &[])
|
||||
{
|
||||
non_roots.insert(dependency.package_id.clone());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let parent = if invert {
|
||||
&dependency.package_id
|
||||
} else {
|
||||
&packages.id
|
||||
&package.id
|
||||
};
|
||||
let child = if invert {
|
||||
Cow::Owned(Dependency {
|
||||
package_id: packages.id.clone(),
|
||||
package_id: package.id.clone(),
|
||||
extra: dependency.extra.clone(),
|
||||
simplified_marker: dependency.simplified_marker.clone(),
|
||||
complexified_marker: dependency.complexified_marker.clone(),
|
||||
|
|
@ -143,16 +156,6 @@ impl<'env> TreeDisplay<'env> {
|
|||
|
||||
non_roots.insert(child.package_id.clone());
|
||||
|
||||
// Skip dependencies that don't apply to the current environment.
|
||||
if let Some(environment_markers) = markers {
|
||||
if !dependency
|
||||
.complexified_marker
|
||||
.evaluate(environment_markers, &[])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
dev_dependencies
|
||||
.entry(parent)
|
||||
.or_default()
|
||||
|
|
@ -178,7 +181,7 @@ impl<'env> TreeDisplay<'env> {
|
|||
dev_dependencies,
|
||||
depth,
|
||||
prune,
|
||||
package,
|
||||
packages,
|
||||
no_dedupe,
|
||||
}
|
||||
}
|
||||
|
|
@ -309,7 +312,7 @@ impl<'env> TreeDisplay<'env> {
|
|||
let mut path = Vec::new();
|
||||
let mut lines = Vec::new();
|
||||
|
||||
if self.package.is_empty() {
|
||||
if self.packages.is_empty() {
|
||||
for id in &self.roots {
|
||||
path.clear();
|
||||
lines.extend(self.visit(Node::Root(id), &mut visited, &mut path));
|
||||
|
|
@ -317,7 +320,7 @@ impl<'env> TreeDisplay<'env> {
|
|||
} else {
|
||||
let by_package: FxHashMap<_, _> = self.roots.iter().map(|id| (&id.name, id)).collect();
|
||||
let mut first = true;
|
||||
for package in &self.package {
|
||||
for package in &self.packages {
|
||||
if std::mem::take(&mut first) {
|
||||
lines.push(String::new());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -258,6 +258,52 @@ fn platform_dependencies() -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn platform_dependencies_inverted() -> 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 = [
|
||||
"click"
|
||||
]
|
||||
"#,
|
||||
)?;
|
||||
|
||||
// When `--universal` is _not_ provided, `colorama` should _not_ be included.
|
||||
#[cfg(not(windows))]
|
||||
uv_snapshot!(context.filters(), context.tree().arg("--invert"), @r#"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
click v8.1.7
|
||||
└── project v0.1.0
|
||||
|
||||
----- stderr -----
|
||||
Resolved 3 packages in [TIME]
|
||||
"#);
|
||||
|
||||
// Unless `--python-platform` is set to `windows`, in which case it should be included.
|
||||
uv_snapshot!(context.filters(), context.tree().arg("--invert").arg("--python-platform").arg("windows"), @r#"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
colorama v0.4.6
|
||||
└── click v8.1.7
|
||||
└── project v0.1.0
|
||||
|
||||
----- stderr -----
|
||||
Resolved 3 packages in [TIME]
|
||||
"#);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn repeated_dependencies() -> Result<()> {
|
||||
let context = TestContext::new("3.12");
|
||||
|
|
|
|||
Loading…
Reference in New Issue