Model Python version as a PubGrub package (#745)
## Summary This PR modifies the resolver to treat the Python version as a package, which allows for better error messages (since we no longer treat incompatible packages as if they "don't exist at all"). There are a few tricky pieces here... First, we need to track both the interpreter's Python version and the _target_ Python version, because we support resolving for other versions via `--python 3.7`. Second, we allow using incompatible wheels during resolution, as long as there's a compatible source distribution. So we still need to test for `requires-python` compatibility when selecting distributions. This could use more testing, but it feels like an area where `packse` would be more productive than writing PyPI tests. Closes https://github.com/astral-sh/puffin/issues/406.
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
use pep440_rs::Version;
|
||||
use pep508_rs::MarkerEnvironment;
|
||||
use puffin_interpreter::Interpreter;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PythonRequirement<'a> {
|
||||
/// The installed version of Python.
|
||||
installed: &'a 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.
|
||||
target: &'a Version,
|
||||
}
|
||||
|
||||
impl<'a> PythonRequirement<'a> {
|
||||
pub fn new(interpreter: &'a Interpreter, markers: &'a MarkerEnvironment) -> Self {
|
||||
Self {
|
||||
installed: interpreter.version(),
|
||||
target: &markers.python_version.version,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the installed version of Python.
|
||||
pub(crate) fn installed(&self) -> &'a Version {
|
||||
self.installed
|
||||
}
|
||||
|
||||
/// Return the target version of Python.
|
||||
pub(crate) fn target(&self) -> &'a Version {
|
||||
self.target
|
||||
}
|
||||
|
||||
/// Returns an iterator over the versions of Python to consider when resolving dependencies.
|
||||
pub(crate) fn versions(&self) -> impl Iterator<Item = &'a Version> {
|
||||
std::iter::once(self.installed).chain(std::iter::once(self.target))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user