Cache WHEEL and METADATA reads in installed distributions (#15489)

## Summary

Uses interior mutability to cache the reads. This follows the pattern we
use for reading the platform tags in `Interpreter::tags`.
This commit is contained in:
Charlie Marsh 2025-08-25 09:40:20 -04:00 committed by GitHub
parent be4d5b72aa
commit ef9a332364
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 240 additions and 161 deletions

View file

@ -2,6 +2,7 @@ use std::borrow::Cow;
use std::io::BufReader;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::sync::OnceLock;
use fs_err as fs;
use thiserror::Error;
@ -68,9 +69,42 @@ pub enum InstalledDistError {
},
}
#[derive(Debug, Clone)]
pub struct InstalledDist {
pub kind: InstalledDistKind,
// Cache data that must be read from the `.dist-info` directory. These are safe to cache as
// the `InstalledDist` is immutable after creation.
metadata_cache: OnceLock<uv_pypi_types::ResolutionMetadata>,
tags_cache: OnceLock<Option<ExpandedTags>>,
}
impl From<InstalledDistKind> for InstalledDist {
fn from(kind: InstalledDistKind) -> Self {
Self {
kind,
metadata_cache: OnceLock::new(),
tags_cache: OnceLock::new(),
}
}
}
impl std::hash::Hash for InstalledDist {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.kind.hash(state);
}
}
impl PartialEq for InstalledDist {
fn eq(&self, other: &Self) -> bool {
self.kind == other.kind
}
}
impl Eq for InstalledDist {}
/// A built distribution (wheel) that is installed in a virtual environment.
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum InstalledDist {
pub enum InstalledDistKind {
/// The distribution was derived from a registry, like `PyPI`.
Registry(InstalledRegistryDist),
/// The distribution was derived from an arbitrary URL.
@ -152,35 +186,41 @@ impl InstalledDist {
return if let Some(direct_url) = Self::read_direct_url(path)? {
match Url::try_from(&direct_url) {
Ok(url) => Ok(Some(Self::Url(InstalledDirectUrlDist {
name,
version,
editable: matches!(&direct_url, DirectUrl::LocalDirectory { dir_info, .. } if dir_info.editable == Some(true)),
direct_url: Box::new(direct_url),
url: DisplaySafeUrl::from(url),
path: path.to_path_buf().into_boxed_path(),
cache_info,
build_info,
}))),
Err(err) => {
warn!("Failed to parse direct URL: {err}");
Ok(Some(Self::Registry(InstalledRegistryDist {
Ok(url) => Ok(Some(Self::from(InstalledDistKind::Url(
InstalledDirectUrlDist {
name,
version,
editable: matches!(&direct_url, DirectUrl::LocalDirectory { dir_info, .. } if dir_info.editable == Some(true)),
direct_url: Box::new(direct_url),
url: DisplaySafeUrl::from(url),
path: path.to_path_buf().into_boxed_path(),
cache_info,
build_info,
})))
},
)))),
Err(err) => {
warn!("Failed to parse direct URL: {err}");
Ok(Some(Self::from(InstalledDistKind::Registry(
InstalledRegistryDist {
name,
version,
path: path.to_path_buf().into_boxed_path(),
cache_info,
build_info,
},
))))
}
}
} else {
Ok(Some(Self::Registry(InstalledRegistryDist {
name,
version,
path: path.to_path_buf().into_boxed_path(),
cache_info,
build_info,
})))
Ok(Some(Self::from(InstalledDistKind::Registry(
InstalledRegistryDist {
name,
version,
path: path.to_path_buf().into_boxed_path(),
cache_info,
build_info,
},
))))
};
}
@ -204,19 +244,23 @@ impl InstalledDist {
if let Some(version) = file_name.version {
if metadata.is_dir() {
return Ok(Some(Self::EggInfoDirectory(InstalledEggInfoDirectory {
name: file_name.name,
version,
path: path.to_path_buf().into_boxed_path(),
})));
return Ok(Some(Self::from(InstalledDistKind::EggInfoDirectory(
InstalledEggInfoDirectory {
name: file_name.name,
version,
path: path.to_path_buf().into_boxed_path(),
},
))));
}
if metadata.is_file() {
return Ok(Some(Self::EggInfoFile(InstalledEggInfoFile {
name: file_name.name,
version,
path: path.to_path_buf().into_boxed_path(),
})));
return Ok(Some(Self::from(InstalledDistKind::EggInfoFile(
InstalledEggInfoFile {
name: file_name.name,
version,
path: path.to_path_buf().into_boxed_path(),
},
))));
}
}
@ -224,22 +268,26 @@ impl InstalledDist {
let Some(egg_metadata) = read_metadata(&path.join("PKG-INFO")) else {
return Ok(None);
};
return Ok(Some(Self::EggInfoDirectory(InstalledEggInfoDirectory {
name: file_name.name,
version: Version::from_str(&egg_metadata.version)?,
path: path.to_path_buf().into_boxed_path(),
})));
return Ok(Some(Self::from(InstalledDistKind::EggInfoDirectory(
InstalledEggInfoDirectory {
name: file_name.name,
version: Version::from_str(&egg_metadata.version)?,
path: path.to_path_buf().into_boxed_path(),
},
))));
}
if metadata.is_file() {
let Some(egg_metadata) = read_metadata(path) else {
return Ok(None);
};
return Ok(Some(Self::EggInfoDirectory(InstalledEggInfoDirectory {
name: file_name.name,
version: Version::from_str(&egg_metadata.version)?,
path: path.to_path_buf().into_boxed_path(),
})));
return Ok(Some(Self::from(InstalledDistKind::EggInfoDirectory(
InstalledEggInfoDirectory {
name: file_name.name,
version: Version::from_str(&egg_metadata.version)?,
path: path.to_path_buf().into_boxed_path(),
},
))));
}
}
@ -283,14 +331,16 @@ impl InstalledDist {
return Ok(None);
};
return Ok(Some(Self::LegacyEditable(InstalledLegacyEditable {
name: egg_metadata.name,
version: Version::from_str(&egg_metadata.version)?,
egg_link: path.to_path_buf().into_boxed_path(),
target: target.into_boxed_path(),
target_url: DisplaySafeUrl::from(url),
egg_info: egg_info.into_boxed_path(),
})));
return Ok(Some(Self::from(InstalledDistKind::LegacyEditable(
InstalledLegacyEditable {
name: egg_metadata.name,
version: Version::from_str(&egg_metadata.version)?,
egg_link: path.to_path_buf().into_boxed_path(),
target: target.into_boxed_path(),
target_url: DisplaySafeUrl::from(url),
egg_info: egg_info.into_boxed_path(),
},
))));
}
Ok(None)
@ -298,45 +348,45 @@ impl InstalledDist {
/// Return the [`Path`] at which the distribution is stored on-disk.
pub fn install_path(&self) -> &Path {
match self {
Self::Registry(dist) => &dist.path,
Self::Url(dist) => &dist.path,
Self::EggInfoDirectory(dist) => &dist.path,
Self::EggInfoFile(dist) => &dist.path,
Self::LegacyEditable(dist) => &dist.egg_info,
match &self.kind {
InstalledDistKind::Registry(dist) => &dist.path,
InstalledDistKind::Url(dist) => &dist.path,
InstalledDistKind::EggInfoDirectory(dist) => &dist.path,
InstalledDistKind::EggInfoFile(dist) => &dist.path,
InstalledDistKind::LegacyEditable(dist) => &dist.egg_info,
}
}
/// Return the [`Version`] of the distribution.
pub fn version(&self) -> &Version {
match self {
Self::Registry(dist) => &dist.version,
Self::Url(dist) => &dist.version,
Self::EggInfoDirectory(dist) => &dist.version,
Self::EggInfoFile(dist) => &dist.version,
Self::LegacyEditable(dist) => &dist.version,
match &self.kind {
InstalledDistKind::Registry(dist) => &dist.version,
InstalledDistKind::Url(dist) => &dist.version,
InstalledDistKind::EggInfoDirectory(dist) => &dist.version,
InstalledDistKind::EggInfoFile(dist) => &dist.version,
InstalledDistKind::LegacyEditable(dist) => &dist.version,
}
}
/// Return the [`CacheInfo`] of the distribution, if any.
pub fn cache_info(&self) -> Option<&CacheInfo> {
match self {
Self::Registry(dist) => dist.cache_info.as_ref(),
Self::Url(dist) => dist.cache_info.as_ref(),
Self::EggInfoDirectory(..) => None,
Self::EggInfoFile(..) => None,
Self::LegacyEditable(..) => None,
match &self.kind {
InstalledDistKind::Registry(dist) => dist.cache_info.as_ref(),
InstalledDistKind::Url(dist) => dist.cache_info.as_ref(),
InstalledDistKind::EggInfoDirectory(..) => None,
InstalledDistKind::EggInfoFile(..) => None,
InstalledDistKind::LegacyEditable(..) => None,
}
}
/// Return the [`BuildInfo`] of the distribution, if any.
pub fn build_info(&self) -> Option<&BuildInfo> {
match self {
Self::Registry(dist) => dist.build_info.as_ref(),
Self::Url(dist) => dist.build_info.as_ref(),
Self::EggInfoDirectory(..) => None,
Self::EggInfoFile(..) => None,
Self::LegacyEditable(..) => None,
match &self.kind {
InstalledDistKind::Registry(dist) => dist.build_info.as_ref(),
InstalledDistKind::Url(dist) => dist.build_info.as_ref(),
InstalledDistKind::EggInfoDirectory(..) => None,
InstalledDistKind::EggInfoFile(..) => None,
InstalledDistKind::LegacyEditable(..) => None,
}
}
@ -380,9 +430,13 @@ impl InstalledDist {
}
/// Read the `METADATA` file from a `.dist-info` directory.
pub fn read_metadata(&self) -> Result<uv_pypi_types::ResolutionMetadata, InstalledDistError> {
match self {
Self::Registry(_) | Self::Url(_) => {
pub fn read_metadata(&self) -> Result<&uv_pypi_types::ResolutionMetadata, InstalledDistError> {
if let Some(metadata) = self.metadata_cache.get() {
return Ok(metadata);
}
let metadata = match &self.kind {
InstalledDistKind::Registry(_) | InstalledDistKind::Url(_) => {
let path = self.install_path().join("METADATA");
let contents = fs::read(&path)?;
// TODO(zanieb): Update this to use thiserror so we can unpack parse errors downstream
@ -391,13 +445,19 @@ impl InstalledDist {
path: path.clone(),
err: Box::new(err),
}
})
})?
}
Self::EggInfoFile(_) | Self::EggInfoDirectory(_) | Self::LegacyEditable(_) => {
let path = match self {
Self::EggInfoFile(dist) => Cow::Borrowed(&*dist.path),
Self::EggInfoDirectory(dist) => Cow::Owned(dist.path.join("PKG-INFO")),
Self::LegacyEditable(dist) => Cow::Owned(dist.egg_info.join("PKG-INFO")),
InstalledDistKind::EggInfoFile(_)
| InstalledDistKind::EggInfoDirectory(_)
| InstalledDistKind::LegacyEditable(_) => {
let path = match &self.kind {
InstalledDistKind::EggInfoFile(dist) => Cow::Borrowed(&*dist.path),
InstalledDistKind::EggInfoDirectory(dist) => {
Cow::Owned(dist.path.join("PKG-INFO"))
}
InstalledDistKind::LegacyEditable(dist) => {
Cow::Owned(dist.egg_info.join("PKG-INFO"))
}
_ => unreachable!(),
};
let contents = fs::read(path.as_ref())?;
@ -406,9 +466,12 @@ impl InstalledDist {
path: path.to_path_buf(),
err: Box::new(err),
}
})
})?
}
}
};
let _ = self.metadata_cache.set(metadata);
Ok(self.metadata_cache.get().expect("metadata should be set"))
}
/// Return the `INSTALLER` of the distribution.
@ -422,56 +485,64 @@ impl InstalledDist {
}
/// Return the supported wheel tags for the distribution from the `WHEEL` file, if available.
pub fn read_tags(&self) -> Result<Option<ExpandedTags>, InstalledDistError> {
// TODO(charlie): Cache this result.
let path = match self {
Self::Registry(InstalledRegistryDist { path, .. }) => path,
Self::Url(InstalledDirectUrlDist { path, .. }) => path,
Self::EggInfoFile(_) => return Ok(None),
Self::EggInfoDirectory(_) => return Ok(None),
Self::LegacyEditable(_) => return Ok(None),
pub fn read_tags(&self) -> Result<Option<&ExpandedTags>, InstalledDistError> {
if let Some(tags) = self.tags_cache.get() {
return Ok(tags.as_ref());
}
let path = match &self.kind {
InstalledDistKind::Registry(dist) => &dist.path,
InstalledDistKind::Url(dist) => &dist.path,
InstalledDistKind::EggInfoFile(_) => return Ok(None),
InstalledDistKind::EggInfoDirectory(_) => return Ok(None),
InstalledDistKind::LegacyEditable(_) => return Ok(None),
};
// Read the `WHEEL` file.
let contents = fs_err::read_to_string(path.join("WHEEL"))?;
let wheel_file = WheelFile::parse(&contents)?;
let Some(tags) = wheel_file.tags() else {
return Ok(None);
};
// Parse the tags.
let tags = ExpandedTags::parse(tags.iter().map(String::as_str))?;
let tags = if let Some(tags) = wheel_file.tags() {
Some(ExpandedTags::parse(tags.iter().map(String::as_str))?)
} else {
None
};
Ok(Some(tags))
let _ = self.tags_cache.set(tags);
Ok(self.tags_cache.get().expect("tags should be set").as_ref())
}
/// Return true if the distribution is editable.
pub fn is_editable(&self) -> bool {
matches!(
self,
Self::LegacyEditable(_) | Self::Url(InstalledDirectUrlDist { editable: true, .. })
&self.kind,
InstalledDistKind::LegacyEditable(_)
| InstalledDistKind::Url(InstalledDirectUrlDist { editable: true, .. })
)
}
/// Return the [`Url`] of the distribution, if it is editable.
pub fn as_editable(&self) -> Option<&Url> {
match self {
Self::Registry(_) => None,
Self::Url(dist) => dist.editable.then_some(&dist.url),
Self::EggInfoFile(_) => None,
Self::EggInfoDirectory(_) => None,
Self::LegacyEditable(dist) => Some(&dist.target_url),
match &self.kind {
InstalledDistKind::Registry(_) => None,
InstalledDistKind::Url(dist) => dist.editable.then_some(&dist.url),
InstalledDistKind::EggInfoFile(_) => None,
InstalledDistKind::EggInfoDirectory(_) => None,
InstalledDistKind::LegacyEditable(dist) => Some(&dist.target_url),
}
}
/// Return true if the distribution refers to a local file or directory.
pub fn is_local(&self) -> bool {
match self {
Self::Registry(_) => false,
Self::Url(dist) => matches!(&*dist.direct_url, DirectUrl::LocalDirectory { .. }),
Self::EggInfoFile(_) => false,
Self::EggInfoDirectory(_) => false,
Self::LegacyEditable(_) => true,
match &self.kind {
InstalledDistKind::Registry(_) => false,
InstalledDistKind::Url(dist) => {
matches!(&*dist.direct_url, DirectUrl::LocalDirectory { .. })
}
InstalledDistKind::EggInfoFile(_) => false,
InstalledDistKind::EggInfoDirectory(_) => false,
InstalledDistKind::LegacyEditable(_) => true,
}
}
}
@ -514,12 +585,12 @@ impl Name for InstalledLegacyEditable {
impl Name for InstalledDist {
fn name(&self) -> &PackageName {
match self {
Self::Registry(dist) => dist.name(),
Self::Url(dist) => dist.name(),
Self::EggInfoDirectory(dist) => dist.name(),
Self::EggInfoFile(dist) => dist.name(),
Self::LegacyEditable(dist) => dist.name(),
match &self.kind {
InstalledDistKind::Registry(dist) => dist.name(),
InstalledDistKind::Url(dist) => dist.name(),
InstalledDistKind::EggInfoDirectory(dist) => dist.name(),
InstalledDistKind::EggInfoFile(dist) => dist.name(),
InstalledDistKind::LegacyEditable(dist) => dist.name(),
}
}
}
@ -556,12 +627,12 @@ impl InstalledMetadata for InstalledLegacyEditable {
impl InstalledMetadata for InstalledDist {
fn installed_version(&self) -> InstalledVersion<'_> {
match self {
Self::Registry(dist) => dist.installed_version(),
Self::Url(dist) => dist.installed_version(),
Self::EggInfoFile(dist) => dist.installed_version(),
Self::EggInfoDirectory(dist) => dist.installed_version(),
Self::LegacyEditable(dist) => dist.installed_version(),
match &self.kind {
InstalledDistKind::Registry(dist) => dist.installed_version(),
InstalledDistKind::Url(dist) => dist.installed_version(),
InstalledDistKind::EggInfoFile(dist) => dist.installed_version(),
InstalledDistKind::EggInfoDirectory(dist) => dist.installed_version(),
InstalledDistKind::LegacyEditable(dist) => dist.installed_version(),
}
}
}

View file

@ -144,7 +144,7 @@ impl<'a, Context: BuildContext> DistributionDatabase<'a, Context> {
.read_metadata()
.map_err(|err| Error::ReadInstalled(Box::new(dist.clone()), err))?;
Ok(ArchiveMetadata::from_metadata23(metadata))
Ok(ArchiveMetadata::from_metadata23(metadata.clone()))
}
/// Either fetch the only wheel metadata (directly from the index or with range requests) or

View file

@ -9,8 +9,8 @@ use uv_cache_info::CacheInfo;
use uv_cache_key::{CanonicalUrl, RepositoryUrl};
use uv_distribution_types::{
BuildInfo, BuildVariables, ConfigSettings, ExtraBuildRequirement, ExtraBuildRequires,
ExtraBuildVariables, InstalledDirectUrlDist, InstalledDist, PackageConfigSettings,
RequirementSource,
ExtraBuildVariables, InstalledDirectUrlDist, InstalledDist, InstalledDistKind,
PackageConfigSettings, RequirementSource,
};
use uv_git_types::GitOid;
use uv_normalize::PackageName;
@ -78,12 +78,12 @@ impl RequirementSatisfaction {
ext: _,
url: _,
} => {
let InstalledDist::Url(InstalledDirectUrlDist {
let InstalledDistKind::Url(InstalledDirectUrlDist {
direct_url,
editable,
cache_info,
..
}) = &distribution
}) = &distribution.kind
else {
return Self::Mismatch;
};
@ -137,7 +137,8 @@ impl RequirementSatisfaction {
git: requested_git,
subdirectory: requested_subdirectory,
} => {
let InstalledDist::Url(InstalledDirectUrlDist { direct_url, .. }) = &distribution
let InstalledDistKind::Url(InstalledDirectUrlDist { direct_url, .. }) =
&distribution.kind
else {
return Self::Mismatch;
};
@ -192,11 +193,11 @@ impl RequirementSatisfaction {
ext: _,
url: _,
} => {
let InstalledDist::Url(InstalledDirectUrlDist {
let InstalledDistKind::Url(InstalledDirectUrlDist {
direct_url,
cache_info,
..
}) = &distribution
}) = &distribution.kind
else {
return Self::Mismatch;
};
@ -247,11 +248,11 @@ impl RequirementSatisfaction {
r#virtual: _,
url: _,
} => {
let InstalledDist::Url(InstalledDirectUrlDist {
let InstalledDistKind::Url(InstalledDirectUrlDist {
direct_url,
cache_info,
..
}) = &distribution
}) = &distribution.kind
else {
return Self::Mismatch;
};

View file

@ -8,9 +8,9 @@ use fs_err as fs;
use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet};
use uv_distribution_types::{
ConfigSettings, Diagnostic, ExtraBuildRequires, ExtraBuildVariables, InstalledDist, Name,
NameRequirementSpecification, PackageConfigSettings, Requirement, UnresolvedRequirement,
UnresolvedRequirementSpecification,
ConfigSettings, Diagnostic, ExtraBuildRequires, ExtraBuildVariables, InstalledDist,
InstalledDistKind, Name, NameRequirementSpecification, PackageConfigSettings, Requirement,
UnresolvedRequirement, UnresolvedRequirementSpecification,
};
use uv_fs::Simplified;
use uv_normalize::PackageName;
@ -126,7 +126,7 @@ impl SitePackages {
.push(idx);
// Index the distribution by URL.
if let InstalledDist::Url(dist) = &dist_info {
if let InstalledDistKind::Url(dist) = &dist_info.kind {
by_url.entry(dist.url.clone()).or_default().push(idx);
}
@ -528,8 +528,8 @@ impl SitePackages {
.with_context(|| format!("Failed to read metadata for: {distribution}"))?;
// Add the dependencies to the queue.
for dependency in metadata.requires_dist {
let dependency = Requirement::from(dependency);
for dependency in &metadata.requires_dist {
let dependency = Requirement::from(dependency.clone());
if let Some(r#overrides) = overrides.get(&dependency.name) {
for dependency in r#overrides {
if dependency.evaluate_markers(Some(markers), &requirement.extras) {

View file

@ -1,4 +1,4 @@
use uv_distribution_types::{InstalledDist, InstalledEggInfoFile};
use uv_distribution_types::{InstalledDist, InstalledDistKind, InstalledEggInfoFile};
/// Uninstall a package from the specified Python environment.
pub async fn uninstall(
@ -6,17 +6,17 @@ pub async fn uninstall(
) -> Result<uv_install_wheel::Uninstall, UninstallError> {
let uninstall = tokio::task::spawn_blocking({
let dist = dist.clone();
move || match dist {
InstalledDist::Registry(_) | InstalledDist::Url(_) => {
move || match dist.kind {
InstalledDistKind::Registry(_) | InstalledDistKind::Url(_) => {
Ok(uv_install_wheel::uninstall_wheel(dist.install_path())?)
}
InstalledDist::EggInfoDirectory(_) => {
InstalledDistKind::EggInfoDirectory(_) => {
Ok(uv_install_wheel::uninstall_egg(dist.install_path())?)
}
InstalledDist::LegacyEditable(dist) => {
InstalledDistKind::LegacyEditable(dist) => {
Ok(uv_install_wheel::uninstall_legacy_editable(&dist.egg_link)?)
}
InstalledDist::EggInfoFile(dist) => Err(UninstallError::Distutils(dist)),
InstalledDistKind::EggInfoFile(dist) => Err(UninstallError::Distutils(dist)),
}
})
.await??;

View file

@ -4,7 +4,7 @@ use std::str::FromStr;
use rustc_hash::FxHashMap;
use tracing::trace;
use uv_distribution_types::{IndexUrl, InstalledDist};
use uv_distribution_types::{IndexUrl, InstalledDist, InstalledDistKind};
use uv_normalize::PackageName;
use uv_pep440::{Operator, Version};
use uv_pep508::{MarkerTree, VerbatimUrl, VersionOrUrl};
@ -122,7 +122,7 @@ impl Preference {
/// Create a [`Preference`] from an installed distribution.
pub fn from_installed(dist: &InstalledDist) -> Option<Self> {
let InstalledDist::Registry(dist) = dist else {
let InstalledDistKind::Registry(dist) = &dist.kind else {
return None;
};
Some(Self {

View file

@ -6,7 +6,7 @@ use itertools::Itertools;
use owo_colors::OwoColorize;
use uv_cache::Cache;
use uv_distribution_types::{Diagnostic, InstalledDist, Name};
use uv_distribution_types::{Diagnostic, InstalledDistKind, Name};
use uv_installer::SitePackages;
use uv_preview::Preview;
use uv_python::PythonPreference;
@ -61,24 +61,24 @@ pub(crate) fn pip_freeze(
.flat_map(uv_installer::SitePackages::iter)
.filter(|dist| !(exclude_editable && dist.is_editable()))
.sorted_unstable_by(|a, b| a.name().cmp(b.name()).then(a.version().cmp(b.version())))
.map(|dist| match dist {
InstalledDist::Registry(dist) => {
.map(|dist| match &dist.kind {
InstalledDistKind::Registry(dist) => {
format!("{}=={}", dist.name().bold(), dist.version)
}
InstalledDist::Url(dist) => {
InstalledDistKind::Url(dist) => {
if dist.editable {
format!("-e {}", dist.url)
} else {
format!("{} @ {}", dist.name().bold(), dist.url)
}
}
InstalledDist::EggInfoFile(dist) => {
InstalledDistKind::EggInfoFile(dist) => {
format!("{}=={}", dist.name().bold(), dist.version)
}
InstalledDist::EggInfoDirectory(dist) => {
InstalledDistKind::EggInfoDirectory(dist) => {
format!("{}=={}", dist.name().bold(), dist.version)
}
InstalledDist::LegacyEditable(dist) => {
InstalledDistKind::LegacyEditable(dist) => {
format!("-e {}", dist.target.display())
}
})

View file

@ -389,6 +389,9 @@ pub(crate) struct Changelog {
impl Changelog {
/// Create a [`Changelog`] from a list of installed and uninstalled distributions.
pub(crate) fn new(installed: Vec<CachedDist>, uninstalled: Vec<InstalledDist>) -> Self {
// SAFETY: This is allowed because `LocalDist` implements `Hash` and `Eq` based solely on
// the inner `kind`, and omits the types that rely on internal mutability.
#[allow(clippy::mutable_key_type)]
let mut uninstalled: HashSet<_> = uninstalled.into_iter().map(LocalDist::from).collect();
let (reinstalled, installed): (HashSet<_>, HashSet<_>) = installed

View file

@ -102,9 +102,11 @@ pub(crate) fn pip_show(
if let Ok(metadata) = dist.read_metadata() {
requires_map.insert(
dist.name(),
Box::into_iter(metadata.requires_dist)
metadata
.requires_dist
.iter()
.filter(|req| req.evaluate_markers(&markers, &[]))
.map(|req| req.name)
.map(|req| &req.name)
.sorted_unstable()
.dedup()
.collect_vec(),
@ -118,9 +120,11 @@ pub(crate) fn pip_show(
continue;
}
if let Ok(metadata) = installed.read_metadata() {
let requires = Box::into_iter(metadata.requires_dist)
let requires = metadata
.requires_dist
.iter()
.filter(|req| req.evaluate_markers(&markers, &[]))
.map(|req| req.name)
.map(|req| &req.name)
.collect_vec();
if !requires.is_empty() {
requires_map.insert(installed.name(), requires);
@ -172,7 +176,7 @@ pub(crate) fn pip_show(
.iter()
.filter(|(name, pkgs)| {
**name != distribution.name()
&& pkgs.iter().any(|pkg| pkg == distribution.name())
&& pkgs.iter().any(|pkg| *pkg == distribution.name())
})
.map(|(name, _)| name)
.sorted_unstable()

View file

@ -225,7 +225,7 @@ impl<'env> DisplayDependencyGraph<'env> {
invert: bool,
show_version_specifiers: bool,
markers: &ResolverMarkerEnvironment,
packages: &'env FxHashMap<&PackageName, Vec<ResolutionMetadata>>,
packages: &'env FxHashMap<&PackageName, Vec<&ResolutionMetadata>>,
latest: &'env FxHashMap<&PackageName, Version>,
) -> Self {
// Create a graph.