Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 17 additions & 9 deletions crates/uv-installer/src/site_packages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ use fs_err as fs;
use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet};

use uv_distribution_types::{
ConfigSettings, Diagnostic, ExtraBuildRequires, ExtraBuildVariables, InstalledDist,
InstalledDistKind, Name, NameRequirementSpecification, PackageConfigSettings, Requirement,
UnresolvedRequirement, UnresolvedRequirementSpecification,
ConfigSettings, DependencyMetadata, Diagnostic, ExtraBuildRequires, ExtraBuildVariables,
InstalledDist, InstalledDistKind, Name, NameRequirementSpecification, PackageConfigSettings,
Requirement, UnresolvedRequirement, UnresolvedRequirementSpecification,
};
use uv_fs::Simplified;
use uv_normalize::PackageName;
Expand Down Expand Up @@ -196,6 +196,7 @@ impl SitePackages {
&self,
markers: &ResolverMarkerEnvironment,
tags: &Tags,
dependency_metadata: &DependencyMetadata,
) -> Result<Vec<SitePackagesDiagnostic>> {
let mut diagnostics = Vec::new();

Expand Down Expand Up @@ -225,12 +226,19 @@ impl SitePackages {
};

// Determine the dependencies for the given package.
let Ok(metadata) = distribution.read_metadata() else {
diagnostics.push(SitePackagesDiagnostic::MetadataUnavailable {
package: package.clone(),
path: distribution.install_path().to_owned(),
});
continue;
let metadata = if let Some(metadata) =
dependency_metadata.get(package, Some(distribution.version()))
{
Cow::Owned(metadata)
} else {
let Ok(metadata) = distribution.read_metadata() else {
diagnostics.push(SitePackagesDiagnostic::MetadataUnavailable {
package: package.clone(),
path: distribution.install_path().to_owned(),
});
continue;
};
Cow::Borrowed(metadata)
};

// Verify that the package is compatible with the current Python version.
Expand Down
5 changes: 3 additions & 2 deletions crates/uv/src/commands/pip/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use owo_colors::OwoColorize;

use uv_cache::Cache;
use uv_configuration::TargetTriple;
use uv_distribution_types::{Diagnostic, InstalledDist};
use uv_distribution_types::{DependencyMetadata, Diagnostic, InstalledDist};
use uv_installer::{SitePackages, SitePackagesDiagnostic};
use uv_preview::Preview;
use uv_python::{
Expand All @@ -24,6 +24,7 @@ pub(crate) fn pip_check(
system: bool,
python_version: Option<&PythonVersion>,
python_platform: Option<&TargetTriple>,
dependency_metadata: &DependencyMetadata,
cache: &Cache,
printer: Printer,
preview: Preview,
Expand Down Expand Up @@ -63,7 +64,7 @@ pub(crate) fn pip_check(

// Run the diagnostics.
let diagnostics: Vec<SitePackagesDiagnostic> = site_packages
.diagnostics(&markers, &tags)?
.diagnostics(&markers, &tags, dependency_metadata)?
.into_iter()
.collect();

Expand Down
5 changes: 3 additions & 2 deletions crates/uv/src/commands/pip/freeze.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use rustc_hash::FxHashSet;
use tracing::debug;

use uv_cache::Cache;
use uv_distribution_types::{Diagnostic, InstalledDistKind, Name};
use uv_distribution_types::{DependencyMetadata, Diagnostic, InstalledDistKind, Name};
use uv_fs::Simplified;
use uv_installer::SitePackages;
use uv_normalize::PackageName;
Expand All @@ -25,6 +25,7 @@ pub(crate) fn pip_freeze(
exclude_editable: bool,
exclude: &FxHashSet<PackageName>,
strict: bool,
dependency_metadata: &DependencyMetadata,
python: Option<&str>,
system: bool,
target: Option<Target>,
Expand Down Expand Up @@ -124,7 +125,7 @@ pub(crate) fn pip_freeze(
let tags = environment.interpreter().tags()?;

for entry in site_packages {
for diagnostic in entry.diagnostics(&markers, tags)? {
for diagnostic in entry.diagnostics(&markers, tags, dependency_metadata)? {
writeln!(
printer.stderr(),
"{}{} {}",
Expand Down
9 changes: 8 additions & 1 deletion crates/uv/src/commands/pip/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,14 @@ pub(crate) async fn pip_install(

// Notify the user of any environment diagnostics.
if strict && !dry_run.enabled() {
operations::diagnose_environment(&resolution, &environment, &marker_env, &tags, printer)?;
operations::diagnose_environment(
&resolution,
&environment,
&marker_env,
&tags,
&dependency_metadata,
printer,
)?;
}

Ok(ExitStatus::Success)
Expand Down
6 changes: 4 additions & 2 deletions crates/uv/src/commands/pip/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ use uv_client::{BaseClientBuilder, RegistryClientBuilder};
use uv_configuration::{Concurrency, IndexStrategy, KeyringProviderType};
use uv_distribution_filename::DistFilename;
use uv_distribution_types::{
Diagnostic, IndexCapabilities, IndexLocations, InstalledDist, Name, RequiresPython,
DependencyMetadata, Diagnostic, IndexCapabilities, IndexLocations, InstalledDist, Name,
RequiresPython,
};
use uv_fs::Simplified;
use uv_installer::SitePackages;
Expand Down Expand Up @@ -48,6 +49,7 @@ pub(crate) async fn pip_list(
concurrency: Concurrency,
strict: bool,
exclude_newer: ExcludeNewer,
dependency_metadata: &DependencyMetadata,
python: Option<&str>,
system: bool,
target: Option<Target>,
Expand Down Expand Up @@ -294,7 +296,7 @@ pub(crate) async fn pip_list(
let markers = environment.interpreter().resolver_marker_environment();
let tags = environment.interpreter().tags()?;

for diagnostic in site_packages.diagnostics(&markers, tags)? {
for diagnostic in site_packages.diagnostics(&markers, tags, dependency_metadata)? {
writeln!(
printer.stderr(),
"{}{} {}",
Expand Down
5 changes: 3 additions & 2 deletions crates/uv/src/commands/pip/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use uv_configuration::{
use uv_dispatch::BuildDispatch;
use uv_distribution::{DistributionDatabase, SourcedDependencyGroups};
use uv_distribution_types::{
CachedDist, Diagnostic, Dist, InstalledDist, InstalledVersion, LocalDist,
CachedDist, DependencyMetadata, Diagnostic, Dist, InstalledDist, InstalledVersion, LocalDist,
NameRequirementSpecification, Requirement, ResolutionDiagnostic, UnresolvedRequirement,
UnresolvedRequirementSpecification, VersionOrUrlRef,
};
Expand Down Expand Up @@ -1067,10 +1067,11 @@ pub(crate) fn diagnose_environment(
venv: &PythonEnvironment,
markers: &ResolverMarkerEnvironment,
tags: &Tags,
dependency_metadata: &DependencyMetadata,
printer: Printer,
) -> Result<(), Error> {
let site_packages = SitePackages::from_environment(venv)?;
for diagnostic in site_packages.diagnostics(markers, tags)? {
for diagnostic in site_packages.diagnostics(markers, tags, dependency_metadata)? {
// Only surface diagnostics that are "relevant" to the current resolution.
if resolution
.distributions()
Expand Down
5 changes: 3 additions & 2 deletions crates/uv/src/commands/pip/show.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use rustc_hash::FxHashMap;
use tracing::debug;

use uv_cache::Cache;
use uv_distribution_types::{Diagnostic, Name};
use uv_distribution_types::{DependencyMetadata, Diagnostic, Name};
use uv_fs::Simplified;
use uv_install_wheel::read_record_file;
use uv_installer::SitePackages;
Expand All @@ -26,6 +26,7 @@ use crate::printer::Printer;
pub(crate) fn pip_show(
mut packages: Vec<PackageName>,
strict: bool,
dependency_metadata: &DependencyMetadata,
python: Option<&str>,
system: bool,
target: Option<Target>,
Expand Down Expand Up @@ -227,7 +228,7 @@ pub(crate) fn pip_show(

// Validate that the environment is consistent.
if strict {
for diagnostic in site_packages.diagnostics(&markers, tags)? {
for diagnostic in site_packages.diagnostics(&markers, tags, dependency_metadata)? {
writeln!(
printer.stderr(),
"{}{} {}",
Expand Down
9 changes: 8 additions & 1 deletion crates/uv/src/commands/pip/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,14 @@ pub(crate) async fn pip_sync(

// Notify the user of any environment diagnostics.
if strict && !dry_run.enabled() {
operations::diagnose_environment(&resolution, &environment, &marker_env, &tags, printer)?;
operations::diagnose_environment(
&resolution,
&environment,
&marker_env,
&tags,
&dependency_metadata,
printer,
)?;
}

Ok(ExitStatus::Success)
Expand Down
7 changes: 5 additions & 2 deletions crates/uv/src/commands/pip/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ use uv_cache::{Cache, Refresh};
use uv_cache_info::Timestamp;
use uv_client::{BaseClientBuilder, RegistryClientBuilder};
use uv_configuration::{Concurrency, IndexStrategy, KeyringProviderType};
use uv_distribution_types::{Diagnostic, IndexCapabilities, IndexLocations, Name, RequiresPython};
use uv_distribution_types::{
DependencyMetadata, Diagnostic, IndexCapabilities, IndexLocations, Name, RequiresPython,
};
use uv_installer::SitePackages;
use uv_normalize::PackageName;
use uv_pep440::{Operator, Version, VersionSpecifier, VersionSpecifiers};
Expand Down Expand Up @@ -48,6 +50,7 @@ pub(crate) async fn pip_tree(
concurrency: Concurrency,
strict: bool,
exclude_newer: ExcludeNewer,
dependency_metadata: &DependencyMetadata,
python: Option<&str>,
system: bool,
cache: &Cache,
Expand Down Expand Up @@ -175,7 +178,7 @@ pub(crate) async fn pip_tree(

// Validate that the environment is consistent.
if strict {
for diagnostic in site_packages.diagnostics(&markers, tags)? {
for diagnostic in site_packages.diagnostics(&markers, tags, dependency_metadata)? {
writeln!(
printer.stderr(),
"{}{} {}",
Expand Down
5 changes: 5 additions & 0 deletions crates/uv/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1029,6 +1029,7 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
args.exclude_editable,
&args.exclude,
args.settings.strict,
&args.settings.dependency_metadata,
args.settings.python.as_deref(),
args.settings.system,
args.settings.target,
Expand Down Expand Up @@ -1064,6 +1065,7 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
globals.concurrency,
args.settings.strict,
args.settings.exclude_newer,
&args.settings.dependency_metadata,
args.settings.python.as_deref(),
args.settings.system,
args.settings.target,
Expand All @@ -1087,6 +1089,7 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
commands::pip_show(
args.package,
args.settings.strict,
&args.settings.dependency_metadata,
args.settings.python.as_deref(),
args.settings.system,
args.settings.target,
Expand Down Expand Up @@ -1122,6 +1125,7 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
globals.concurrency,
args.settings.strict,
args.settings.exclude_newer,
&args.settings.dependency_metadata,
args.settings.python.as_deref(),
args.settings.system,
&cache,
Expand All @@ -1145,6 +1149,7 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
args.settings.system,
args.settings.python_version.as_ref(),
args.settings.python_platform.as_ref(),
&args.settings.dependency_metadata,
&cache,
printer,
globals.preview,
Expand Down
77 changes: 77 additions & 0 deletions crates/uv/tests/it/pip_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,3 +219,80 @@ fn check_python_version() {
"
);
}

#[test]
fn check_dependency_metadata_from_config_file() -> Result<()> {
let context = uv_test::test_context!("3.12");

let requirements_txt = context.temp_dir.child("requirements.txt");
requirements_txt.write_str("requests==2.31.0")?;

uv_snapshot!(context
.pip_install()
.arg("-r")
.arg("requirements.txt")
.arg("--strict"), @"
success: true
exit_code: 0
----- stdout -----

----- stderr -----
Resolved 5 packages in [TIME]
Prepared 5 packages in [TIME]
Installed 5 packages in [TIME]
+ certifi==2024.2.2
+ charset-normalizer==3.3.2
+ idna==3.6
+ requests==2.31.0
+ urllib3==2.2.1
"
);

let requirements_txt_idna = context.temp_dir.child("requirements_idna.txt");
requirements_txt_idna.write_str("idna==2.4")?;

uv_snapshot!(context
.pip_install()
.arg("-r")
.arg("requirements_idna.txt")
.arg("--strict"), @"
success: true
exit_code: 0
----- stdout -----

----- stderr -----
Resolved 1 package in [TIME]
Prepared 1 package in [TIME]
Uninstalled 1 package in [TIME]
Installed 1 package in [TIME]
- idna==3.6
+ idna==2.4
warning: The package `requests` requires `idna>=2.5,<4`, but `2.4` is installed
"
);

let uv_toml = context.temp_dir.child("uv.toml");
uv_toml.write_str(
r#"
dependency-metadata = [
{ name = "requests", version = "2.31.0", requires-dist = ["certifi>=2017.4.17", "charset-normalizer>=2,<4", "idna>=2.4,<4", "urllib3>=1.21.1,<3"] },
]
"#,
)?;

uv_snapshot!(context
.pip_check()
.arg("--config-file")
.arg("uv.toml"), @"
success: true
exit_code: 0
----- stdout -----

----- stderr -----
Checked 5 packages in [TIME]
All installed packages are compatible
"
);

Ok(())
}
Loading