Skip to content

Commit

Permalink
Merge branch 'main' into ignore-quiet-flag-for-pip-list-and-tree
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed Oct 20, 2024
2 parents 3b41ab0 + 7e2822d commit e323a70
Show file tree
Hide file tree
Showing 8 changed files with 237 additions and 48 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,10 @@ jobs:

- name: "Cargo test"
working-directory: ${{ env.UV_WORKSPACE }}
env:
# Avoid permission errors during concurrent tests
# See https://github.com/astral-sh/uv/issues/6940
UV_LINK_MODE: copy
run: |
cargo nextest run --no-default-features --features python,pypi --workspace --status-level skip --failure-output immediate-final --no-fail-fast -j 20 --final-status-level slow
Expand Down
33 changes: 29 additions & 4 deletions crates/uv-resolver/src/lock/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,21 @@ impl Lock {
let mut packages = BTreeMap::new();
let requires_python = graph.requires_python.clone();

// Determine the set of packages included at multiple versions.
let mut seen = FxHashSet::default();
let mut duplicates = FxHashSet::default();
for node_index in graph.petgraph.node_indices() {
let ResolutionGraphNode::Dist(dist) = &graph.petgraph[node_index] else {
continue;
};
if !dist.is_base() {
continue;
}
if !seen.insert(dist.name()) {
duplicates.insert(dist.name());
}
}

// Lock all base packages.
for node_index in graph.petgraph.node_indices() {
let ResolutionGraphNode::Dist(dist) = &graph.petgraph[node_index] else {
Expand All @@ -116,10 +131,20 @@ impl Lock {
if !dist.is_base() {
continue;
}
let fork_markers = graph
.fork_markers(dist.name(), &dist.version, dist.dist.version_or_url().url())
.cloned()
.unwrap_or_default();

// If there are multiple distributions for the same package, include the markers of all
// forks that included the current distribution.
let fork_markers = if duplicates.contains(dist.name()) {
graph
.fork_markers
.iter()
.filter(|fork_markers| !fork_markers.is_disjoint(&dist.marker))
.cloned()
.collect()
} else {
vec![]
};

let mut package = Package::from_annotated_dist(dist, fork_markers, root)?;
Self::remove_unreachable_wheels(graph, &requires_python, node_index, &mut package);

Expand Down
26 changes: 2 additions & 24 deletions crates/uv-resolver/src/resolution/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use uv_distribution_types::{
use uv_git::GitResolver;
use uv_normalize::{ExtraName, GroupName, PackageName};
use uv_pep440::{Version, VersionSpecifier};
use uv_pep508::{MarkerEnvironment, MarkerTree, MarkerTreeKind, VerbatimUrl};
use uv_pep508::{MarkerEnvironment, MarkerTree, MarkerTreeKind};
use uv_pypi_types::{HashDigest, ParsedUrlError, Requirement, VerbatimParsedUrl, Yanked};

use crate::graph_ops::marker_reachability;
Expand All @@ -31,7 +31,7 @@ use crate::{
ResolverMarkers, VersionsResponse,
};

pub(crate) type MarkersForDistribution = FxHashMap<(Version, Option<VerbatimUrl>), Vec<MarkerTree>>;
pub(crate) type MarkersForDistribution = Vec<MarkerTree>;

/// A complete resolution graph in which every node represents a pinned package and every edge
/// represents a dependency between two pinned packages.
Expand All @@ -54,9 +54,6 @@ pub struct ResolutionGraph {
pub(crate) overrides: Overrides,
/// The options that were used to build the graph.
pub(crate) options: Options,
/// If there are multiple options for a package, track which fork they belong to so we
/// can write that to the lockfile and later get the correct preference per fork back.
pub(crate) package_markers: FxHashMap<PackageName, MarkersForDistribution>,
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -131,8 +128,6 @@ impl ResolutionGraph {
package_markers
.entry(package.name.clone())
.or_default()
.entry((version.clone(), package.url.clone().map(|url| url.verbatim)))
.or_default()
.push(markers.clone());
}
}
Expand Down Expand Up @@ -239,7 +234,6 @@ impl ResolutionGraph {
let graph = Self {
petgraph,
requires_python,
package_markers,
diagnostics,
requirements: requirements.to_vec(),
constraints: constraints.clone(),
Expand Down Expand Up @@ -727,22 +721,6 @@ impl ResolutionGraph {
Ok(conjunction)
}

/// If there are multiple distributions for the same package name, return the markers of the
/// fork(s) that contained this distribution, otherwise return `None`.
pub fn fork_markers(
&self,
package_name: &PackageName,
version: &Version,
url: Option<&VerbatimUrl>,
) -> Option<&Vec<MarkerTree>> {
let package_markers = &self.package_markers.get(package_name)?;
if package_markers.len() == 1 {
None
} else {
Some(&package_markers[&(version.clone(), url.cloned())])
}
}

/// Returns a sequence of conflicting distribution errors from this
/// resolution.
///
Expand Down
15 changes: 5 additions & 10 deletions crates/uv/src/commands/pip/list.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::cmp::max;
use std::fmt::Write;

use anstream::println;
use anyhow::Result;
use itertools::Itertools;
use owo_colors::OwoColorize;
Expand All @@ -18,7 +19,7 @@ use uv_python::{EnvironmentPreference, PythonEnvironment};

use crate::commands::pip::operations::report_target_environment;
use crate::commands::ExitStatus;
use crate::printer::{Printer, Stdout};
use crate::printer::Printer;

/// Enumerate the installed packages in the current environment.
#[allow(clippy::fn_params_excessive_bools)]
Expand Down Expand Up @@ -52,12 +53,11 @@ pub(crate) fn pip_list(
.sorted_unstable_by(|a, b| a.name().cmp(b.name()).then(a.version().cmp(b.version())))
.collect_vec();

// We force output to stdout specifically for `pip list` command (#8379)
match format {
ListFormat::Json => {
let rows = results.iter().copied().map(Entry::from).collect_vec();
let output = serde_json::to_string(&rows)?;
writeln!(Stdout::Enabled, "{output}")?;
println!("{output}");
}
ListFormat::Columns if results.is_empty() => {}
ListFormat::Columns => {
Expand Down Expand Up @@ -98,18 +98,13 @@ pub(crate) fn pip_list(
}

for elems in MultiZip(columns.iter().map(Column::fmt).collect_vec()) {
writeln!(Stdout::Enabled, "{}", elems.join(" ").trim_end())?;
println!("{}", elems.join(" ").trim_end());
}
}
ListFormat::Freeze if results.is_empty() => {}
ListFormat::Freeze => {
for dist in &results {
writeln!(
Stdout::Enabled,
"{}=={}",
dist.name().bold(),
dist.version()
)?;
println!("{}=={}", dist.name().bold(), dist.version());
}
}
}
Expand Down
10 changes: 5 additions & 5 deletions crates/uv/src/commands/project/tree.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use anyhow::Result;
use std::fmt::Write;
use std::path::Path;

use anstream::println;
use anyhow::Result;

use uv_cache::Cache;
use uv_client::Connectivity;
use uv_configuration::{Concurrency, DevMode, LowerBound, TargetTriple};
Expand All @@ -14,7 +15,7 @@ use crate::commands::pip::loggers::DefaultResolveLogger;
use crate::commands::pip::resolution_markers;
use crate::commands::project::ProjectInterpreter;
use crate::commands::{project, ExitStatus, SharedState};
use crate::printer::{Printer, Stdout};
use crate::printer::Printer;
use crate::settings::ResolverSettings;

/// Run a command.
Expand Down Expand Up @@ -100,8 +101,7 @@ pub(crate) async fn tree(
invert,
);

// Making an exclusion specifically for tree subcommand (#8379)
write!(Stdout::Enabled, "{tree}")?;
println!("{tree}");

Ok(ExitStatus::Success)
}
17 changes: 16 additions & 1 deletion crates/uv/tests/it/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,12 @@ impl TestContext {

let mut filters = Vec::new();

// Exclude `link-mode` on Windows since we set it in the remote test suite
if cfg!(windows) {
filters.push(("--link-mode <LINK_MODE> ".to_string(), String::new()));
filters.push(((r#"link-mode = "copy"\n"#).to_string(), String::new()));
}

filters.extend(
Self::path_patterns(&cache_dir)
.into_iter()
Expand Down Expand Up @@ -1112,6 +1118,7 @@ pub fn run_and_format<T: AsRef<str>>(
/// Execute the command and format its output status, stdout and stderr into a snapshot string.
///
/// This function is derived from `insta_cmd`s `spawn_with_info`.
#[allow(clippy::print_stderr)]
pub fn run_and_format_with_status<T: AsRef<str>>(
mut command: impl BorrowMut<Command>,
filters: impl AsRef<[(T, T)]>,
Expand Down Expand Up @@ -1141,13 +1148,21 @@ pub fn run_and_format_with_status<T: AsRef<str>>(
.output()
.unwrap_or_else(|err| panic!("Failed to spawn {program}: {err}"));

eprintln!("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Unfiltered output ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
eprintln!(
"----- stdout -----\n{}\n----- stderr -----\n{}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr),
);
eprintln!("────────────────────────────────────────────────────────────────────────────────\n");

let mut snapshot = apply_filters(
format!(
"success: {:?}\nexit_code: {}\n----- stdout -----\n{}\n----- stderr -----\n{}",
output.status.success(),
output.status.code().unwrap_or(!0),
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
String::from_utf8_lossy(&output.stderr),
),
filters,
);
Expand Down
6 changes: 3 additions & 3 deletions crates/uv/tests/it/edit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3383,7 +3383,7 @@ fn add_reject_multiple_git_ref_flags() {
let context = TestContext::new("3.12");

// --tag and --branch
uv_snapshot!(context
uv_snapshot!(context.filters(), context
.add()
.arg("foo")
.arg("--tag")
Expand All @@ -3404,7 +3404,7 @@ fn add_reject_multiple_git_ref_flags() {
);

// --tag and --rev
uv_snapshot!(context
uv_snapshot!(context.filters(), context
.add()
.arg("foo")
.arg("--tag")
Expand All @@ -3425,7 +3425,7 @@ fn add_reject_multiple_git_ref_flags() {
);

// --tag and --tag
uv_snapshot!(context
uv_snapshot!(context.filters(), context
.add()
.arg("foo")
.arg("--tag")
Expand Down
Loading

0 comments on commit e323a70

Please sign in to comment.