Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GraalPy support #5141

Merged
merged 2 commits into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 131 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,137 @@ jobs:
run: |
.\uv.exe pip install anyio

integration-test-graalpy-linux:
needs: build-binary-linux
name: "integration test | graalpy on ubuntu"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: "graalpy24.0"

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

- name: "Prepare binary"
run: chmod +x ./uv

- name: Graalpy info
run: |
which graalpy
echo "GRAAL_PYTHONHOME=$(graalpy -c 'print(__graalpython__.home)')" >> $GITHUB_ENV
Copy link
Contributor Author

@timfel timfel Jul 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Workaround for 24.0 bug (fixed in 24.1, due out in September)


- name: "Create a virtual environment"
run: |
./uv venv -p $(which graalpy)

- name: "Check for executables"
run: |
check_in_bin() {
local executable_name=$1
local bin_path=".venv/bin"

if [[ -x "$bin_path/$executable_name" ]]; then
return 0
else
echo "Executable '$executable_name' not found in folder '$bin_path'."
return 1
fi
}

executables=("graalpy" "python3" "python")

all_found=true
for executable_name in "${executables[@]}"; do
check_in_bin "$executable_name" "$folder_path"
result=$?

if [[ $result -ne 0 ]]; then
all_found=false
fi
done

if ! $all_found; then
echo "One or more expected executables were not found."
exit 1
fi

- name: "Check version"
run: |
.venv/bin/graalpy --version
.venv/bin/python3 --version
.venv/bin/python --version

- name: "Check install"
run: |
./uv pip install anyio

integration-test-graalpy-windows:
needs: build-binary-windows
name: "integration test | graalpy on windows"
runs-on: windows-latest

steps:
- uses: timfel/setup-python@fc9bcb4a04f5b1ea7d678c2ca7ea1c479a2468d7
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR to setup-python is open: actions/setup-python#880

with:
python-version: "graalpy24.0"

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

- name: Graalpy info
run: Get-Command graalpy

- name: "Create a virtual environment"
run: |
$graalpy = (Get-Command graalpy).source
.\uv.exe venv -p $graalpy

- name: "Check for executables"
shell: python
run: |
import sys
from pathlib import Path

def binary_exist(binary):
binaries_path = Path(".venv\\Scripts")
if (binaries_path / binary).exists():
return True
print(f"Executable '{binary}' not found in folder '{binaries_path}'.")

all_found = True
expected_binaries = [
"graalpy.exe",
"python.exe",
"python3.exe",
]
for binary in expected_binaries:
if not binary_exist(binary):
all_found = False

if not all_found:
print("One or more expected executables were not found.")
sys.exit(1)

- name: "Check version"
run: |
& .venv\Scripts\graalpy.exe --version
& .venv\Scripts\python3.exe --version
& .venv\Scripts\python.exe --version

- name: "Check install"
env:
# Avoid debug build stack overflows.
UV_STACK_SIZE: 2000000 # 2 megabyte, double the default on windows
run: |
.\uv.exe pip install anyio

