Move architecture and operating system probing to Python (#2381)

The architecture of uv does not necessarily match that of the python
interpreter (#2326). In cross compiling/testing scenarios the operating
system can also mismatch. To solve this, we move arch and os detection
to python, vendoring the relevant pypa/packaging code, preventing
mismatches between what the python interpreter was compiled for and what
uv was compiled for.

To make the scripts more manageable, they are now a directory in a
tempdir and we run them with `python -m` . I've simplified the
pypa/packaging code since we're still building the tags in rust. A
`Platform` is now instantiated by querying the python interpreter for
its platform. The pypa/packaging files are copied verbatim for easier
updates except a `lru_cache()` python 3.7 backport.

Error handling is done by a `"result": "success|error"` field that allow
passing error details to rust:

```console
$ uv venv --no-cache
  × Can't use Python at `/home/konsti/projects/uv/.venv/bin/python3`
  ╰─▶ Unknown operation system `linux`
```

I've used the [maturin sysconfig
collection](855f6d2cb1/sysconfig)
as reference. I'm unsure how to test these changes across the wide
variety of platforms.

Fixes #2326
This commit is contained in:
konsti 2024-03-13 12:51:14 +01:00 committed by GitHub
parent e0ac5b4e84
commit 7964bfbb2b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
50 changed files with 1603 additions and 1473 deletions

View file

@ -17,6 +17,7 @@ use thiserror::Error;
pub use crate::cfg::PyVenvConfiguration;
pub use crate::find_python::{find_best_python, find_default_python, find_requested_python};
pub use crate::interpreter::Interpreter;
use crate::interpreter::InterpreterInfoError;
pub use crate::python_environment::PythonEnvironment;
pub use crate::python_version::PythonVersion;
pub use crate::virtualenv::Virtualenv;
@ -38,11 +39,11 @@ pub enum Error {
PythonNotFound,
#[error("Failed to locate a virtualenv or Conda environment (checked: `VIRTUAL_ENV`, `CONDA_PREFIX`, and `.venv`). Run `uv venv` to create a virtualenv.")]
VenvNotFound,
#[error("Failed to locate Python interpreter at: `{0}`")]
#[error("Failed to locate Python interpreter at `{0}`")]
RequestedPythonNotFound(String),
#[error(transparent)]
Io(#[from] io::Error),
#[error("Failed to query python interpreter `{interpreter}`")]
#[error("Failed to query Python interpreter at `{interpreter}`")]
PythonSubcommandLaunch {
interpreter: PathBuf,
#[source]
@ -56,7 +57,7 @@ pub enum Error {
)]
NoSuchPython(String),
#[cfg(unix)]
#[error("No Python {0} In `PATH`. Is Python {0} installed?")]
#[error("No Python {0} in `PATH`. Is Python {0} installed?")]
NoSuchPython(String),
#[error("Neither `python` nor `python3` are in `PATH`. Is Python installed?")]
NoPythonInstalledUnix,
@ -71,12 +72,16 @@ pub enum Error {
stdout: String,
stderr: String,
},
#[error("Python 2 or older is not supported. Please use Python 3 or newer.")]
Python2OrOlder,
#[error("Failed to write to cache")]
Encode(#[from] rmp_serde::encode::Error),
#[error("Broken virtualenv: Failed to parse pyvenv.cfg")]
Cfg(#[from] cfg::Error),
#[error("Error finding `{}` in PATH", _0.to_string_lossy())]
WhichError(OsString, #[source] which::Error),
#[error("Can't use Python at `{interpreter}`")]
QueryScript {
#[source]
err: InterpreterInfoError,
interpreter: PathBuf,
},
}