Skip to content

Commit

Permalink
Report yanks for cached and resolved packages
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed May 22, 2024
1 parent 1fc71ea commit ff2c64c
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 38 deletions.
13 changes: 13 additions & 0 deletions crates/distribution-types/src/resolved.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::fmt::{Display, Formatter};

use pep508_rs::PackageName;
use pypi_types::Yanked;

use crate::{
BuiltDist, Dist, DistributionId, DistributionMetadata, Identifier, IndexUrl, InstalledDist,
Expand Down Expand Up @@ -51,6 +52,18 @@ impl ResolvedDist {
Self::Installed(_) => None,
}
}

/// Returns the [`Yanked`] status of the distribution, if available.
pub fn yanked(&self) -> Option<&Yanked> {
match self {
Self::Installable(dist) => match dist {
Dist::Source(SourceDist::Registry(sdist)) => sdist.file.yanked.as_ref(),
Dist::Built(BuiltDist::Registry(wheel)) => wheel.best_wheel().file.yanked.as_ref(),
_ => None,
},
Self::Installed(_) => None,
}
}
}

impl ResolvedDistRef<'_> {
Expand Down
41 changes: 40 additions & 1 deletion crates/uv-resolver/src/resolution/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use distribution_types::{
};
use pep440_rs::{Version, VersionSpecifier};
use pep508_rs::MarkerEnvironment;
use pypi_types::Yanked;
use uv_normalize::{ExtraName, PackageName};

use crate::dependency_provider::UvDependencyProvider;
Expand Down Expand Up @@ -56,6 +57,30 @@ impl ResolutionGraph {
let mut diagnostics = Vec::new();
for (package, version) in selection {
match &**package {
PubGrubPackageInner::Package {
name,
extra: None,
marker: None,
url: None,
} => {
let dist = pins
.get(name, version)
.expect("Every package should be pinned")
.clone();

match dist.yanked() {
None | Some(Yanked::Bool(false)) => {}
Some(Yanked::Bool(true)) => {
diagnostics.push(Diagnostic::YankedVersion { reason: None, dist });
}
Some(Yanked::Reason(reason)) => {
diagnostics.push(Diagnostic::YankedVersion {
reason: Some(reason.clone()),
dist,
});
}
}
}
PubGrubPackageInner::Package {
name,
extra: Some(extra),
Expand Down Expand Up @@ -580,12 +605,18 @@ impl From<ResolutionGraph> for distribution_types::Resolution {
#[derive(Debug)]
pub enum Diagnostic {
MissingExtra {
/// The distribution that was requested with an non-existent extra. For example,
/// The distribution that was requested with a non-existent extra. For example,
/// `black==23.10.0`.
dist: ResolvedDist,
/// The extra that was requested. For example, `colorama` in `black[colorama]`.
extra: ExtraName,
},
YankedVersion {
/// The package that was requested with a yanked version. For example, `black==23.10.0`.
dist: ResolvedDist,
/// The reason that the version was yanked, if any.
reason: Option<String>,
},
}

impl Diagnostic {
Expand All @@ -595,13 +626,21 @@ impl Diagnostic {
Self::MissingExtra { dist, extra } => {
format!("The package `{dist}` does not have an extra named `{extra}`.")
}
Self::YankedVersion { dist, reason } => {
if let Some(reason) = reason {
format!("`{dist}` is yanked (reason: \"{reason}\").")
} else {
format!("`{dist}` is yanked.")
}
}
}
}

/// Returns `true` if the [`PackageName`] is involved in this diagnostic.
pub fn includes(&self, name: &PackageName) -> bool {
match self {
Self::MissingExtra { dist, .. } => name == dist.name(),
Self::YankedVersion { dist, .. } => name == dist.name(),
}
}
}
38 changes: 1 addition & 37 deletions crates/uv/src/commands/pip/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use owo_colors::OwoColorize;
use tracing::debug;

use distribution_types::{
CachedDist, Dist, InstalledDist, Requirement, UnresolvedRequirementSpecification,
CachedDist, InstalledDist, Requirement, UnresolvedRequirementSpecification,
};
use distribution_types::{
DistributionMetadata, IndexLocations, InstalledMetadata, InstalledVersion, LocalDist, Name,
Expand All @@ -19,7 +19,6 @@ use install_wheel_rs::linker::LinkMode;
use pep440_rs::{VersionSpecifier, VersionSpecifiers};
use pep508_rs::{MarkerEnvironment, VerbatimUrl};
use platform_tags::Tags;
use pypi_types::Yanked;
use uv_cache::Cache;
use uv_client::{BaseClientBuilder, RegistryClient};
use uv_configuration::{
Expand Down Expand Up @@ -523,8 +522,6 @@ pub(crate) async fn install(

report_modifications(wheels, reinstalls, extraneous, printer)?;

report_yanks(&remote, printer)?;

Ok(())
}

Expand Down Expand Up @@ -666,8 +663,6 @@ fn report_dry_run(
}
}

report_yanks(&remote, printer)?;

Ok(())
}

Expand Down Expand Up @@ -721,37 +716,6 @@ pub(crate) fn report_modifications(
Ok(())
}

/// Report on any yanked distributions in the resolution.
pub(crate) fn report_yanks(remote: &[Dist], printer: Printer) -> Result<(), Error> {
// TODO(konstin): Also check the cache whether any cached or installed dist is already known to
// have been yanked, we currently don't show this message on the second run anymore
for dist in remote {
let Some(file) = dist.file() else {
continue;
};
match &file.yanked {
None | Some(Yanked::Bool(false)) => {}
Some(Yanked::Bool(true)) => {
writeln!(
printer.stderr(),
"{}{} {dist} is yanked.",
"warning".yellow().bold(),
":".bold(),
)?;
}
Some(Yanked::Reason(reason)) => {
writeln!(
printer.stderr(),
"{}{} {dist} is yanked (reason: \"{reason}\").",
"warning".yellow().bold(),
":".bold(),
)?;
}
}
}
Ok(())
}

/// Report any diagnostics on installed distributions in the Python environment.
pub(crate) fn report_diagnostics(
resolution: &Resolution,
Expand Down
1 change: 1 addition & 0 deletions crates/uv/tests/pip_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2805,6 +2805,7 @@ fn compile_yanked_version_direct() -> Result<()> {
----- stderr -----
Resolved 1 package in [TIME]
warning: `attrs==21.1.0` is yanked (reason: "Installable but not importable on Python 3.4.").
"###
);

Expand Down

0 comments on commit ff2c64c

Please sign in to comment.