mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 21:35:00 +00:00
Run the test suite on windows in CI (#1262)
Run `cargo test` on windows in CI, pulling the switch on tier 1 windows support. These changes make the bootstrap script virtually required for running the tests. This gives us consistency between and CI, but it also locks our tests to python-build-standalone and an articificial `PATH`. I've deleted the shell bootstrap script in favor of only the python one, which also runs on windows. I've left the (sym)link creation of the bootstrap in place, even though it is not used by the tests anymore. I've reactivated the three tests that would previously stack overflow by doubling their stack sizes. The stack overflows only happen in debug mode, so this is neither a user facing problem nor an actual problem with our code and this workaround seems better than optimizing our code for case that the (release) compiler can optimize much better for. The handling of patch versions will be fixed in a follow-up PR. Closes #1160 Closes #1161 --------- Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
This commit is contained in:
parent
96276d9e3e
commit
1dc9904f8c
12 changed files with 228 additions and 357 deletions
|
@ -1,137 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
#
|
||||
# Download required Python versions and install to `bin`
|
||||
# Uses prebuilt Python distributions from indygreg/python-build-standalone
|
||||
#
|
||||
# Requirements
|
||||
#
|
||||
# macOS
|
||||
#
|
||||
# brew install zstd jq coreutils
|
||||
#
|
||||
# Ubuntu
|
||||
#
|
||||
# apt install zstd jq
|
||||
#
|
||||
# Arch Linux
|
||||
#
|
||||
# pacman -S zstd jq libxcrypt-compat
|
||||
#
|
||||
# Windows
|
||||
#
|
||||
# winget install jqlang.jq
|
||||
#
|
||||
# Usage
|
||||
#
|
||||
# ./scripts/bootstrap/install.sh
|
||||
#
|
||||
# The Python versions are installed from `.python_versions`.
|
||||
# Python versions are linked in-order such that the _last_ defined version will be the default.
|
||||
#
|
||||
# Version metadata can be updated with `fetch-version-metadata.py` which requires Python 3.12
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Convenience function for displaying URLs
|
||||
function urldecode() { : "${*//+/ }"; echo -e "${_//%/\\x}"; }
|
||||
|
||||
# Convenience function for checking that a command exists.
|
||||
requires() {
|
||||
cmd="$1"
|
||||
if ! command -v "$cmd" > /dev/null 2>&1; then
|
||||
echo "DEPENDENCY MISSING: $(basename $0) requires $cmd to be installed" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
requires jq
|
||||
requires zstd
|
||||
|
||||
# Setup some file paths
|
||||
this_dir=$(realpath "$(dirname "$0")")
|
||||
root_dir=$(dirname "$(dirname "$this_dir")")
|
||||
bin_dir="$root_dir/bin"
|
||||
install_dir="$bin_dir/versions"
|
||||
versions_file="$root_dir/.python-versions"
|
||||
versions_metadata="$this_dir/versions.json"
|
||||
|
||||
# Determine system metadata
|
||||
os=$(uname -s | tr '[:upper:]' '[:lower:]')
|
||||
arch=$(uname -m)
|
||||
interpreter='cpython'
|
||||
|
||||
# On macOS, we need a newer version of `realpath` for `--relative-to` support
|
||||
realpath="$(which grealpath || which realpath)"
|
||||
|
||||
|
||||
# Utility for linking executables for the version being installed
|
||||
# We need to update executables even if the version is already downloaded and extracted
|
||||
# to ensure that changes to the precedence of versions are respected
|
||||
link_executables() {
|
||||
# Use relative paths for links so if the bin is moved they don't break
|
||||
local link=$($realpath --relative-to="$bin_dir" "$install_key/install/bin/python3")
|
||||
local minor=$(jq --arg key "$key" '.[$key] | .minor' -r < "$versions_metadata")
|
||||
|
||||
# Link as all version tuples, later versions in the file will take precedence
|
||||
ln -sf "./$link" "$bin_dir/python$version"
|
||||
ln -sf "./$link" "$bin_dir/python3.$minor"
|
||||
ln -sf "./$link" "$bin_dir/python3"
|
||||
ln -sf "./$link" "$bin_dir/python"
|
||||
}
|
||||
|
||||
# Read requested versions into an array
|
||||
versions=()
|
||||
while IFS= read -r version; do
|
||||
versions+=("$version")
|
||||
done < "$versions_file"
|
||||
|
||||
# Install each version
|
||||
for version in "${versions[@]}"; do
|
||||
key="$interpreter-$version-$os-$arch"
|
||||
install_key="$install_dir/$interpreter@$version"
|
||||
echo "Installing $key"
|
||||
|
||||
if [ -d "$install_key" ]; then
|
||||
echo "Already available, skipping download"
|
||||
link_executables
|
||||
echo "Updated executables for python$version"
|
||||
continue
|
||||
fi
|
||||
|
||||
url=$(jq --arg key "$key" '.[$key] | .url' -r < "$versions_metadata")
|
||||
|
||||
if [ "$url" == 'null' ]; then
|
||||
echo "No matching download for $key"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
filename=$(basename "$url")
|
||||
echo "Downloading $(urldecode "$filename")"
|
||||
curl -L --progress-bar -o "$filename" "$url" --output-dir "$this_dir"
|
||||
|
||||
expected_sha=$(jq --arg key "$key" '.[$key] | .sha256' -r < "$versions_metadata")
|
||||
if [ "$expected_sha" == 'null' ]; then
|
||||
echo "WARNING: no checksum for $key"
|
||||
else
|
||||
echo -n "Verifying checksum..."
|
||||
echo "$expected_sha $this_dir/$filename" | sha256sum -c --quiet
|
||||
echo " OK"
|
||||
fi
|
||||
|
||||
rm -rf "$install_key"
|
||||
echo "Extracting to $($realpath --relative-to="$root_dir" "$install_key")"
|
||||
mkdir -p "$install_key"
|
||||
zstd -d "$this_dir/$filename" --stdout | tar -x -C "$install_key"
|
||||
|
||||
# Setup the installation
|
||||
mv "$install_key/python/"* "$install_key"
|
||||
|
||||
link_executables
|
||||
echo "Installed executables for python$version"
|
||||
|
||||
# Cleanup
|
||||
rmdir "$install_key/python/"
|
||||
rm "$this_dir/$filename"
|
||||
done
|
||||
|
||||
echo "Done!"
|
|
@ -6,52 +6,17 @@
|
|||
#![cfg(all(feature = "python", feature = "pypi"))]
|
||||
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
use anyhow::Result;
|
||||
use assert_cmd::assert::OutputAssertExt;
|
||||
use assert_fs::fixture::{FileWriteStr, PathChild};
|
||||
#[cfg(unix)]
|
||||
use fs_err::os::unix::fs::symlink as symlink_file;
|
||||
#[cfg(windows)]
|
||||
use fs_err::os::windows::fs::symlink_file;
|
||||
use predicates::prelude::predicate;
|
||||
|
||||
use common::{bootstrapped_pythons, get_bin, puffin_snapshot, TestContext, INSTA_FILTERS};
|
||||
use puffin_interpreter::find_requested_python;
|
||||
use common::{create_bin_with_executables, get_bin, puffin_snapshot, TestContext, INSTA_FILTERS};
|
||||
|
||||
mod common;
|
||||
|
||||
/// Create a directory with the requested Python binaries available.
|
||||
pub(crate) fn create_bin_with_executables(
|
||||
temp_dir: &assert_fs::TempDir,
|
||||
python_versions: &[&str],
|
||||
) -> Result<PathBuf> {
|
||||
if let Some(bootstrapped_pythons) = bootstrapped_pythons() {
|
||||
let selected_pythons = bootstrapped_pythons.into_iter().filter(|path| {
|
||||
python_versions.iter().any(|python_version| {
|
||||
// Good enough since we control the directory
|
||||
path.to_str()
|
||||
.unwrap()
|
||||
.contains(&format!("@{python_version}"))
|
||||
})
|
||||
});
|
||||
return Ok(env::join_paths(selected_pythons)?.into());
|
||||
}
|
||||
|
||||
let bin = temp_dir.child("bin");
|
||||
fs_err::create_dir(&bin)?;
|
||||
for request in python_versions {
|
||||
let executable = find_requested_python(request)?;
|
||||
let name = executable
|
||||
.file_name()
|
||||
.expect("Discovered executable must have a filename");
|
||||
symlink_file(&executable, bin.child(name))?;
|
||||
}
|
||||
Ok(bin.canonicalize()?)
|
||||
}
|
||||
|
||||
/// Provision python binaries and return a `pip compile` command with options shared across all scenarios.
|
||||
fn command(context: &TestContext, python_versions: &[&str]) -> Command {
|
||||
let bin = create_bin_with_executables(&context.temp_dir, python_versions)
|
||||
|
@ -67,7 +32,7 @@ fn command(context: &TestContext, python_versions: &[&str]) -> Command {
|
|||
.arg(context.cache_dir.path())
|
||||
.env("VIRTUAL_ENV", context.venv.as_os_str())
|
||||
.env("PUFFIN_NO_WRAP", "1")
|
||||
.env("PUFFIN_PYTHON_PATH", bin)
|
||||
.env("PUFFIN_TEST_PYTHON_PATH", bin)
|
||||
.current_dir(&context.temp_dir);
|
||||
command
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue