mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-03 18:38:21 +00:00
Add a diagnostic to detect invalid Python versions (#630)
Related to: https://github.com/astral-sh/puffin/issues/410.
This commit is contained in:
parent
a24eb57e93
commit
edd741bf13
2 changed files with 31 additions and 4 deletions
|
@ -384,7 +384,7 @@ fn allow_incompatibilities() -> Result<()> {
|
|||
Installed 1 package in [TIME]
|
||||
- jinja2==3.1.2
|
||||
+ jinja2==2.11.3
|
||||
warning: The package `flask` requires `jinja2 >=3.1.2` but `2.11.3` is installed.
|
||||
warning: The package `flask` requires `jinja2 >=3.1.2`, but `2.11.3` is installed.
|
||||
"###);
|
||||
});
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ use fs_err as fs;
|
|||
use rustc_hash::FxHashSet;
|
||||
|
||||
use distribution_types::{InstalledDist, Metadata, VersionOrUrl};
|
||||
use pep440_rs::Version;
|
||||
use pep440_rs::{Version, VersionSpecifiers};
|
||||
use pep508_rs::Requirement;
|
||||
use puffin_interpreter::Virtualenv;
|
||||
use puffin_normalize::PackageName;
|
||||
|
@ -95,6 +95,17 @@ impl<'a> SitePackages<'a> {
|
|||
// Determine the dependencies for the given package.
|
||||
let metadata = distribution.metadata()?;
|
||||
|
||||
// Verify that the package is compatible with the current Python version.
|
||||
if let Some(requires_python) = metadata.requires_python.as_ref() {
|
||||
if !requires_python.contains(self.venv.interpreter().version()) {
|
||||
diagnostics.push(Diagnostic::IncompatiblePythonVersion {
|
||||
package: package.clone(),
|
||||
version: self.venv.interpreter().version().clone(),
|
||||
requires_python: requires_python.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Verify that the dependencies are installed.
|
||||
for requirement in &metadata.requires_dist {
|
||||
if !requirement.evaluate_markers(self.venv.interpreter().markers(), &[]) {
|
||||
|
@ -198,6 +209,14 @@ impl IntoIterator for SitePackages<'_> {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub enum Diagnostic {
|
||||
IncompatiblePythonVersion {
|
||||
/// The package that requires a different version of Python.
|
||||
package: PackageName,
|
||||
/// The version of Python that is installed.
|
||||
version: Version,
|
||||
/// The version of Python that is required.
|
||||
requires_python: VersionSpecifiers,
|
||||
},
|
||||
MissingDependency {
|
||||
/// The package that is missing a dependency.
|
||||
package: PackageName,
|
||||
|
@ -218,18 +237,25 @@ impl Diagnostic {
|
|||
/// Convert the diagnostic into a user-facing message.
|
||||
pub fn message(&self) -> String {
|
||||
match self {
|
||||
Self::IncompatiblePythonVersion {
|
||||
package,
|
||||
version,
|
||||
requires_python,
|
||||
} => format!(
|
||||
"The package `{package}` requires Python {requires_python}, but `{version}` is installed."
|
||||
),
|
||||
Self::MissingDependency {
|
||||
package,
|
||||
requirement,
|
||||
} => {
|
||||
format!("The package `{package}` requires `{requirement}` but it is not installed.")
|
||||
format!("The package `{package}` requires `{requirement}`, but it's not installed.")
|
||||
}
|
||||
Self::IncompatibleDependency {
|
||||
package,
|
||||
version,
|
||||
requirement,
|
||||
} => format!(
|
||||
"The package `{package}` requires `{requirement}` but `{version}` is installed."
|
||||
"The package `{package}` requires `{requirement}`, but `{version}` is installed."
|
||||
),
|
||||
}
|
||||
}
|
||||
|
@ -237,6 +263,7 @@ impl Diagnostic {
|
|||
/// Returns `true` if the [`PackageName`] is involved in this diagnostic.
|
||||
pub fn includes(&self, name: &PackageName) -> bool {
|
||||
match self {
|
||||
Self::IncompatiblePythonVersion { package, .. } => name == package,
|
||||
Self::MissingDependency { package, .. } => name == package,
|
||||
Self::IncompatibleDependency {
|
||||
package,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue