mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 21:35:00 +00:00
Always use release-only comparisons for requires-python
(#4794)
## Summary There are a few ideas at play here: 1. pip always strips versions to the release when evaluating against a `Requires-Python`, so we now do the same. That means, e.g., using `3.13.0b0` will be accepted by a project with `Requires-Python: >= 3.13`, which does _not_ adhere to PEP 440 semantics but is somewhat intuitive. 2. Because we know we'll only be evaluating against release-only versions, we can use different semantics in PubGrub that let us collapse ranges. For example, `python_version >= '3.10' or python_version < '3.10'` can be collapsed to the truthy marker. Closes https://github.com/astral-sh/uv/issues/4714. Closes https://github.com/astral-sh/uv/issues/4272. Closes https://github.com/astral-sh/uv/issues/4719.
This commit is contained in:
parent
11cb0059c1
commit
b588054dfb
13 changed files with 401 additions and 171 deletions
|
@ -1,5 +1,5 @@
|
|||
use pep440_rs::VersionSpecifiers;
|
||||
use pep508_rs::{MarkerTree, StringVersion};
|
||||
use pep440_rs::{Version, VersionSpecifiers};
|
||||
use pep508_rs::MarkerTree;
|
||||
use uv_python::{Interpreter, PythonVersion};
|
||||
|
||||
use crate::{RequiresPython, RequiresPythonBound};
|
||||
|
@ -7,7 +7,7 @@ use crate::{RequiresPython, RequiresPythonBound};
|
|||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct PythonRequirement {
|
||||
/// The installed version of Python.
|
||||
installed: StringVersion,
|
||||
installed: Version,
|
||||
/// The target version of Python; that is, the version of Python for which we are resolving
|
||||
/// dependencies. This is typically the same as the installed version, but may be different
|
||||
/// when specifying an alternate Python version for the resolution.
|
||||
|
@ -21,11 +21,10 @@ impl PythonRequirement {
|
|||
/// [`PythonVersion`].
|
||||
pub fn from_python_version(interpreter: &Interpreter, python_version: &PythonVersion) -> Self {
|
||||
Self {
|
||||
installed: interpreter.python_full_version().clone(),
|
||||
target: Some(PythonTarget::Version(StringVersion {
|
||||
string: python_version.to_string(),
|
||||
version: python_version.python_full_version(),
|
||||
})),
|
||||
installed: interpreter.python_full_version().version.only_release(),
|
||||
target: Some(PythonTarget::Version(
|
||||
python_version.python_full_version().only_release(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,7 +35,7 @@ impl PythonRequirement {
|
|||
requires_python: &RequiresPython,
|
||||
) -> Self {
|
||||
Self {
|
||||
installed: interpreter.python_full_version().clone(),
|
||||
installed: interpreter.python_full_version().version.only_release(),
|
||||
target: Some(PythonTarget::RequiresPython(requires_python.clone())),
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +43,7 @@ impl PythonRequirement {
|
|||
/// Create a [`PythonRequirement`] to resolve against an [`Interpreter`].
|
||||
pub fn from_interpreter(interpreter: &Interpreter) -> Self {
|
||||
Self {
|
||||
installed: interpreter.python_full_version().clone(),
|
||||
installed: interpreter.python_full_version().version.only_release(),
|
||||
target: None,
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +62,7 @@ impl PythonRequirement {
|
|||
}
|
||||
|
||||
/// Return the installed version of Python.
|
||||
pub fn installed(&self) -> &StringVersion {
|
||||
pub fn installed(&self) -> &Version {
|
||||
&self.installed
|
||||
}
|
||||
|
||||
|
@ -91,7 +90,7 @@ pub enum PythonTarget {
|
|||
///
|
||||
/// The use of a separate enum variant allows us to use a verbatim representation when reporting
|
||||
/// back to the user.
|
||||
Version(StringVersion),
|
||||
Version(Version),
|
||||
/// The [`PythonTarget`] specifier is a set of version specifiers, as extracted from the
|
||||
/// `Requires-Python` field in a `pyproject.toml` or `METADATA` file.
|
||||
RequiresPython(RequiresPython),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue