Skip to content

Commit

Permalink
Patch Python executable name for Windows free-threaded builds
Browse files Browse the repository at this point in the history
  • Loading branch information
zanieb committed Oct 17, 2024
1 parent 3fd69b4 commit b541c8b
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 1 deletion.
40 changes: 40 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,46 @@ jobs:
run: |
./uv pip install -v anyio
integration-test-free-threaded-windows:
timeout-minutes: 10
needs: build-binary-windows
name: "integration test | free-threaded on windows"
runs-on: windows-latest
env:
# Avoid debug build stack overflows.
UV_STACK_SIZE: 2000000

steps:
- name: "Download binary"
uses: actions/download-artifact@v4
with:
name: uv-windows-${{ github.sha }}

- name: "Install free-threaded Python via uv"
run: |
./uv python install -v 3.13t
- name: "Create a virtual environment"
run: |
./uv venv -p 3.13t --python-preference only-managed
- name: "Check version"
run: |
.venv/Scripts/python --version
- name: "Check is free-threaded"
run: |
.venv/Scripts/python -c "import sys; exit(1) if sys._is_gil_enabled() else exit(0)"
- name: "Check install"
run: |
./uv pip install -v anyio
- name: "Check uv run"
run: |
./uv run python -c ""
./uv run -p 3.13t python -c ""
integration-test-pypy-linux:
timeout-minutes: 10
needs: build-binary-linux
Expand Down
20 changes: 20 additions & 0 deletions crates/uv-fs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,26 @@ pub fn remove_symlink(path: impl AsRef<Path>) -> std::io::Result<()> {
fs_err::remove_file(path.as_ref())
}

/// Create a symlink at `dst` pointing to `src` or, on Windows, copy `src` to `dst`.
///
/// If working with a directory, use [`replace_symlink`] instead which will use a junction on
/// Windows.
pub fn symlink_copy_fallback_file(
src: impl AsRef<Path>,
dst: impl AsRef<Path>,
) -> std::io::Result<()> {
#[cfg(windows)]
{
fs_err::copy(src.as_ref(), dst.as_ref())?;
}
#[cfg(unix)]
{
std::os::unix::fs::symlink(src.as_ref(), dst.as_ref())?;
}

Ok(())
}

#[cfg(windows)]
pub fn remove_symlink(path: impl AsRef<Path>) -> std::io::Result<()> {
match junction::delete(dunce::simplified(path.as_ref())) {
Expand Down
1 change: 1 addition & 0 deletions crates/uv-python/src/installation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ impl PythonInstallation {

let installed = ManagedPythonInstallation::new(path)?;
installed.ensure_externally_managed()?;
installed.ensure_canonical_executables()?;

Ok(Self {
source: PythonSource::Managed,
Expand Down
32 changes: 31 additions & 1 deletion crates/uv-python/src/managed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::io::{self, Write};
use std::path::{Path, PathBuf};
use std::str::FromStr;
use thiserror::Error;
use tracing::warn;
use tracing::{debug, warn};

use uv_state::{StateBucket, StateStore};

Expand Down Expand Up @@ -323,6 +323,36 @@ impl ManagedPythonInstallation {
}
}

/// Ensure the environment contains the canonical Python executable names.
pub fn ensure_canonical_executables(&self) -> Result<(), Error> {
let python = self.executable();

// Workaround for python-build-standalone v20241016 which is missing the standard Python
// executable on Windows.
// See https://github.com/astral-sh/uv/issues/8298
if !python.try_exists()? {
match self.key.variant {
PythonVariant::Default => {}
PythonVariant::Freethreaded => {
let existing = self.python_dir().join(format!(
"python{}.{}t{}",
self.key.major,
self.key.minor,
std::env::consts::EXE_SUFFIX
));
debug!(
"Creating link {} -> {}",
python.user_display(),
existing.user_display()
);
uv_fs::symlink_copy_fallback_file(existing, python)?;
}
}
}

Ok(())
}

/// Ensure the environment is marked as externally managed with the
/// standard `EXTERNALLY-MANAGED` file.
pub fn ensure_externally_managed(&self) -> Result<(), Error> {
Expand Down
1 change: 1 addition & 0 deletions crates/uv/src/commands/python/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ pub(crate) async fn install(
// Ensure the installations have externally managed markers
let managed = ManagedPythonInstallation::new(path.clone())?;
managed.ensure_externally_managed()?;
managed.ensure_canonical_executables()?;
}
Err(err) => {
errors.push((key, err));
Expand Down

0 comments on commit b541c8b

Please sign in to comment.