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](https://github.com/PyO3/maturin/tree/855f6d2cb1fb8fb43c2bb9e500ab0e5e84bd3140/sysconfig) as reference. I'm unsure how to test these changes across the wide variety of platforms. Fixes #2326
This commit is contained in:
@@ -3,7 +3,6 @@ use std::path::{Path, PathBuf};
|
||||
|
||||
use tracing::debug;
|
||||
|
||||
use platform_host::Platform;
|
||||
use uv_cache::Cache;
|
||||
use uv_fs::{LockedFile, Simplified};
|
||||
|
||||
@@ -19,13 +18,13 @@ pub struct PythonEnvironment {
|
||||
|
||||
impl PythonEnvironment {
|
||||
/// Create a [`PythonEnvironment`] for an existing virtual environment.
|
||||
pub fn from_virtualenv(platform: Platform, cache: &Cache) -> Result<Self, Error> {
|
||||
pub fn from_virtualenv(cache: &Cache) -> Result<Self, Error> {
|
||||
let Some(venv) = detect_virtual_env()? else {
|
||||
return Err(Error::VenvNotFound);
|
||||
};
|
||||
let venv = fs_err::canonicalize(venv)?;
|
||||
let executable = detect_python_executable(&venv);
|
||||
let interpreter = Interpreter::query(&executable, platform, cache)?;
|
||||
let interpreter = Interpreter::query(&executable, cache)?;
|
||||
|
||||
debug_assert!(
|
||||
interpreter.base_prefix() == interpreter.base_exec_prefix(),
|
||||
@@ -41,12 +40,8 @@ impl PythonEnvironment {
|
||||
}
|
||||
|
||||
/// Create a [`PythonEnvironment`] for a Python interpreter specifier (e.g., a path or a binary name).
|
||||
pub fn from_requested_python(
|
||||
python: &str,
|
||||
platform: &Platform,
|
||||
cache: &Cache,
|
||||
) -> Result<Self, Error> {
|
||||
let Some(interpreter) = find_requested_python(python, platform, cache)? else {
|
||||
pub fn from_requested_python(python: &str, cache: &Cache) -> Result<Self, Error> {
|
||||
let Some(interpreter) = find_requested_python(python, cache)? else {
|
||||
return Err(Error::RequestedPythonNotFound(python.to_string()));
|
||||
};
|
||||
Ok(Self {
|
||||
@@ -56,8 +51,8 @@ impl PythonEnvironment {
|
||||
}
|
||||
|
||||
/// Create a [`PythonEnvironment`] for the default Python interpreter.
|
||||
pub fn from_default_python(platform: &Platform, cache: &Cache) -> Result<Self, Error> {
|
||||
let interpreter = find_default_python(platform, cache)?;
|
||||
pub fn from_default_python(cache: &Cache) -> Result<Self, Error> {
|
||||
let interpreter = find_default_python(cache)?;
|
||||
Ok(Self {
|
||||
root: interpreter.prefix().to_path_buf(),
|
||||
interpreter,
|
||||
|
||||
Reference in New Issue
Block a user