-
Notifications
You must be signed in to change notification settings - Fork 766
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Show full derivation chain when encountering build failures #9108
Merged
+1,147
−172
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
use uv_normalize::PackageName; | ||
use uv_pep440::Version; | ||
|
||
/// A chain of derivation steps from the root package to the current package, to explain why a | ||
/// package is included in the resolution. | ||
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)] | ||
pub struct DerivationChain(Vec<DerivationStep>); | ||
|
||
impl FromIterator<DerivationStep> for DerivationChain { | ||
fn from_iter<T: IntoIterator<Item = DerivationStep>>(iter: T) -> Self { | ||
Self(iter.into_iter().collect()) | ||
} | ||
} | ||
|
||
impl DerivationChain { | ||
/// Returns the length of the derivation chain. | ||
pub fn len(&self) -> usize { | ||
self.0.len() | ||
} | ||
|
||
/// Returns `true` if the derivation chain is empty. | ||
pub fn is_empty(&self) -> bool { | ||
self.0.is_empty() | ||
} | ||
|
||
/// Returns an iterator over the steps in the derivation chain. | ||
pub fn iter(&self) -> std::slice::Iter<DerivationStep> { | ||
self.0.iter() | ||
} | ||
} | ||
|
||
impl std::fmt::Display for DerivationChain { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
for (idx, step) in self.0.iter().enumerate() { | ||
if idx > 0 { | ||
write!(f, " -> ")?; | ||
} | ||
write!(f, "{}=={}", step.name, step.version)?; | ||
} | ||
Ok(()) | ||
} | ||
} | ||
|
||
impl<'chain> IntoIterator for &'chain DerivationChain { | ||
type Item = &'chain DerivationStep; | ||
type IntoIter = std::slice::Iter<'chain, DerivationStep>; | ||
|
||
fn into_iter(self) -> Self::IntoIter { | ||
self.0.iter() | ||
} | ||
} | ||
|
||
impl IntoIterator for DerivationChain { | ||
type Item = DerivationStep; | ||
type IntoIter = std::vec::IntoIter<DerivationStep>; | ||
|
||
fn into_iter(self) -> Self::IntoIter { | ||
self.0.into_iter() | ||
} | ||
} | ||
|
||
/// A step in a derivation chain. | ||
#[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
pub struct DerivationStep { | ||
/// The name of the package. | ||
name: PackageName, | ||
/// The version of the package. | ||
version: Version, | ||
} | ||
|
||
impl DerivationStep { | ||
/// Create a [`DerivationStep`] from a package name and version. | ||
pub fn new(name: PackageName, version: Version) -> Self { | ||
Self { name, version } | ||
} | ||
} | ||
|
||
impl std::fmt::Display for DerivationStep { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
write!(f, "{}=={}", self.name, self.version) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,6 +52,7 @@ pub use crate::any::*; | |
pub use crate::buildable::*; | ||
pub use crate::cached::*; | ||
pub use crate::dependency_metadata::*; | ||
pub use crate::derivation::*; | ||
pub use crate::diagnostic::*; | ||
pub use crate::error::*; | ||
pub use crate::file::*; | ||
|
@@ -74,6 +75,7 @@ mod any; | |
mod buildable; | ||
mod cached; | ||
mod dependency_metadata; | ||
mod derivation; | ||
mod diagnostic; | ||
mod error; | ||
mod file; | ||
|
@@ -166,14 +168,21 @@ impl std::fmt::Display for InstalledVersion<'_> { | |
/// Either a built distribution, a wheel, or a source distribution that exists at some location. | ||
/// | ||
/// The location can be an index, URL or path (wheel), or index, URL, path or Git repository (source distribution). | ||
#[derive(Debug, Clone, Hash)] | ||
#[derive(Debug, Clone, Hash, PartialEq, Eq)] | ||
pub enum Dist { | ||
Built(BuiltDist), | ||
Source(SourceDist), | ||
} | ||
|
||
/// A reference to a built or source distribution. | ||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] | ||
pub enum DistRef<'a> { | ||
Built(&'a BuiltDist), | ||
Source(&'a SourceDist), | ||
} | ||
|
||
/// A wheel, with its three possible origins (index, url, path) | ||
#[derive(Debug, Clone, Hash)] | ||
#[derive(Debug, Clone, Hash, PartialEq, Eq)] | ||
#[allow(clippy::large_enum_variant)] | ||
pub enum BuiltDist { | ||
Registry(RegistryBuiltDist), | ||
|
@@ -182,7 +191,7 @@ pub enum BuiltDist { | |
} | ||
|
||
/// A source distribution, with its possible origins (index, url, path, git) | ||
#[derive(Debug, Clone, Hash)] | ||
#[derive(Debug, Clone, Hash, PartialEq, Eq)] | ||
#[allow(clippy::large_enum_variant)] | ||
pub enum SourceDist { | ||
Registry(RegistrySourceDist), | ||
|
@@ -193,15 +202,15 @@ pub enum SourceDist { | |
} | ||
|
||
/// A built distribution (wheel) that exists in a registry, like `PyPI`. | ||
#[derive(Debug, Clone, Hash)] | ||
#[derive(Debug, Clone, Hash, PartialEq, Eq)] | ||
pub struct RegistryBuiltWheel { | ||
pub filename: WheelFilename, | ||
pub file: Box<File>, | ||
pub index: IndexUrl, | ||
} | ||
|
||
/// A built distribution (wheel) that exists in a registry, like `PyPI`. | ||
#[derive(Debug, Clone, Hash)] | ||
#[derive(Debug, Clone, Hash, PartialEq, Eq)] | ||
pub struct RegistryBuiltDist { | ||
/// All wheels associated with this distribution. It is guaranteed | ||
/// that there is at least one wheel. | ||
|
@@ -231,7 +240,7 @@ pub struct RegistryBuiltDist { | |
} | ||
|
||
/// A built distribution (wheel) that exists at an arbitrary URL. | ||
#[derive(Debug, Clone, Hash)] | ||
#[derive(Debug, Clone, Hash, PartialEq, Eq)] | ||
pub struct DirectUrlBuiltDist { | ||
/// We require that wheel urls end in the full wheel filename, e.g. | ||
/// `https://example.org/packages/flask-3.0.0-py3-none-any.whl` | ||
|
@@ -243,7 +252,7 @@ pub struct DirectUrlBuiltDist { | |
} | ||
|
||
/// A built distribution (wheel) that exists in a local directory. | ||
#[derive(Debug, Clone, Hash)] | ||
#[derive(Debug, Clone, Hash, PartialEq, Eq)] | ||
pub struct PathBuiltDist { | ||
pub filename: WheelFilename, | ||
/// The absolute path to the wheel which we use for installing. | ||
|
@@ -253,7 +262,7 @@ pub struct PathBuiltDist { | |
} | ||
|
||
/// A source distribution that exists in a registry, like `PyPI`. | ||
#[derive(Debug, Clone, Hash)] | ||
#[derive(Debug, Clone, Hash, PartialEq, Eq)] | ||
pub struct RegistrySourceDist { | ||
pub name: PackageName, | ||
pub version: Version, | ||
|
@@ -272,7 +281,7 @@ pub struct RegistrySourceDist { | |
} | ||
|
||
/// A source distribution that exists at an arbitrary URL. | ||
#[derive(Debug, Clone, Hash)] | ||
#[derive(Debug, Clone, Hash, PartialEq, Eq)] | ||
pub struct DirectUrlSourceDist { | ||
/// Unlike [`DirectUrlBuiltDist`], we can't require a full filename with a version here, people | ||
/// like using e.g. `foo @ https://github.com/org/repo/archive/master.zip` | ||
|
@@ -288,7 +297,7 @@ pub struct DirectUrlSourceDist { | |
} | ||
|
||
/// A source distribution that exists in a Git repository. | ||
#[derive(Debug, Clone, Hash)] | ||
#[derive(Debug, Clone, Hash, PartialEq, Eq)] | ||
pub struct GitSourceDist { | ||
pub name: PackageName, | ||
/// The URL without the revision and subdirectory fragment. | ||
|
@@ -300,7 +309,7 @@ pub struct GitSourceDist { | |
} | ||
|
||
/// A source distribution that exists in a local archive (e.g., a `.tar.gz` file). | ||
#[derive(Debug, Clone, Hash)] | ||
#[derive(Debug, Clone, Hash, PartialEq, Eq)] | ||
pub struct PathSourceDist { | ||
pub name: PackageName, | ||
/// The absolute path to the distribution which we use for installing. | ||
|
@@ -312,7 +321,7 @@ pub struct PathSourceDist { | |
} | ||
|
||
/// A source distribution that exists in a local directory. | ||
#[derive(Debug, Clone, Hash)] | ||
#[derive(Debug, Clone, Hash, PartialEq, Eq)] | ||
pub struct DirectorySourceDist { | ||
pub name: PackageName, | ||
/// The absolute path to the distribution which we use for installing. | ||
|
@@ -512,12 +521,33 @@ impl Dist { | |
} | ||
} | ||
|
||
/// Returns the version of the distribution, if it is known. | ||
pub fn version(&self) -> Option<&Version> { | ||
match self { | ||
Self::Built(wheel) => Some(wheel.version()), | ||
Self::Source(source_dist) => source_dist.version(), | ||
} | ||
} | ||
|
||
/// Convert this distribution into a reference. | ||
pub fn as_ref(&self) -> DistRef { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh interesting, I thought Clippy didn't like omitting lifetimes like this. e.g., |
||
match self { | ||
Self::Built(dist) => DistRef::Built(dist), | ||
Self::Source(dist) => DistRef::Source(dist), | ||
} | ||
} | ||
} | ||
|
||
impl<'a> From<&'a SourceDist> for DistRef<'a> { | ||
fn from(dist: &'a SourceDist) -> Self { | ||
DistRef::Source(dist) | ||
} | ||
} | ||
|
||
impl<'a> From<&'a BuiltDist> for DistRef<'a> { | ||
fn from(dist: &'a BuiltDist) -> Self { | ||
DistRef::Built(dist) | ||
} | ||
} | ||
|
||
impl BuiltDist { | ||
|
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yay ref types.
I don't know if you saw it in my conflicting groups PR, but a useful tip if you ever need to use one of these types for key lookups in hashmaps is to use hashbrown and its
Equivalent
trait.