Allow selection of pyodide interpreters with "pyodide" (#15256)
This commit is contained in:
@@ -17,7 +17,7 @@ use uv_configuration::{Preview, PreviewFeatures};
|
||||
use windows_sys::Win32::Storage::FileSystem::FILE_ATTRIBUTE_REPARSE_POINT;
|
||||
|
||||
use uv_fs::{LockedFile, Simplified, replace_symlink, symlink_or_copy_file};
|
||||
use uv_platform::Error as PlatformError;
|
||||
use uv_platform::{Error as PlatformError, Os};
|
||||
use uv_platform::{LibcDetectionError, Platform};
|
||||
use uv_state::{StateBucket, StateStore};
|
||||
use uv_static::EnvVars;
|
||||
@@ -358,8 +358,6 @@ impl ManagedPythonInstallation {
|
||||
/// If windowed is true, `pythonw.exe` is selected over `python.exe` on windows, with no changes
|
||||
/// on non-windows.
|
||||
pub fn executable(&self, windowed: bool) -> PathBuf {
|
||||
let implementation = self.implementation().executable_name();
|
||||
|
||||
let version = match self.implementation() {
|
||||
ImplementationName::CPython => {
|
||||
if cfg!(unix) {
|
||||
@@ -370,12 +368,14 @@ impl ManagedPythonInstallation {
|
||||
}
|
||||
// PyPy uses a full version number, even on Windows.
|
||||
ImplementationName::PyPy => format!("{}.{}", self.key.major, self.key.minor),
|
||||
// Pyodide and GraalPy do not have a version suffix.
|
||||
ImplementationName::Pyodide => String::new(),
|
||||
ImplementationName::GraalPy => String::new(),
|
||||
};
|
||||
|
||||
// On Windows, the executable is just `python.exe` even for alternative variants
|
||||
// GraalPy always uses `graalpy.exe` as the main executable
|
||||
let variant = if *self.implementation() == ImplementationName::GraalPy {
|
||||
let variant = if self.implementation() == ImplementationName::GraalPy {
|
||||
""
|
||||
} else if cfg!(unix) {
|
||||
self.key.variant.suffix()
|
||||
@@ -388,13 +388,15 @@ impl ManagedPythonInstallation {
|
||||
|
||||
let name = format!(
|
||||
"{implementation}{version}{variant}{exe}",
|
||||
implementation = self.implementation().executable_name(),
|
||||
exe = std::env::consts::EXE_SUFFIX
|
||||
);
|
||||
|
||||
let executable = executable_path_from_base(
|
||||
self.python_dir().as_path(),
|
||||
&name,
|
||||
&LenientImplementationName::from(*self.implementation()),
|
||||
&LenientImplementationName::from(self.implementation()),
|
||||
*self.key.os(),
|
||||
);
|
||||
|
||||
// Workaround for python-build-standalone v20241016 which is missing the standard
|
||||
@@ -431,8 +433,8 @@ impl ManagedPythonInstallation {
|
||||
self.key.version()
|
||||
}
|
||||
|
||||
pub fn implementation(&self) -> &ImplementationName {
|
||||
match self.key.implementation() {
|
||||
pub fn implementation(&self) -> ImplementationName {
|
||||
match self.key.implementation().into_owned() {
|
||||
LenientImplementationName::Known(implementation) => implementation,
|
||||
LenientImplementationName::Unknown(_) => {
|
||||
panic!("Managed Python installations should have a known implementation")
|
||||
@@ -466,10 +468,10 @@ impl ManagedPythonInstallation {
|
||||
.file_name()
|
||||
.is_some_and(|filename| filename.to_string_lossy() == *name),
|
||||
PythonRequest::Implementation(implementation) => {
|
||||
implementation == self.implementation()
|
||||
*implementation == self.implementation()
|
||||
}
|
||||
PythonRequest::ImplementationVersion(implementation, version) => {
|
||||
implementation == self.implementation() && version.matches_version(&self.version())
|
||||
*implementation == self.implementation() && version.matches_version(&self.version())
|
||||
}
|
||||
PythonRequest::Version(version) => version.matches_version(&self.version()),
|
||||
PythonRequest::Key(request) => request.satisfied_by_key(self.key()),
|
||||
@@ -579,7 +581,7 @@ impl ManagedPythonInstallation {
|
||||
// sysconfig directly
|
||||
return Ok(());
|
||||
}
|
||||
if *self.implementation() == ImplementationName::CPython {
|
||||
if self.implementation() == ImplementationName::CPython {
|
||||
sysconfig::update_sysconfig(
|
||||
self.path(),
|
||||
self.key.major,
|
||||
@@ -600,7 +602,7 @@ impl ManagedPythonInstallation {
|
||||
pub fn ensure_dylib_patched(&self) -> Result<(), macos_dylib::Error> {
|
||||
if cfg!(target_os = "macos") {
|
||||
if self.key().os().is_like_darwin() {
|
||||
if *self.implementation() == ImplementationName::CPython {
|
||||
if self.implementation() == ImplementationName::CPython {
|
||||
let dylib_path = self.python_dir().join("lib").join(format!(
|
||||
"{}python{}{}{}",
|
||||
std::env::consts::DLL_PREFIX,
|
||||
@@ -716,7 +718,7 @@ impl PythonMinorVersionLink {
|
||||
) -> Option<Self> {
|
||||
let implementation = key.implementation();
|
||||
if !matches!(
|
||||
implementation,
|
||||
implementation.as_ref(),
|
||||
LenientImplementationName::Known(ImplementationName::CPython)
|
||||
) {
|
||||
// We don't currently support transparent upgrades for PyPy or GraalPy.
|
||||
@@ -755,7 +757,8 @@ impl PythonMinorVersionLink {
|
||||
let symlink_executable = executable_path_from_base(
|
||||
symlink_directory.as_path(),
|
||||
&executable_name.to_string_lossy(),
|
||||
implementation,
|
||||
&implementation,
|
||||
*key.os(),
|
||||
);
|
||||
let minor_version_link = Self {
|
||||
symlink_directory,
|
||||
@@ -839,18 +842,28 @@ fn executable_path_from_base(
|
||||
base: &Path,
|
||||
executable_name: &str,
|
||||
implementation: &LenientImplementationName,
|
||||
os: Os,
|
||||
) -> PathBuf {
|
||||
if cfg!(unix)
|
||||
if matches!(
|
||||
implementation,
|
||||
&LenientImplementationName::Known(ImplementationName::GraalPy)
|
||||
) {
|
||||
// GraalPy is always in `bin/` regardless of the os
|
||||
base.join("bin").join(executable_name)
|
||||
} else if os.is_emscripten()
|
||||
|| matches!(
|
||||
implementation,
|
||||
&LenientImplementationName::Known(ImplementationName::GraalPy)
|
||||
&LenientImplementationName::Known(ImplementationName::Pyodide)
|
||||
)
|
||||
{
|
||||
base.join("bin").join(executable_name)
|
||||
} else if cfg!(windows) {
|
||||
// Emscripten's canonical executable is in the base directory
|
||||
base.join(executable_name)
|
||||
} else if os.is_windows() {
|
||||
// On Windows, the executable is in the base directory
|
||||
base.join(executable_name)
|
||||
} else {
|
||||
unimplemented!("Only Windows and Unix systems are supported.")
|
||||
// On Unix, the executable is in `bin/`
|
||||
base.join("bin").join(executable_name)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user