integration-test-github-actions:
needs: build-binary-linux
name: "integration test | github actions"
Expand Down
14 changes: 14 additions & 0 deletions crates/platform-tags/src/tags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ impl std::fmt::Display for Tags {
enum Implementation {
CPython { gil_disabled: bool },
PyPy,
GraalPy,
Pyston,
}

Expand All @@ -310,6 +311,8 @@ impl Implementation {
Self::CPython { .. } => format!("cp{}{}", python_version.0, python_version.1),
// Ex) `pp39`
Self::PyPy => format!("pp{}{}", python_version.0, python_version.1),
// Ex) `graalpy310`
Self::GraalPy => format!("graalpy{}{}", python_version.0, python_version.1),
// Ex) `pt38``
Self::Pyston => format!("pt{}{}", python_version.0, python_version.1),
}
Expand Down Expand Up @@ -342,6 +345,16 @@ impl Implementation {
implementation_version.0,
implementation_version.1
),
// Ex) `graalpy310_graalpy240_310_native
Self::GraalPy => format!(
"graalpy{}{}_graalpy{}{}_{}{}_native",
python_version.0,
python_version.1,
implementation_version.0,
implementation_version.1,
python_version.0,
python_version.1
),
// Ex) `pyston38-pyston_23`
Self::Pyston => format!(
"pyston{}{}-pyston_{}{}",
Expand All @@ -361,6 +374,7 @@ impl Implementation {
// Known and supported implementations.
"cpython" => Ok(Self::CPython { gil_disabled }),
"pypy" => Ok(Self::PyPy),
"graalpy" => Ok(Self::GraalPy),
"pyston" => Ok(Self::Pyston),
// Known but unsupported implementations.
"python" => Err(TagsError::UnsupportedImplementation(name.to_string())),
Expand Down
48 changes: 48 additions & 0 deletions crates/uv-python/src/discovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1640,6 +1640,14 @@ mod tests {
PythonRequest::parse("pp"),
PythonRequest::Implementation(ImplementationName::PyPy)
);
assert_eq!(
PythonRequest::parse("graalpy"),
PythonRequest::Implementation(ImplementationName::GraalPy)
);
assert_eq!(
PythonRequest::parse("gp"),
PythonRequest::Implementation(ImplementationName::GraalPy)
);
assert_eq!(
PythonRequest::parse("cp"),
PythonRequest::Implementation(ImplementationName::CPython)
Expand All @@ -1658,6 +1666,20 @@ mod tests {
VersionRequest::from_str("3.10").unwrap()
)
);
assert_eq!(
PythonRequest::parse("graalpy3.10"),
PythonRequest::ImplementationVersion(
ImplementationName::GraalPy,
VersionRequest::from_str("3.10").unwrap()
)
);
assert_eq!(
PythonRequest::parse("gp310"),
PythonRequest::ImplementationVersion(
ImplementationName::GraalPy,
VersionRequest::from_str("3.10").unwrap()
)
);
assert_eq!(
PythonRequest::parse("cp38"),
PythonRequest::ImplementationVersion(
Expand All @@ -1679,6 +1701,20 @@ mod tests {
VersionRequest::from_str("3.10").unwrap()
)
);
assert_eq!(
PythonRequest::parse("[email protected]"),
PythonRequest::ImplementationVersion(
ImplementationName::GraalPy,
VersionRequest::from_str("3.10").unwrap()
)
);
assert_eq!(
PythonRequest::parse("graalpy310"),
PythonRequest::ImplementationVersion(
ImplementationName::GraalPy,
VersionRequest::from_str("3.10").unwrap()
)
);

let tempdir = TempDir::new().unwrap();
assert_eq!(
Expand Down Expand Up @@ -1749,6 +1785,18 @@ mod tests {
.to_canonical_string(),
"[email protected]"
);
assert_eq!(
PythonRequest::Implementation(ImplementationName::GraalPy).to_canonical_string(),
"graalpy"
);
assert_eq!(
PythonRequest::ImplementationVersion(
ImplementationName::GraalPy,
VersionRequest::from_str("3.10").unwrap()
)
.to_canonical_string(),
"[email protected]"
);

let tempdir = TempDir::new().unwrap();
assert_eq!(
Expand Down
6 changes: 5 additions & 1 deletion crates/uv-python/src/implementation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub enum ImplementationName {
#[default]
CPython,
PyPy,
GraalPy,
}

#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
Expand All @@ -25,13 +26,14 @@ pub enum LenientImplementationName {

impl ImplementationName {
pub(crate) fn possible_names() -> impl Iterator<Item = &'static str> {
["cpython", "pypy", "cp", "pp"].into_iter()
["cpython", "pypy", "graalpy", "cp", "pp", "gp"].into_iter()
}

pub fn pretty(self) -> &'static str {
match self {
Self::CPython => "CPython",
Self::PyPy => "PyPy",
Self::GraalPy => "GraalPy",
}
}
}
Expand All @@ -50,6 +52,7 @@ impl From<&ImplementationName> for &'static str {
match v {
ImplementationName::CPython => "cpython",
ImplementationName::PyPy => "pypy",
ImplementationName::GraalPy => "graalpy",
}
}
}
Expand All @@ -73,6 +76,7 @@ impl FromStr for ImplementationName {
match s.to_ascii_lowercase().as_str() {
"cpython" | "cp" => Ok(Self::CPython),
"pypy" | "pp" => Ok(Self::PyPy),
"graalpy" | "gp" => Ok(Self::GraalPy),
_ => Err(Error::UnknownImplementation(s.to_string())),
}
}
Expand Down
Loading
Loading