Skip to content

Commit

Permalink
Editable project location and Required-by for pip show (#2589)
Browse files Browse the repository at this point in the history
<!--
Thank you for contributing to uv! To help us out with reviewing, please
consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

<!-- What's the purpose of the change? What does it do, and why? -->

- Displays missing packages as single-line warnings.
- Adds support for `Editable project location` and `Required-by` fields
in `pip show`.

Part of #2526.

# Conflicts:
#	crates/uv-dispatch/src/lib.rs
#	crates/uv-resolver/src/resolver/mod.rs
#	crates/uv-resolver/tests/resolver.rs
#	crates/uv-traits/src/lib.rs
#	crates/uv/src/commands/pip_compile.rs

# Conflicts:
#	crates/uv/src/commands/pip_sync.rs
  • Loading branch information
zanieb committed Mar 27, 2024
1 parent 384355b commit a0adc73
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 11 deletions.
5 changes: 4 additions & 1 deletion crates/uv-dev/src/resolve_cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use pep508_rs::Requirement;
use uv_cache::{Cache, CacheArgs};
use uv_client::{FlatIndex, FlatIndexClient, RegistryClientBuilder};
use uv_dispatch::BuildDispatch;
use uv_installer::NoBinary;
use uv_installer::{NoBinary, SitePackages};
use uv_interpreter::PythonEnvironment;
use uv_resolver::{InMemoryIndex, Manifest, Options, Resolver};
use uv_types::{BuildIsolation, ConfigSettings, InFlight, NoBuild, SetupPyStrategy};
Expand Down Expand Up @@ -88,6 +88,8 @@ pub(crate) async fn resolve_cli(args: ResolveCliArgs) -> Result<()> {
&NoBinary::None,
);

let site_packages = SitePackages::from_executable(&venv)?;

// Copied from `BuildDispatch`
let tags = venv.interpreter().tags()?;
let resolver = Resolver::new(
Expand All @@ -100,6 +102,7 @@ pub(crate) async fn resolve_cli(args: ResolveCliArgs) -> Result<()> {
&flat_index,
&index,
&build_dispatch,
&site_packages,
)?;
let resolution_graph = resolver.resolve().await.with_context(|| {
format!(
Expand Down
3 changes: 2 additions & 1 deletion crates/uv-dispatch/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use uv_installer::{Downloader, Installer, NoBinary, Plan, Planner, Reinstall, Si
use uv_interpreter::{Interpreter, PythonEnvironment};
use uv_resolver::{InMemoryIndex, Manifest, Options, Resolver};
use uv_types::{
BuildContext, BuildIsolation, BuildKind, ConfigSettings, InFlight, NoBuild, SetupPyStrategy,
BuildContext, BuildIsolation, BuildKind, ConfigSettings, InFlight, NoBuild, EmptyInstalledPackages, SetupPyStrategy,
};

/// The main implementation of [`BuildContext`], used by the CLI, see [`BuildContext`]
Expand Down Expand Up @@ -145,6 +145,7 @@ impl<'a> BuildContext for BuildDispatch<'a> {
self.flat_index,
self.index,
self,
&EmptyInstalledPackages,
)?;
let graph = resolver.resolve().await.with_context(|| {
format!(
Expand Down
21 changes: 21 additions & 0 deletions crates/uv-installer/src/site_packages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use requirements_txt::EditableRequirement;
use uv_cache::{ArchiveTarget, ArchiveTimestamp};
use uv_interpreter::PythonEnvironment;
use uv_normalize::PackageName;
use uv_traits::InstalledPackagesProvider;

use crate::is_dynamic;

Expand Down Expand Up @@ -577,3 +578,23 @@ impl Diagnostic {
}
}
}

impl InstalledPackagesProvider for SitePackages<'_> {
fn iter(&self) -> impl Iterator<Item = &InstalledDist> {
self.iter()
}

fn get_packages(&self, name: &PackageName) -> Vec<&InstalledDist> {
self.get_packages(name)
}
}

impl InstalledPackagesProvider for &SitePackages<'_> {
fn iter(&self) -> impl Iterator<Item = &InstalledDist> {
(*self).iter()
}

fn get_packages(&self, name: &PackageName) -> Vec<&InstalledDist> {
(*self).get_packages(name)
}
}
27 changes: 23 additions & 4 deletions crates/uv-resolver/src/resolver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use uv_client::{FlatIndex, RegistryClient};
use uv_distribution::DistributionDatabase;
use uv_interpreter::Interpreter;
use uv_normalize::PackageName;
use uv_types::BuildContext;
use uv_types::{BuildContext, InstalledPackagesProvider};

use crate::candidate_selector::{CandidateDist, CandidateSelector};
use crate::constraints::Constraints;
Expand Down Expand Up @@ -89,7 +89,11 @@ enum ResolverVersion {
Unavailable(Version, UnavailableVersion),
}

pub struct Resolver<'a, Provider: ResolverProvider> {
pub struct Resolver<
'a,
Provider: ResolverProvider,
InstalledPackages: InstalledPackagesProvider + Send + Sync,
> {
project: Option<PackageName>,
requirements: Vec<Requirement>,
constraints: Constraints,
Expand All @@ -103,6 +107,7 @@ pub struct Resolver<'a, Provider: ResolverProvider> {
python_requirement: PythonRequirement,
selector: CandidateSelector,
index: &'a InMemoryIndex,
installed_packages: &'a InstalledPackages,
/// Incompatibilities for packages that are entirely unavailable
unavailable_packages: DashMap<PackageName, UnavailablePackage>,
/// The set of all registry-based packages visited during resolution.
Expand All @@ -111,7 +116,12 @@ pub struct Resolver<'a, Provider: ResolverProvider> {
provider: Provider,
}

impl<'a, Context: BuildContext + Send + Sync> Resolver<'a, DefaultResolverProvider<'a, Context>> {
impl<
'a,
Context: BuildContext + Send + Sync,
InstalledPackages: InstalledPackagesProvider + Send + Sync,
> Resolver<'a, DefaultResolverProvider<'a, Context>, InstalledPackages>
{
/// Initialize a new resolver using the default backend doing real requests.
///
/// Reads the flat index entries.
Expand All @@ -126,6 +136,7 @@ impl<'a, Context: BuildContext + Send + Sync> Resolver<'a, DefaultResolverProvid
flat_index: &'a FlatIndex,
index: &'a InMemoryIndex,
build_context: &'a Context,
installed_packages: &'a InstalledPackages,
) -> Result<Self, ResolveError> {
let provider = DefaultResolverProvider::new(
client,
Expand All @@ -145,11 +156,17 @@ impl<'a, Context: BuildContext + Send + Sync> Resolver<'a, DefaultResolverProvid
PythonRequirement::new(interpreter, markers),
index,
provider,
installed_packages,
)
}
}

impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
impl<
'a,
Provider: ResolverProvider,
InstalledPackages: InstalledPackagesProvider + Send + Sync,
> Resolver<'a, Provider, InstalledPackages>
{
/// Initialize a new resolver using a user provided backend.
pub fn new_custom_io(
manifest: Manifest,
Expand All @@ -158,6 +175,7 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
python_requirement: PythonRequirement,
index: &'a InMemoryIndex,
provider: Provider,
installed_packages: &'a InstalledPackages,
) -> Result<Self, ResolveError> {
Ok(Self {
index,
Expand All @@ -177,6 +195,7 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
python_requirement,
reporter: None,
provider,
installed_packages,
})
}

Expand Down
4 changes: 3 additions & 1 deletion crates/uv-resolver/tests/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use uv_resolver::{
Preference, ResolutionGraph, ResolutionMode, Resolver,
};
use uv_types::{
BuildContext, BuildIsolation, BuildKind, NoBinary, NoBuild, SetupPyStrategy, SourceBuildTrait,
BuildContext, BuildIsolation, BuildKind, NoBinary, EmptyInstalledPackages, NoBuild, SetupPyStrategy, SourceBuildTrait,
};

// Exclude any packages uploaded after this date.
Expand Down Expand Up @@ -124,6 +124,7 @@ async fn resolve(
find_default_python(&Cache::temp().unwrap()).expect("Expected a python to be installed");
let interpreter = Interpreter::artificial(real_interpreter.platform().clone(), markers.clone());
let build_context = DummyContext::new(Cache::temp()?, interpreter.clone());
let installed_packages = EmptyInstalledPackages;
let resolver = Resolver::new(
manifest,
options,
Expand All @@ -134,6 +135,7 @@ async fn resolve(
&flat_index,
&index,
&build_context,
&installed_packages,
)?;
Ok(resolver.resolve().await?)
}
Expand Down
22 changes: 22 additions & 0 deletions crates/uv-types/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,25 @@ pub trait SourceBuildTrait {
fn wheel<'a>(&'a self, wheel_dir: &'a Path)
-> impl Future<Output = Result<String>> + Send + 'a;
}

/// A wrapper for [`uv_installer::SitePackages`]
pub trait InstalledPackagesProvider {
fn iter(&self) -> impl Iterator<Item = &InstalledDist>;
fn get_packages(&self, name: &PackageName) -> Vec<&InstalledDist>;
}

/// An [`InstalledPackagesProvider`] with no packages in it.
pub struct EmptyInstalledPackages;

impl InstalledPackagesProvider for EmptyInstalledPackages {
fn get_packages(
&self,
_name: &pep508_rs::PackageName,
) -> Vec<&distribution_types::InstalledDist> {
Vec::new()
}

fn iter(&self) -> impl Iterator<Item = &distribution_types::InstalledDist> {
std::iter::empty()
}
}
3 changes: 2 additions & 1 deletion crates/uv/src/commands/pip_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use uv_resolver::{
AnnotationStyle, DependencyMode, DisplayResolutionGraph, InMemoryIndex, Manifest,
OptionsBuilder, PreReleaseMode, PythonRequirement, ResolutionMode, Resolver,
};
use uv_types::{BuildIsolation, ConfigSettings, InFlight, NoBuild, SetupPyStrategy, Upgrade};
use uv_types::{BuildIsolation, ConfigSettings, InFlight, EmptyInstalledPackages, NoBuild, SetupPyStrategy, Upgrade};
use uv_warnings::warn_user;

use crate::commands::reporters::{DownloadReporter, ResolverReporter};
Expand Down Expand Up @@ -358,6 +358,7 @@ pub(crate) async fn pip_compile(
&flat_index,
&top_level_index,
&build_dispatch,
&EmptyInstalledPackages,
)?
.with_reporter(ResolverReporter::from(printer));

Expand Down
1 change: 1 addition & 0 deletions crates/uv/src/commands/pip_install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,7 @@ async fn resolve(
flat_index,
index,
build_dispatch,
&site_packages,
)?
.with_reporter(ResolverReporter::from(printer));
let resolution = resolver.resolve().await?;
Expand Down
6 changes: 3 additions & 3 deletions crates/uv/src/commands/pip_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@ pub(crate) async fn pip_sync(
let no_binary = no_binary.combine(specified_no_binary);
let no_build = no_build.combine(specified_no_build);

// Determine the set of installed packages.
let site_packages = SitePackages::from_executable(&venv)?;

// Prep the build context.
let build_dispatch = BuildDispatch::new(
&client,
Expand Down Expand Up @@ -208,9 +211,6 @@ pub(crate) async fn pip_sync(
requirements
};

// Determine the set of installed packages.
let site_packages = SitePackages::from_executable(&venv)?;

// Resolve any editables.
let resolved_editables = resolve_editables(
editables,
Expand Down

0 comments on commit a0adc73

Please sign in to comment.