From 9a38e709bb43bdd8e43aa7c2fce603ed30ed469f Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Mon, 25 Mar 2024 19:54:52 +0100 Subject: [PATCH] Basic GraalPy Support (#3247) * graalpy: recognize graalpy implementation when building * graalpy: global Ellipse, None, NotImplemented, True, and False are only available as pointers * graalpy: PyObject struct is opaque, use functions for everything * graalpy: missing many of the same functions as pypy * graalpy: do not have 128bit conversion functions * graalpy: add functions for datetime accessor macros * graalpy: add implementations for list macro functions * graalpy: skip tuple macros * graalpy: always use extern Py_CompileString function * graalpy: disable assertion that does not apply to graalpy * graalpy: floatobject structure is opaque on graalpy * graalpy: ignore gc dependent test * graalpy: add CI config * graalpy: run rust fmt * graalpy: add changelog entry * graalpy: discover interpreter on PATH * graalpy: interpreter id is not applicable to graalpy (just like pypy) * graalpy: skip tests that cannot work on GraalPy * graalpy: fix constructing normalized Err instances Co-authored-by: David Hewitt * graalpy: correct capi library name, but skip rust tests due to missing symbols * graalpy: no support for C extensions on windows in latest release * graalpy: declare support versions * graalpy: frame, code, method, and function objects access from C API is mostly missing * graalpy: take care only to expose C structure that GraalPy allocates * graalpy: Bail out if graalpy version is less than what we support --------- Co-authored-by: David Hewitt --- .github/workflows/build.yml | 15 +- .github/workflows/ci.yml | 1 + README.md | 2 +- newsfragments/3247.added.md | 1 + pyo3-build-config/src/impl_.rs | 69 +++++++- pyo3-build-config/src/import_lib.rs | 5 +- pyo3-build-config/src/lib.rs | 1 + pyo3-ffi/build.rs | 29 ++++ pyo3-ffi/src/abstract_.rs | 1 + pyo3-ffi/src/boolobject.rs | 18 ++- pyo3-ffi/src/bytearrayobject.rs | 4 +- pyo3-ffi/src/complexobject.rs | 1 + pyo3-ffi/src/cpython/abstract_.rs | 39 ++--- pyo3-ffi/src/cpython/bytesobject.rs | 6 +- pyo3-ffi/src/cpython/code.rs | 24 +-- pyo3-ffi/src/cpython/compile.rs | 4 +- pyo3-ffi/src/cpython/dictobject.rs | 1 + pyo3-ffi/src/cpython/floatobject.rs | 8 +- pyo3-ffi/src/cpython/frameobject.rs | 15 +- pyo3-ffi/src/cpython/funcobject.rs | 9 +- pyo3-ffi/src/cpython/genobject.rs | 4 +- pyo3-ffi/src/cpython/listobject.rs | 8 +- pyo3-ffi/src/cpython/methodobject.rs | 6 + pyo3-ffi/src/cpython/mod.rs | 2 +- pyo3-ffi/src/cpython/object.rs | 2 + pyo3-ffi/src/cpython/objimpl.rs | 10 +- pyo3-ffi/src/cpython/pyerrors.rs | 42 ++--- pyo3-ffi/src/cpython/pymem.rs | 8 +- pyo3-ffi/src/cpython/pythonrun.rs | 43 ++--- pyo3-ffi/src/cpython/tupleobject.rs | 5 +- pyo3-ffi/src/cpython/unicodeobject.rs | 51 ++++-- pyo3-ffi/src/cpython/weakrefobject.rs | 2 +- pyo3-ffi/src/datetime.rs | 224 ++++++++++++++++++++------ pyo3-ffi/src/dictobject.rs | 2 +- pyo3-ffi/src/listobject.rs | 8 +- pyo3-ffi/src/methodobject.rs | 2 +- pyo3-ffi/src/object.rs | 55 ++++++- pyo3-ffi/src/pyframe.rs | 2 + pyo3-ffi/src/pyhash.rs | 12 +- pyo3-ffi/src/pythonrun.rs | 4 +- pyo3-ffi/src/setobject.rs | 10 +- pyo3-ffi/src/sliceobject.rs | 12 +- pyo3-ffi/src/structseq.rs | 4 +- pyo3-ffi/src/weakrefobject.rs | 4 +- pytests/tests/test_awaitable.py | 9 ++ pytests/tests/test_misc.py | 4 +- pytests/tests/test_objstore.py | 5 + src/conversions/std/num.rs | 4 +- src/err/mod.rs | 13 +- src/exceptions.rs | 16 +- src/gil.rs | 8 +- src/impl_/pymodule.rs | 22 ++- src/impl_/trampoline.rs | 6 +- src/lib.rs | 2 +- src/macros.rs | 2 +- src/marker.rs | 2 +- src/types/any.rs | 11 +- src/types/complex.rs | 10 +- src/types/datetime.rs | 32 ++++ src/types/dict.rs | 38 ++--- src/types/frozenset.rs | 4 +- src/types/mod.rs | 16 +- src/types/sequence.rs | 4 +- src/types/set.rs | 4 +- src/types/string.rs | 8 +- src/types/tuple.rs | 44 ++--- 66 files changed, 731 insertions(+), 308 deletions(-) create mode 100644 newsfragments/3247.added.md diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 25c8014f..d2f74401 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,6 +24,7 @@ jobs: build: continue-on-error: ${{ endsWith(inputs.python-version, '-dev') || contains(fromJSON('["3.7", "pypy3.7"]'), inputs.python-version) || inputs.rust == 'beta' || inputs.rust == 'nightly' }} runs-on: ${{ inputs.os }} + if: ${{ !(startsWith(inputs.python-version, 'graalpy') && startsWith(inputs.os, 'windows')) }} steps: - uses: actions/checkout@v4 @@ -65,6 +66,7 @@ jobs: run: nox -s docs - name: Build (no features) + if: ${{ !startsWith(inputs.python-version, 'graalpy') }} run: cargo build --lib --tests --no-default-features # --no-default-features when used with `cargo build/test -p` doesn't seem to work! @@ -74,7 +76,7 @@ jobs: cargo build --no-default-features # Run tests (except on PyPy, because no embedding API). - - if: ${{ !startsWith(inputs.python-version, 'pypy') }} + - if: ${{ !startsWith(inputs.python-version, 'pypy') && !startsWith(inputs.python-version, 'graalpy') }} name: Test (no features) run: cargo test --no-default-features --lib --tests @@ -85,6 +87,7 @@ jobs: cargo test --no-default-features - name: Build (all additive features) + if: ${{ !startsWith(inputs.python-version, 'graalpy') }} run: cargo build --lib --tests --no-default-features --features "full ${{ inputs.extra-features }}" - if: ${{ startsWith(inputs.python-version, 'pypy') }} @@ -92,17 +95,17 @@ jobs: run: cargo build --lib --tests --no-default-features --features "abi3-py37 full ${{ inputs.extra-features }}" # Run tests (except on PyPy, because no embedding API). - - if: ${{ !startsWith(inputs.python-version, 'pypy') }} + - if: ${{ !startsWith(inputs.python-version, 'pypy') && !startsWith(inputs.python-version, 'graalpy') }} name: Test run: cargo test --no-default-features --features "full ${{ inputs.extra-features }}" # Run tests again, but in abi3 mode - - if: ${{ !startsWith(inputs.python-version, 'pypy') }} + - if: ${{ !startsWith(inputs.python-version, 'pypy') && !startsWith(inputs.python-version, 'graalpy') }} name: Test (abi3) run: cargo test --no-default-features --features "abi3 full ${{ inputs.extra-features }}" # Run tests again, for abi3-py37 (the minimal Python version) - - if: ${{ (!startsWith(inputs.python-version, 'pypy')) && (inputs.python-version != '3.7') }} + - if: ${{ (!startsWith(inputs.python-version, 'pypy') && !startsWith(inputs.python-version, 'graalpy')) && (inputs.python-version != '3.7') }} name: Test (abi3-py37) run: cargo test --no-default-features --features "abi3-py37 full ${{ inputs.extra-features }}" @@ -120,7 +123,7 @@ jobs: - uses: dorny/paths-filter@v3 # pypy 3.7 and 3.8 are not PEP 3123 compliant so fail checks here - if: ${{ inputs.rust == 'stable' && inputs.python-version != 'pypy3.7' && inputs.python-version != 'pypy3.8' }} + if: ${{ inputs.rust == 'stable' && inputs.python-version != 'pypy3.7' && inputs.python-version != 'pypy3.8' && !startsWith(inputs.python-version, 'graalpy') }} id: ffi-changes with: base: ${{ github.event.pull_request.base.ref || github.event.merge_group.base_ref }} @@ -135,7 +138,7 @@ jobs: - name: Run pyo3-ffi-check # pypy 3.7 and 3.8 are not PEP 3123 compliant so fail checks here, nor # is pypy 3.9 on windows - if: ${{ endsWith(inputs.python-version, '-dev') || (steps.ffi-changes.outputs.changed == 'true' && inputs.rust == 'stable' && inputs.python-version != 'pypy3.7' && inputs.python-version != 'pypy3.8' && !(inputs.python-version == 'pypy3.9' && contains(inputs.os, 'windows'))) }} + if: ${{ endsWith(inputs.python-version, '-dev') || (steps.ffi-changes.outputs.changed == 'true' && inputs.rust == 'stable' && inputs.python-version != 'pypy3.7' && inputs.python-version != 'pypy3.8' && !startsWith(inputs.python-version, 'graalpy') && !(inputs.python-version == 'pypy3.9' && contains(inputs.os, 'windows'))) }} run: nox -s ffi-check env: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5ee0776e..63f6c31a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -228,6 +228,7 @@ jobs: "pypy3.8", "pypy3.9", "pypy3.10", + "graalpy24.0", ] platform: [ diff --git a/README.md b/README.md index c11754c3..461e5661 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ ## Usage PyO3 supports the following software versions: - - Python 3.7 and up (CPython and PyPy) + - Python 3.7 and up (CPython, PyPy, and GraalPy) - Rust 1.56 and up You can use PyO3 to write a native Python module in Rust, or to embed Python in a Rust binary. The following sections explain each of these in turn. diff --git a/newsfragments/3247.added.md b/newsfragments/3247.added.md new file mode 100644 index 00000000..dd2641c3 --- /dev/null +++ b/newsfragments/3247.added.md @@ -0,0 +1 @@ +Added support for running PyO3 extensions on GraalPy. diff --git a/pyo3-build-config/src/impl_.rs b/pyo3-build-config/src/impl_.rs index 7f02f744..d5373db9 100644 --- a/pyo3-build-config/src/impl_.rs +++ b/pyo3-build-config/src/impl_.rs @@ -32,6 +32,12 @@ use crate::{ /// Minimum Python version PyO3 supports. const MINIMUM_SUPPORTED_VERSION: PythonVersion = PythonVersion { major: 3, minor: 7 }; +/// GraalPy may implement the same CPython version over multiple releases. +const MINIMUM_SUPPORTED_VERSION_GRAALPY: PythonVersion = PythonVersion { + major: 24, + minor: 0, +}; + /// Maximum Python version that can be used as minimum required Python version with abi3. const ABI3_MAX_MINOR: u8 = 12; @@ -173,6 +179,11 @@ impl InterpreterConfig { See https://foss.heptapod.net/pypy/pypy/-/issues/3397 for more information." )); } + } else if self.implementation.is_graalpy() { + println!("cargo:rustc-cfg=GraalPy"); + if self.abi3 { + warn!("GraalPy does not support abi3 so the build artifacts will be version-specific."); + } } else if self.abi3 { out.push("cargo:rustc-cfg=Py_LIMITED_API".to_owned()); } @@ -197,6 +208,12 @@ import sys from sysconfig import get_config_var, get_platform PYPY = platform.python_implementation() == "PyPy" +GRAALPY = platform.python_implementation() == "GraalVM" + +if GRAALPY: + graalpy_ver = map(int, __graalpython__.get_graalvm_version().split('.')); + print("graalpy_major", next(graalpy_ver)) + print("graalpy_minor", next(graalpy_ver)) # sys.base_prefix is missing on Python versions older than 3.3; this allows the script to continue # so that the version mismatch can be reported in a nicer way later. @@ -226,7 +243,7 @@ SHARED = bool(get_config_var("Py_ENABLE_SHARED")) print("implementation", platform.python_implementation()) print("version_major", sys.version_info[0]) print("version_minor", sys.version_info[1]) -print("shared", PYPY or ANACONDA or WINDOWS or FRAMEWORK or SHARED) +print("shared", PYPY or GRAALPY or ANACONDA or WINDOWS or FRAMEWORK or SHARED) print_if_set("ld_version", get_config_var("LDVERSION")) print_if_set("libdir", get_config_var("LIBDIR")) print_if_set("base_prefix", base_prefix) @@ -244,6 +261,23 @@ print("ext_suffix", get_config_var("EXT_SUFFIX")) interpreter.as_ref().display() ); + if let Some(value) = map.get("graalpy_major") { + let graalpy_version = PythonVersion { + major: value + .parse() + .context("failed to parse GraalPy major version")?, + minor: map["graalpy_minor"] + .parse() + .context("failed to parse GraalPy minor version")?, + }; + ensure!( + graalpy_version >= MINIMUM_SUPPORTED_VERSION_GRAALPY, + "At least GraalPy version {} needed, got {}", + MINIMUM_SUPPORTED_VERSION_GRAALPY, + graalpy_version + ); + }; + let shared = map["shared"].as_str() == "True"; let version = PythonVersion { @@ -588,7 +622,7 @@ print("ext_suffix", get_config_var("EXT_SUFFIX")) /// Lowers the configured version to the abi3 version, if set. fn fixup_for_abi3_version(&mut self, abi3_version: Option) -> Result<()> { // PyPy doesn't support abi3; don't adjust the version - if self.implementation.is_pypy() { + if self.implementation.is_pypy() || self.implementation.is_graalpy() { return Ok(()); } @@ -647,6 +681,7 @@ impl FromStr for PythonVersion { pub enum PythonImplementation { CPython, PyPy, + GraalPy, } impl PythonImplementation { @@ -655,12 +690,19 @@ impl PythonImplementation { self == PythonImplementation::PyPy } + #[doc(hidden)] + pub fn is_graalpy(self) -> bool { + self == PythonImplementation::GraalPy + } + #[doc(hidden)] pub fn from_soabi(soabi: &str) -> Result { if soabi.starts_with("pypy") { Ok(PythonImplementation::PyPy) } else if soabi.starts_with("cpython") { Ok(PythonImplementation::CPython) + } else if soabi.starts_with("graalpy") { + Ok(PythonImplementation::GraalPy) } else { bail!("unsupported Python interpreter"); } @@ -672,6 +714,7 @@ impl Display for PythonImplementation { match self { PythonImplementation::CPython => write!(f, "CPython"), PythonImplementation::PyPy => write!(f, "PyPy"), + PythonImplementation::GraalPy => write!(f, "GraalVM"), } } } @@ -682,6 +725,7 @@ impl FromStr for PythonImplementation { match s { "CPython" => Ok(PythonImplementation::CPython), "PyPy" => Ok(PythonImplementation::PyPy), + "GraalVM" => Ok(PythonImplementation::GraalPy), _ => bail!("unknown interpreter: {}", s), } } @@ -760,7 +804,7 @@ pub struct CrossCompileConfig { /// The version of the Python library to link against. version: Option, - /// The target Python implementation hint (CPython or PyPy) + /// The target Python implementation hint (CPython, PyPy, GraalPy, ...) implementation: Option, /// The compile target triple (e.g. aarch64-unknown-linux-gnu) @@ -1264,6 +1308,15 @@ fn is_pypy_lib_dir(path: &str, v: &Option) -> bool { path == "lib_pypy" || path.starts_with(&pypy_version_pat) } +fn is_graalpy_lib_dir(path: &str, v: &Option) -> bool { + let graalpy_version_pat = if let Some(v) = v { + format!("graalpy{}", v) + } else { + "graalpy2".into() + }; + path == "lib_graalpython" || path.starts_with(&graalpy_version_pat) +} + fn is_cpython_lib_dir(path: &str, v: &Option) -> bool { let cpython_version_pat = if let Some(v) = v { format!("python{}", v) @@ -1297,6 +1350,7 @@ fn search_lib_dir(path: impl AsRef, cross: &CrossCompileConfig) -> Vec Result InterpreterConfig { - // FIXME: PyPy does not support the Stable ABI yet. + // FIXME: PyPy & GraalPy do not support the Stable ABI. let implementation = PythonImplementation::CPython; let abi3 = true; @@ -1524,7 +1578,7 @@ fn default_lib_name_windows( // CPython bug: linking against python3_d.dll raises error // https://github.com/python/cpython/issues/101614 format!("python{}{}_d", version.major, version.minor) - } else if abi3 && !implementation.is_pypy() { + } else if abi3 && !(implementation.is_pypy() || implementation.is_graalpy()) { WINDOWS_ABI3_LIB_NAME.to_owned() } else if mingw { // https://packages.msys2.org/base/mingw-w64-python @@ -1562,6 +1616,7 @@ fn default_lib_name_unix( format!("pypy{}-c", version.major) } } + PythonImplementation::GraalPy => "python-native".to_string(), } } @@ -1662,7 +1717,9 @@ pub fn find_interpreter() -> Result { .find(|bin| { if let Ok(out) = Command::new(bin).arg("--version").output() { // begin with `Python 3.X.X :: additional info` - out.stdout.starts_with(b"Python 3") || out.stderr.starts_with(b"Python 3") + out.stdout.starts_with(b"Python 3") + || out.stderr.starts_with(b"Python 3") + || out.stdout.starts_with(b"GraalPy 3") } else { false } diff --git a/pyo3-build-config/src/import_lib.rs b/pyo3-build-config/src/import_lib.rs index dc21638c..0925a861 100644 --- a/pyo3-build-config/src/import_lib.rs +++ b/pyo3-build-config/src/import_lib.rs @@ -7,7 +7,7 @@ use python3_dll_a::ImportLibraryGenerator; use target_lexicon::{Architecture, OperatingSystem, Triple}; use super::{PythonImplementation, PythonVersion}; -use crate::errors::{Context, Result}; +use crate::errors::{Context, Error, Result}; /// Generates the `python3.dll` or `pythonXY.dll` import library for Windows targets. /// @@ -42,6 +42,9 @@ pub(super) fn generate_import_lib( let implementation = match py_impl { PythonImplementation::CPython => python3_dll_a::PythonImplementation::CPython, PythonImplementation::PyPy => python3_dll_a::PythonImplementation::PyPy, + PythonImplementation::GraalPy => { + return Err(Error::from("No support for GraalPy on Windows")) + } }; ImportLibraryGenerator::new(&arch, &env) diff --git a/pyo3-build-config/src/lib.rs b/pyo3-build-config/src/lib.rs index e7e59d3b..eab7376d 100644 --- a/pyo3-build-config/src/lib.rs +++ b/pyo3-build-config/src/lib.rs @@ -38,6 +38,7 @@ use target_lexicon::OperatingSystem; /// | `#[cfg(Py_3_7)]`, `#[cfg(Py_3_8)]`, `#[cfg(Py_3_9)]`, `#[cfg(Py_3_10)]` | These attributes mark code only for a given Python version and up. For example, `#[cfg(Py_3_7)]` marks code which can run on Python 3.7 **and newer**. | /// | `#[cfg(Py_LIMITED_API)]` | This marks code which is run when compiling with PyO3's `abi3` feature enabled. | /// | `#[cfg(PyPy)]` | This marks code which is run when compiling for PyPy. | +/// | `#[cfg(GraalPy)]` | This marks code which is run when compiling for GraalPy. | /// /// For examples of how to use these attributes, [see PyO3's guide](https://pyo3.rs/latest/building-and-distribution/multiple_python_versions.html). #[cfg(feature = "resolve-config")] diff --git a/pyo3-ffi/build.rs b/pyo3-ffi/build.rs index 286767d8..a5ab352b 100644 --- a/pyo3-ffi/build.rs +++ b/pyo3-ffi/build.rs @@ -29,6 +29,17 @@ const SUPPORTED_VERSIONS_PYPY: SupportedVersions = SupportedVersions { }, }; +const SUPPORTED_VERSIONS_GRAALPY: SupportedVersions = SupportedVersions { + min: PythonVersion { + major: 3, + minor: 10, + }, + max: PythonVersion { + major: 3, + minor: 11, + }, +}; + fn ensure_python_version(interpreter_config: &InterpreterConfig) -> Result<()> { // This is an undocumented env var which is only really intended to be used in CI / for testing // and development. @@ -73,6 +84,24 @@ fn ensure_python_version(interpreter_config: &InterpreterConfig) -> Result<()> { std::env::var("CARGO_PKG_VERSION").unwrap() ); } + PythonImplementation::GraalPy => { + let versions = SUPPORTED_VERSIONS_GRAALPY; + ensure!( + interpreter_config.version >= versions.min, + "the configured GraalPy interpreter version ({}) is lower than PyO3's minimum supported version ({})", + interpreter_config.version, + versions.min, + ); + // GraalPy does not support abi3, so we cannot offer forward compatibility + ensure!( + interpreter_config.version <= versions.max, + "the configured GraalPy interpreter version ({}) is newer than PyO3's maximum supported version ({})\n\ + = help: please check if an updated version of PyO3 is available. Current version: {}", + interpreter_config.version, + versions.max, + std::env::var("CARGO_PKG_VERSION").unwrap() + ); + } } Ok(()) diff --git a/pyo3-ffi/src/abstract_.rs b/pyo3-ffi/src/abstract_.rs index 0b3b7dbb..b5bf9cc3 100644 --- a/pyo3-ffi/src/abstract_.rs +++ b/pyo3-ffi/src/abstract_.rs @@ -23,6 +23,7 @@ pub unsafe fn PyObject_DelAttr(o: *mut PyObject, attr_name: *mut PyObject) -> c_ extern "C" { #[cfg(all( not(PyPy), + not(GraalPy), any(Py_3_10, all(not(Py_LIMITED_API), Py_3_9)) // Added to python in 3.9 but to limited API in 3.10 ))] #[cfg_attr(PyPy, link_name = "PyPyObject_CallNoArgs")] diff --git a/pyo3-ffi/src/boolobject.rs b/pyo3-ffi/src/boolobject.rs index 78972ff0..10b5969f 100644 --- a/pyo3-ffi/src/boolobject.rs +++ b/pyo3-ffi/src/boolobject.rs @@ -1,3 +1,4 @@ +#[cfg(not(GraalPy))] use crate::longobject::PyLongObject; use crate::object::*; use std::os::raw::{c_int, c_long}; @@ -16,20 +17,33 @@ pub unsafe fn PyBool_Check(op: *mut PyObject) -> c_int { #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { + #[cfg(not(GraalPy))] #[cfg_attr(PyPy, link_name = "_PyPy_FalseStruct")] static mut _Py_FalseStruct: PyLongObject; + #[cfg(not(GraalPy))] #[cfg_attr(PyPy, link_name = "_PyPy_TrueStruct")] static mut _Py_TrueStruct: PyLongObject; + + #[cfg(GraalPy)] + static mut _Py_FalseStructReference: *mut PyObject; + #[cfg(GraalPy)] + static mut _Py_TrueStructReference: *mut PyObject; } #[inline] pub unsafe fn Py_False() -> *mut PyObject { - addr_of_mut!(_Py_FalseStruct) as *mut PyObject + #[cfg(not(GraalPy))] + return addr_of_mut!(_Py_FalseStruct) as *mut PyObject; + #[cfg(GraalPy)] + return _Py_FalseStructReference; } #[inline] pub unsafe fn Py_True() -> *mut PyObject { - addr_of_mut!(_Py_TrueStruct) as *mut PyObject + #[cfg(not(GraalPy))] + return addr_of_mut!(_Py_TrueStruct) as *mut PyObject; + #[cfg(GraalPy)] + return _Py_TrueStructReference; } #[inline] diff --git a/pyo3-ffi/src/bytearrayobject.rs b/pyo3-ffi/src/bytearrayobject.rs index a37deb41..c09eac5b 100644 --- a/pyo3-ffi/src/bytearrayobject.rs +++ b/pyo3-ffi/src/bytearrayobject.rs @@ -3,7 +3,7 @@ use crate::pyport::Py_ssize_t; use std::os::raw::{c_char, c_int}; use std::ptr::addr_of_mut; -#[cfg(not(any(PyPy, Py_LIMITED_API)))] +#[cfg(not(any(PyPy, GraalPy, Py_LIMITED_API)))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyByteArrayObject { @@ -17,7 +17,7 @@ pub struct PyByteArrayObject { pub ob_exports: c_int, } -#[cfg(any(PyPy, Py_LIMITED_API))] +#[cfg(any(PyPy, GraalPy, Py_LIMITED_API))] opaque_struct!(PyByteArrayObject); #[cfg_attr(windows, link(name = "pythonXY"))] diff --git a/pyo3-ffi/src/complexobject.rs b/pyo3-ffi/src/complexobject.rs index 339f5d8c..a03d9b00 100644 --- a/pyo3-ffi/src/complexobject.rs +++ b/pyo3-ffi/src/complexobject.rs @@ -30,6 +30,7 @@ extern "C" { // non-limited pub struct PyComplexObject { pub ob_base: PyObject, + #[cfg(not(GraalPy))] pub cval: Py_complex, } diff --git a/pyo3-ffi/src/cpython/abstract_.rs b/pyo3-ffi/src/cpython/abstract_.rs index d2e3ca9d..cf95f671 100644 --- a/pyo3-ffi/src/cpython/abstract_.rs +++ b/pyo3-ffi/src/cpython/abstract_.rs @@ -6,7 +6,7 @@ use crate::Py_buffer; #[cfg(Py_3_8)] use crate::pyport::PY_SSIZE_T_MAX; -#[cfg(all(Py_3_8, not(PyPy)))] +#[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))] use crate::{ vectorcallfunc, PyCallable_Check, PyThreadState, PyThreadState_GET, PyTuple_Check, PyType_HasFeature, Py_TPFLAGS_HAVE_VECTORCALL, @@ -15,15 +15,15 @@ use crate::{ use libc::size_t; extern "C" { - #[cfg(all(Py_3_8, not(PyPy)))] + #[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))] pub fn _PyStack_AsDict(values: *const *mut PyObject, kwnames: *mut PyObject) -> *mut PyObject; } -#[cfg(all(Py_3_8, not(PyPy)))] +#[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))] const _PY_FASTCALL_SMALL_STACK: size_t = 5; extern "C" { - #[cfg(all(Py_3_8, not(PyPy)))] + #[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))] pub fn _Py_CheckFunctionResult( tstate: *mut PyThreadState, callable: *mut PyObject, @@ -31,7 +31,7 @@ extern "C" { where_: *const c_char, ) -> *mut PyObject; - #[cfg(all(Py_3_8, not(PyPy)))] + #[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))] pub fn _PyObject_MakeTpCall( tstate: *mut PyThreadState, callable: *mut PyObject, @@ -52,7 +52,7 @@ pub unsafe fn PyVectorcall_NARGS(n: size_t) -> Py_ssize_t { (n as Py_ssize_t) & !PY_VECTORCALL_ARGUMENTS_OFFSET } -#[cfg(all(Py_3_8, not(PyPy)))] +#[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))] #[inline(always)] pub unsafe fn PyVectorcall_Function(callable: *mut PyObject) -> Option { assert!(!callable.is_null()); @@ -67,7 +67,7 @@ pub unsafe fn PyVectorcall_Function(callable: *mut PyObject) -> Option *mut PyObject; #[cfg(Py_3_8)] - #[cfg_attr(all(not(PyPy), not(Py_3_9)), link_name = "_PyObject_VectorcallDict")] + #[cfg_attr( + all(not(any(PyPy, GraalPy)), not(Py_3_9)), + link_name = "_PyObject_VectorcallDict" + )] #[cfg_attr(all(PyPy, not(Py_3_9)), link_name = "_PyPyObject_VectorcallDict")] #[cfg_attr(all(PyPy, Py_3_9), link_name = "PyPyObject_VectorcallDict")] pub fn PyObject_VectorcallDict( @@ -134,7 +137,7 @@ extern "C" { ) -> *mut PyObject; } -#[cfg(all(Py_3_8, not(PyPy)))] +#[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))] #[inline(always)] pub unsafe fn _PyObject_FastCallTstate( tstate: *mut PyThreadState, @@ -145,7 +148,7 @@ pub unsafe fn _PyObject_FastCallTstate( _PyObject_VectorcallTstate(tstate, func, args, nargs as size_t, std::ptr::null_mut()) } -#[cfg(all(Py_3_8, not(PyPy)))] +#[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))] #[inline(always)] pub unsafe fn _PyObject_FastCall( func: *mut PyObject, @@ -155,7 +158,7 @@ pub unsafe fn _PyObject_FastCall( _PyObject_FastCallTstate(PyThreadState_GET(), func, args, nargs) } -#[cfg(all(Py_3_8, not(PyPy)))] +#[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))] #[inline(always)] pub unsafe fn _PyObject_CallNoArg(func: *mut PyObject) -> *mut PyObject { _PyObject_VectorcallTstate( @@ -173,7 +176,7 @@ extern "C" { pub fn _PyObject_CallNoArg(func: *mut PyObject) -> *mut PyObject; } -#[cfg(all(Py_3_8, not(PyPy)))] +#[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))] #[inline(always)] pub unsafe fn PyObject_CallOneArg(func: *mut PyObject, arg: *mut PyObject) -> *mut PyObject { assert!(!arg.is_null()); @@ -185,7 +188,7 @@ pub unsafe fn PyObject_CallOneArg(func: *mut PyObject, arg: *mut PyObject) -> *m } extern "C" { - #[cfg(all(Py_3_9, not(PyPy)))] + #[cfg(all(Py_3_9, not(any(PyPy, GraalPy))))] pub fn PyObject_VectorcallMethod( name: *mut PyObject, args: *const *mut PyObject, @@ -194,7 +197,7 @@ extern "C" { ) -> *mut PyObject; } -#[cfg(all(Py_3_9, not(PyPy)))] +#[cfg(all(Py_3_9, not(any(PyPy, GraalPy))))] #[inline(always)] pub unsafe fn PyObject_CallMethodNoArgs( self_: *mut PyObject, @@ -208,7 +211,7 @@ pub unsafe fn PyObject_CallMethodNoArgs( ) } -#[cfg(all(Py_3_9, not(PyPy)))] +#[cfg(all(Py_3_9, not(any(PyPy, GraalPy))))] #[inline(always)] pub unsafe fn PyObject_CallMethodOneArg( self_: *mut PyObject, @@ -236,7 +239,7 @@ extern "C" { pub fn PyObject_LengthHint(o: *mut PyObject, arg1: Py_ssize_t) -> Py_ssize_t; #[cfg(not(Py_3_11))] // moved to src/buffer.rs from 3.11 - #[cfg(all(Py_3_9, not(PyPy)))] + #[cfg(all(Py_3_9, not(any(PyPy, GraalPy))))] pub fn PyObject_CheckBuffer(obj: *mut PyObject) -> c_int; } @@ -308,7 +311,7 @@ pub const PY_ITERSEARCH_INDEX: c_int = 2; pub const PY_ITERSEARCH_CONTAINS: c_int = 3; extern "C" { - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub fn _PySequence_IterSearch( seq: *mut PyObject, obj: *mut PyObject, diff --git a/pyo3-ffi/src/cpython/bytesobject.rs b/pyo3-ffi/src/cpython/bytesobject.rs index 912fc0ac..fb0b38cf 100644 --- a/pyo3-ffi/src/cpython/bytesobject.rs +++ b/pyo3-ffi/src/cpython/bytesobject.rs @@ -1,10 +1,10 @@ use crate::object::*; use crate::Py_ssize_t; -#[cfg(not(any(PyPy, Py_LIMITED_API)))] +#[cfg(not(any(PyPy, GraalPy, Py_LIMITED_API)))] use std::os::raw::c_char; use std::os::raw::c_int; -#[cfg(not(any(PyPy, Py_LIMITED_API)))] +#[cfg(not(any(PyPy, GraalPy, Py_LIMITED_API)))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyBytesObject { @@ -13,7 +13,7 @@ pub struct PyBytesObject { pub ob_sval: [c_char; 1], } -#[cfg(any(PyPy, Py_LIMITED_API))] +#[cfg(any(PyPy, GraalPy, Py_LIMITED_API))] opaque_struct!(PyBytesObject); extern "C" { diff --git a/pyo3-ffi/src/cpython/code.rs b/pyo3-ffi/src/cpython/code.rs index 498eab59..74586eac 100644 --- a/pyo3-ffi/src/cpython/code.rs +++ b/pyo3-ffi/src/cpython/code.rs @@ -3,10 +3,10 @@ use crate::pyport::Py_ssize_t; #[allow(unused_imports)] use std::os::raw::{c_char, c_int, c_short, c_uchar, c_void}; -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] use std::ptr::addr_of_mut; -#[cfg(all(Py_3_8, not(PyPy), not(Py_3_11)))] +#[cfg(all(Py_3_8, not(any(PyPy, GraalPy)), not(Py_3_11)))] opaque_struct!(_PyOpcache); #[cfg(Py_3_12)] @@ -73,10 +73,10 @@ pub struct _PyCoMonitoringData { pub per_instruction_tools: *mut u8, } -#[cfg(all(not(PyPy), not(Py_3_7)))] +#[cfg(all(not(any(PyPy, GraalPy)), not(Py_3_7)))] opaque_struct!(PyCodeObject); -#[cfg(all(not(PyPy), Py_3_7, not(Py_3_8)))] +#[cfg(all(not(any(PyPy, GraalPy)), Py_3_7, not(Py_3_8)))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyCodeObject { @@ -102,7 +102,7 @@ pub struct PyCodeObject { pub co_extra: *mut c_void, } -#[cfg(all(not(PyPy), Py_3_8, not(Py_3_11)))] +#[cfg(all(not(any(PyPy, GraalPy)), Py_3_8, not(Py_3_11)))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyCodeObject { @@ -136,7 +136,7 @@ pub struct PyCodeObject { pub co_opcache_size: c_uchar, } -#[cfg(all(not(PyPy), Py_3_11))] +#[cfg(all(not(any(PyPy, GraalPy)), Py_3_11))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyCodeObject { @@ -230,26 +230,26 @@ pub const CO_FUTURE_GENERATOR_STOP: c_int = 0x8_0000; pub const CO_MAXBLOCKS: usize = 20; -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { pub static mut PyCode_Type: PyTypeObject; } #[inline] -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] pub unsafe fn PyCode_Check(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PyCode_Type)) as c_int } #[inline] -#[cfg(all(not(PyPy), Py_3_10, not(Py_3_11)))] +#[cfg(all(not(any(PyPy, GraalPy)), Py_3_10, not(Py_3_11)))] pub unsafe fn PyCode_GetNumFree(op: *mut PyCodeObject) -> Py_ssize_t { crate::PyTuple_GET_SIZE((*op).co_freevars) } #[inline] -#[cfg(all(not(Py_3_10), Py_3_11, not(PyPy)))] +#[cfg(all(not(Py_3_10), Py_3_11, not(any(PyPy, GraalPy))))] pub unsafe fn PyCode_GetNumFree(op: *mut PyCodeObject) -> c_int { (*op).co_nfreevars } @@ -265,6 +265,7 @@ extern "C" { } extern "C" { + #[cfg(not(GraalPy))] #[cfg_attr(PyPy, link_name = "PyPyCode_New")] pub fn PyCode_New( argcount: c_int, @@ -283,6 +284,7 @@ extern "C" { firstlineno: c_int, lnotab: *mut PyObject, ) -> *mut PyCodeObject; + #[cfg(not(GraalPy))] #[cfg(Py_3_8)] pub fn PyCode_NewWithPosOnlyArgs( argcount: c_int, @@ -302,12 +304,14 @@ extern "C" { firstlineno: c_int, lnotab: *mut PyObject, ) -> *mut PyCodeObject; + #[cfg(not(GraalPy))] #[cfg_attr(PyPy, link_name = "PyPyCode_NewEmpty")] pub fn PyCode_NewEmpty( filename: *const c_char, funcname: *const c_char, firstlineno: c_int, ) -> *mut PyCodeObject; + #[cfg(not(GraalPy))] pub fn PyCode_Addr2Line(arg1: *mut PyCodeObject, arg2: c_int) -> c_int; // skipped PyCodeAddressRange "for internal use only" // skipped _PyCode_CheckLineNumber diff --git a/pyo3-ffi/src/cpython/compile.rs b/pyo3-ffi/src/cpython/compile.rs index 71af81e8..8bce9dac 100644 --- a/pyo3-ffi/src/cpython/compile.rs +++ b/pyo3-ffi/src/cpython/compile.rs @@ -30,7 +30,7 @@ pub struct PyCompilerFlags { // skipped non-limited _PyCompilerFlags_INIT -#[cfg(all(Py_3_12, not(PyPy)))] +#[cfg(all(Py_3_12, not(any(PyPy, GraalPy))))] #[repr(C)] #[derive(Copy, Clone)] pub struct _PyCompilerSrcLocation { @@ -42,7 +42,7 @@ pub struct _PyCompilerSrcLocation { // skipped SRC_LOCATION_FROM_AST -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyFutureFeatures { diff --git a/pyo3-ffi/src/cpython/dictobject.rs b/pyo3-ffi/src/cpython/dictobject.rs index 4af990a2..74b970eb 100644 --- a/pyo3-ffi/src/cpython/dictobject.rs +++ b/pyo3-ffi/src/cpython/dictobject.rs @@ -7,6 +7,7 @@ opaque_struct!(PyDictKeysObject); #[cfg(Py_3_11)] opaque_struct!(PyDictValues); +#[cfg(not(GraalPy))] #[repr(C)] #[derive(Debug)] pub struct PyDictObject { diff --git a/pyo3-ffi/src/cpython/floatobject.rs b/pyo3-ffi/src/cpython/floatobject.rs index e33da0b9..8c7ee885 100644 --- a/pyo3-ffi/src/cpython/floatobject.rs +++ b/pyo3-ffi/src/cpython/floatobject.rs @@ -1,9 +1,12 @@ +#[cfg(GraalPy)] +use crate::PyFloat_AsDouble; use crate::{PyFloat_Check, PyObject}; use std::os::raw::c_double; #[repr(C)] pub struct PyFloatObject { pub ob_base: PyObject, + #[cfg(not(GraalPy))] pub ob_fval: c_double, } @@ -15,7 +18,10 @@ pub unsafe fn _PyFloat_CAST(op: *mut PyObject) -> *mut PyFloatObject { #[inline] pub unsafe fn PyFloat_AS_DOUBLE(op: *mut PyObject) -> c_double { - (*_PyFloat_CAST(op)).ob_fval + #[cfg(not(GraalPy))] + return (*_PyFloat_CAST(op)).ob_fval; + #[cfg(GraalPy)] + return PyFloat_AsDouble(op); } // skipped PyFloat_Pack2 diff --git a/pyo3-ffi/src/cpython/frameobject.rs b/pyo3-ffi/src/cpython/frameobject.rs index 7410000e..a85818ac 100644 --- a/pyo3-ffi/src/cpython/frameobject.rs +++ b/pyo3-ffi/src/cpython/frameobject.rs @@ -1,17 +1,19 @@ +#[cfg(not(GraalPy))] use crate::cpython::code::PyCodeObject; use crate::object::*; +#[cfg(not(GraalPy))] use crate::pystate::PyThreadState; -#[cfg(not(any(PyPy, Py_3_11)))] +#[cfg(not(any(PyPy, GraalPy, Py_3_11)))] use std::os::raw::c_char; use std::os::raw::c_int; use std::ptr::addr_of_mut; -#[cfg(not(any(PyPy, Py_3_11)))] +#[cfg(not(any(PyPy, GraalPy, Py_3_11)))] pub type PyFrameState = c_char; #[repr(C)] #[derive(Copy, Clone)] -#[cfg(not(any(PyPy, Py_3_11)))] +#[cfg(not(any(PyPy, GraalPy, Py_3_11)))] pub struct PyTryBlock { pub b_type: c_int, pub b_handler: c_int, @@ -20,7 +22,7 @@ pub struct PyTryBlock { #[repr(C)] #[derive(Copy, Clone)] -#[cfg(not(any(PyPy, Py_3_11)))] +#[cfg(not(any(PyPy, GraalPy, Py_3_11)))] pub struct PyFrameObject { pub ob_base: PyVarObject, pub f_back: *mut PyFrameObject, @@ -51,7 +53,7 @@ pub struct PyFrameObject { pub f_localsplus: [*mut PyObject; 1], } -#[cfg(any(PyPy, Py_3_11))] +#[cfg(any(PyPy, GraalPy, Py_3_11))] opaque_struct!(PyFrameObject); // skipped _PyFrame_IsRunnable @@ -69,6 +71,7 @@ pub unsafe fn PyFrame_Check(op: *mut PyObject) -> c_int { } extern "C" { + #[cfg(not(GraalPy))] #[cfg_attr(PyPy, link_name = "PyPyFrame_New")] pub fn PyFrame_New( tstate: *mut PyThreadState, @@ -79,7 +82,7 @@ extern "C" { // skipped _PyFrame_New_NoTrack pub fn PyFrame_BlockSetup(f: *mut PyFrameObject, _type: c_int, handler: c_int, level: c_int); - #[cfg(not(any(PyPy, Py_3_11)))] + #[cfg(not(any(PyPy, GraalPy, Py_3_11)))] pub fn PyFrame_BlockPop(f: *mut PyFrameObject) -> *mut PyTryBlock; pub fn PyFrame_LocalsToFast(f: *mut PyFrameObject, clear: c_int); diff --git a/pyo3-ffi/src/cpython/funcobject.rs b/pyo3-ffi/src/cpython/funcobject.rs index 1e9ee0cc..25de30d5 100644 --- a/pyo3-ffi/src/cpython/funcobject.rs +++ b/pyo3-ffi/src/cpython/funcobject.rs @@ -4,7 +4,7 @@ use std::ptr::addr_of_mut; use crate::PyObject; -#[cfg(all(not(PyPy), not(Py_3_10)))] +#[cfg(all(not(any(PyPy, GraalPy)), not(Py_3_10)))] #[repr(C)] pub struct PyFunctionObject { pub ob_base: PyObject, @@ -24,7 +24,7 @@ pub struct PyFunctionObject { pub vectorcall: Option, } -#[cfg(all(not(PyPy), Py_3_10))] +#[cfg(all(not(any(PyPy, GraalPy)), Py_3_10))] #[repr(C)] pub struct PyFunctionObject { pub ob_base: PyObject, @@ -55,6 +55,11 @@ pub struct PyFunctionObject { pub func_name: *mut PyObject, } +#[cfg(GraalPy)] +pub struct PyFunctionObject { + pub ob_base: PyObject, +} + #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg(not(all(PyPy, not(Py_3_8))))] diff --git a/pyo3-ffi/src/cpython/genobject.rs b/pyo3-ffi/src/cpython/genobject.rs index aaa03f82..73ebdb49 100644 --- a/pyo3-ffi/src/cpython/genobject.rs +++ b/pyo3-ffi/src/cpython/genobject.rs @@ -1,13 +1,13 @@ use crate::object::*; use crate::PyFrameObject; -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] use crate::_PyErr_StackItem; #[cfg(Py_3_11)] use std::os::raw::c_char; use std::os::raw::c_int; use std::ptr::addr_of_mut; -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyGenObject { diff --git a/pyo3-ffi/src/cpython/listobject.rs b/pyo3-ffi/src/cpython/listobject.rs index 7fb2228f..ea15cfc1 100644 --- a/pyo3-ffi/src/cpython/listobject.rs +++ b/pyo3-ffi/src/cpython/listobject.rs @@ -2,7 +2,7 @@ use crate::object::*; #[cfg(not(PyPy))] use crate::pyport::Py_ssize_t; -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyListObject { @@ -11,7 +11,7 @@ pub struct PyListObject { pub allocated: Py_ssize_t, } -#[cfg(PyPy)] +#[cfg(any(PyPy, GraalPy))] pub struct PyListObject { pub ob_base: PyObject, } @@ -22,14 +22,14 @@ pub struct PyListObject { /// Macro, trading safety for speed #[inline] -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] pub unsafe fn PyList_GET_ITEM(op: *mut PyObject, i: Py_ssize_t) -> *mut PyObject { *(*(op as *mut PyListObject)).ob_item.offset(i) } /// Macro, *only* to be used to fill in brand new lists #[inline] -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] pub unsafe fn PyList_SET_ITEM(op: *mut PyObject, i: Py_ssize_t, v: *mut PyObject) { *(*(op as *mut PyListObject)).ob_item.offset(i) = v; } diff --git a/pyo3-ffi/src/cpython/methodobject.rs b/pyo3-ffi/src/cpython/methodobject.rs index 7d965978..97ad9ce3 100644 --- a/pyo3-ffi/src/cpython/methodobject.rs +++ b/pyo3-ffi/src/cpython/methodobject.rs @@ -1,8 +1,10 @@ use crate::object::*; +#[cfg(not(GraalPy))] use crate::{PyCFunctionObject, PyMethodDefPointer, METH_METHOD, METH_STATIC}; use std::os::raw::c_int; use std::ptr::addr_of_mut; +#[cfg(not(GraalPy))] pub struct PyCMethodObject { pub func: PyCFunctionObject, pub mm_class: *mut PyTypeObject, @@ -23,6 +25,7 @@ pub unsafe fn PyCMethod_Check(op: *mut PyObject) -> c_int { PyObject_TypeCheck(op, addr_of_mut!(PyCMethod_Type)) } +#[cfg(not(GraalPy))] #[inline] pub unsafe fn PyCFunction_GET_FUNCTION(func: *mut PyObject) -> PyMethodDefPointer { debug_assert_eq!(PyCMethod_Check(func), 1); @@ -31,6 +34,7 @@ pub unsafe fn PyCFunction_GET_FUNCTION(func: *mut PyObject) -> PyMethodDefPointe (*(*func).m_ml).ml_meth } +#[cfg(not(GraalPy))] #[inline] pub unsafe fn PyCFunction_GET_SELF(func: *mut PyObject) -> *mut PyObject { debug_assert_eq!(PyCMethod_Check(func), 1); @@ -43,6 +47,7 @@ pub unsafe fn PyCFunction_GET_SELF(func: *mut PyObject) -> *mut PyObject { } } +#[cfg(not(GraalPy))] #[inline] pub unsafe fn PyCFunction_GET_FLAGS(func: *mut PyObject) -> c_int { debug_assert_eq!(PyCMethod_Check(func), 1); @@ -51,6 +56,7 @@ pub unsafe fn PyCFunction_GET_FLAGS(func: *mut PyObject) -> c_int { (*(*func).m_ml).ml_flags } +#[cfg(not(GraalPy))] #[inline] pub unsafe fn PyCFunction_GET_CLASS(func: *mut PyObject) -> *mut PyTypeObject { debug_assert_eq!(PyCMethod_Check(func), 1); diff --git a/pyo3-ffi/src/cpython/mod.rs b/pyo3-ffi/src/cpython/mod.rs index 738ba376..1ab0e3c8 100644 --- a/pyo3-ffi/src/cpython/mod.rs +++ b/pyo3-ffi/src/cpython/mod.rs @@ -68,5 +68,5 @@ pub use self::pystate::*; pub use self::pythonrun::*; pub use self::tupleobject::*; pub use self::unicodeobject::*; -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] pub use self::weakrefobject::*; diff --git a/pyo3-ffi/src/cpython/object.rs b/pyo3-ffi/src/cpython/object.rs index d0c16340..0f1778f6 100644 --- a/pyo3-ffi/src/cpython/object.rs +++ b/pyo3-ffi/src/cpython/object.rs @@ -217,6 +217,8 @@ pub struct PyTypeObject { pub ob_size: Py_ssize_t, #[cfg(not(all(PyPy, not(Py_3_9))))] pub ob_base: object::PyVarObject, + #[cfg(GraalPy)] + pub ob_size: Py_ssize_t, pub tp_name: *const c_char, pub tp_basicsize: Py_ssize_t, pub tp_itemsize: Py_ssize_t, diff --git a/pyo3-ffi/src/cpython/objimpl.rs b/pyo3-ffi/src/cpython/objimpl.rs index 36a4380d..3e0270dd 100644 --- a/pyo3-ffi/src/cpython/objimpl.rs +++ b/pyo3-ffi/src/cpython/objimpl.rs @@ -1,7 +1,7 @@ use libc::size_t; use std::os::raw::c_int; -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] use std::os::raw::c_void; use crate::object::*; @@ -14,7 +14,7 @@ extern "C" { pub fn _Py_GetAllocatedBlocks() -> crate::Py_ssize_t; } -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyObjectArenaAllocator { @@ -23,7 +23,7 @@ pub struct PyObjectArenaAllocator { pub free: Option, } -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] impl Default for PyObjectArenaAllocator { #[inline] fn default() -> Self { @@ -32,9 +32,9 @@ impl Default for PyObjectArenaAllocator { } extern "C" { - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub fn PyObject_GetArenaAllocator(allocator: *mut PyObjectArenaAllocator); - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub fn PyObject_SetArenaAllocator(allocator: *mut PyObjectArenaAllocator); #[cfg(Py_3_9)] diff --git a/pyo3-ffi/src/cpython/pyerrors.rs b/pyo3-ffi/src/cpython/pyerrors.rs index fe7b4d4b..6d17ebc8 100644 --- a/pyo3-ffi/src/cpython/pyerrors.rs +++ b/pyo3-ffi/src/cpython/pyerrors.rs @@ -1,28 +1,28 @@ use crate::PyObject; -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] use crate::Py_ssize_t; #[repr(C)] #[derive(Debug)] pub struct PyBaseExceptionObject { pub ob_base: PyObject, - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub dict: *mut PyObject, - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub args: *mut PyObject, - #[cfg(all(Py_3_11, not(PyPy)))] + #[cfg(all(Py_3_11, not(any(PyPy, GraalPy))))] pub notes: *mut PyObject, - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub traceback: *mut PyObject, - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub context: *mut PyObject, - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub cause: *mut PyObject, - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub suppress_context: char, } -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] #[repr(C)] #[derive(Debug)] pub struct PySyntaxErrorObject { @@ -48,7 +48,7 @@ pub struct PySyntaxErrorObject { pub print_file_and_line: *mut PyObject, } -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] #[repr(C)] #[derive(Debug)] pub struct PyImportErrorObject { @@ -69,7 +69,7 @@ pub struct PyImportErrorObject { pub name_from: *mut PyObject, } -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] #[repr(C)] #[derive(Debug)] pub struct PyUnicodeErrorObject { @@ -90,7 +90,7 @@ pub struct PyUnicodeErrorObject { pub reason: *mut PyObject, } -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] #[repr(C)] #[derive(Debug)] pub struct PySystemExitObject { @@ -107,7 +107,7 @@ pub struct PySystemExitObject { pub code: *mut PyObject, } -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] #[repr(C)] #[derive(Debug)] pub struct PyOSErrorObject { @@ -134,26 +134,26 @@ pub struct PyOSErrorObject { #[derive(Debug)] pub struct PyStopIterationObject { pub ob_base: PyObject, - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub dict: *mut PyObject, - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub args: *mut PyObject, - #[cfg(all(Py_3_11, not(PyPy)))] + #[cfg(all(Py_3_11, not(any(PyPy, GraalPy))))] pub notes: *mut PyObject, - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub traceback: *mut PyObject, - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub context: *mut PyObject, - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub cause: *mut PyObject, - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub suppress_context: char, pub value: *mut PyObject, } extern "C" { - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub fn _PyErr_ChainExceptions(typ: *mut PyObject, val: *mut PyObject, tb: *mut PyObject); } diff --git a/pyo3-ffi/src/cpython/pymem.rs b/pyo3-ffi/src/cpython/pymem.rs index 2dfb3f3b..c400fa30 100644 --- a/pyo3-ffi/src/cpython/pymem.rs +++ b/pyo3-ffi/src/cpython/pymem.rs @@ -26,7 +26,7 @@ pub enum PyMemAllocatorDomain { } // skipped PyMemAllocatorName -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyMemAllocatorEx { @@ -40,10 +40,10 @@ pub struct PyMemAllocatorEx { } extern "C" { - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub fn PyMem_GetAllocator(domain: PyMemAllocatorDomain, allocator: *mut PyMemAllocatorEx); - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub fn PyMem_SetAllocator(domain: PyMemAllocatorDomain, allocator: *mut PyMemAllocatorEx); - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub fn PyMem_SetupDebugHooks(); } diff --git a/pyo3-ffi/src/cpython/pythonrun.rs b/pyo3-ffi/src/cpython/pythonrun.rs index a92528b7..94863166 100644 --- a/pyo3-ffi/src/cpython/pythonrun.rs +++ b/pyo3-ffi/src/cpython/pythonrun.rs @@ -1,8 +1,8 @@ use crate::object::*; -#[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))] +#[cfg(not(any(PyPy, GraalPy, Py_LIMITED_API, Py_3_10)))] use crate::pyarena::PyArena; use crate::PyCompilerFlags; -#[cfg(not(any(PyPy, Py_3_10)))] +#[cfg(not(any(PyPy, GraalPy, Py_3_10)))] use crate::{_mod, _node}; use libc::FILE; use std::os::raw::{c_char, c_int}; @@ -54,7 +54,7 @@ extern "C" { flags: *mut PyCompilerFlags, ) -> c_int; - #[cfg(not(any(PyPy, Py_3_10)))] + #[cfg(not(any(PyPy, GraalPy, Py_3_10)))] pub fn PyParser_ASTFromString( s: *const c_char, filename: *const c_char, @@ -62,7 +62,7 @@ extern "C" { flags: *mut PyCompilerFlags, arena: *mut PyArena, ) -> *mut _mod; - #[cfg(not(any(PyPy, Py_3_10)))] + #[cfg(not(any(PyPy, GraalPy, Py_3_10)))] pub fn PyParser_ASTFromStringObject( s: *const c_char, filename: *mut PyObject, @@ -70,7 +70,7 @@ extern "C" { flags: *mut PyCompilerFlags, arena: *mut PyArena, ) -> *mut _mod; - #[cfg(not(any(PyPy, Py_3_10)))] + #[cfg(not(any(PyPy, GraalPy, Py_3_10)))] pub fn PyParser_ASTFromFile( fp: *mut FILE, filename: *const c_char, @@ -82,7 +82,7 @@ extern "C" { errcode: *mut c_int, arena: *mut PyArena, ) -> *mut _mod; - #[cfg(not(any(PyPy, Py_3_10)))] + #[cfg(not(any(PyPy, GraalPy, Py_3_10)))] pub fn PyParser_ASTFromFileObject( fp: *mut FILE, filename: *mut PyObject, @@ -105,7 +105,7 @@ extern "C" { arg4: *mut PyObject, arg5: *mut PyCompilerFlags, ) -> *mut PyObject; - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub fn PyRun_FileExFlags( fp: *mut FILE, filename: *const c_char, @@ -116,7 +116,7 @@ extern "C" { flags: *mut PyCompilerFlags, ) -> *mut PyObject; - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub fn Py_CompileStringExFlags( str: *const c_char, filename: *const c_char, @@ -135,6 +135,7 @@ extern "C" { } #[inline] +#[cfg(not(GraalPy))] pub unsafe fn Py_CompileString(string: *const c_char, p: *const c_char, s: c_int) -> *mut PyObject { #[cfg(not(PyPy))] return Py_CompileStringExFlags(string, p, s, std::ptr::null_mut(), -1); @@ -144,7 +145,7 @@ pub unsafe fn Py_CompileString(string: *const c_char, p: *const c_char, s: c_int } #[inline] -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] pub unsafe fn Py_CompileStringFlags( string: *const c_char, p: *const c_char, @@ -164,11 +165,11 @@ extern "C" { g: *mut PyObject, l: *mut PyObject, ) -> *mut PyObject; - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub fn PyRun_AnyFile(fp: *mut FILE, name: *const c_char) -> c_int; - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub fn PyRun_AnyFileEx(fp: *mut FILE, name: *const c_char, closeit: c_int) -> c_int; - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub fn PyRun_AnyFileFlags( arg1: *mut FILE, arg2: *const c_char, @@ -176,13 +177,13 @@ extern "C" { ) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyRun_SimpleString")] pub fn PyRun_SimpleString(s: *const c_char) -> c_int; - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub fn PyRun_SimpleFile(f: *mut FILE, p: *const c_char) -> c_int; - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub fn PyRun_SimpleFileEx(f: *mut FILE, p: *const c_char, c: c_int) -> c_int; - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub fn PyRun_InteractiveOne(f: *mut FILE, p: *const c_char) -> c_int; - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub fn PyRun_InteractiveLoop(f: *mut FILE, p: *const c_char) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyRun_File")] pub fn PyRun_File( @@ -192,7 +193,7 @@ extern "C" { g: *mut PyObject, l: *mut PyObject, ) -> *mut PyObject; - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub fn PyRun_FileEx( fp: *mut FILE, p: *const c_char, @@ -201,7 +202,7 @@ extern "C" { l: *mut PyObject, c: c_int, ) -> *mut PyObject; - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub fn PyRun_FileFlags( fp: *mut FILE, p: *const c_char, @@ -218,14 +219,14 @@ extern "C" { // skipped macro PyRun_AnyFileFlags extern "C" { - #[cfg(not(any(PyPy, Py_3_10)))] + #[cfg(not(any(PyPy, GraalPy, Py_3_10)))] #[cfg_attr(Py_3_9, deprecated(note = "Python 3.9"))] pub fn PyParser_SimpleParseStringFlags( arg1: *const c_char, arg2: c_int, arg3: c_int, ) -> *mut _node; - #[cfg(not(any(PyPy, Py_3_10)))] + #[cfg(not(any(PyPy, GraalPy, Py_3_10)))] #[cfg_attr(Py_3_9, deprecated(note = "Python 3.9"))] pub fn PyParser_SimpleParseStringFlagsFilename( arg1: *const c_char, @@ -233,7 +234,7 @@ extern "C" { arg3: c_int, arg4: c_int, ) -> *mut _node; - #[cfg(not(any(PyPy, Py_3_10)))] + #[cfg(not(any(PyPy, GraalPy, Py_3_10)))] #[cfg_attr(Py_3_9, deprecated(note = "Python 3.9"))] pub fn PyParser_SimpleParseFileFlags( arg1: *mut FILE, diff --git a/pyo3-ffi/src/cpython/tupleobject.rs b/pyo3-ffi/src/cpython/tupleobject.rs index 24dde268..4ed8520d 100644 --- a/pyo3-ffi/src/cpython/tupleobject.rs +++ b/pyo3-ffi/src/cpython/tupleobject.rs @@ -5,6 +5,7 @@ use crate::pyport::Py_ssize_t; #[repr(C)] pub struct PyTupleObject { pub ob_base: PyVarObject, + #[cfg(not(GraalPy))] pub ob_item: [*mut PyObject; 1], } @@ -22,14 +23,14 @@ pub unsafe fn PyTuple_GET_SIZE(op: *mut PyObject) -> Py_ssize_t { } #[inline] -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] pub unsafe fn PyTuple_GET_ITEM(op: *mut PyObject, i: Py_ssize_t) -> *mut PyObject { *(*(op as *mut PyTupleObject)).ob_item.as_ptr().offset(i) } /// Macro, *only* to be used to fill in brand new tuples #[inline] -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] pub unsafe fn PyTuple_SET_ITEM(op: *mut PyObject, i: Py_ssize_t, v: *mut PyObject) { *(*(op as *mut PyTupleObject)).ob_item.as_mut_ptr().offset(i) = v; } diff --git a/pyo3-ffi/src/cpython/unicodeobject.rs b/pyo3-ffi/src/cpython/unicodeobject.rs index f618ecf0..9ab523a2 100644 --- a/pyo3-ffi/src/cpython/unicodeobject.rs +++ b/pyo3-ffi/src/cpython/unicodeobject.rs @@ -1,7 +1,7 @@ -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] use crate::Py_hash_t; use crate::{PyObject, Py_UCS1, Py_UCS2, Py_UCS4, Py_UNICODE, Py_ssize_t}; -#[cfg(not(Py_3_12))] +#[cfg(not(any(Py_3_12, GraalPy)))] use libc::wchar_t; use std::os::raw::{c_char, c_int, c_uint, c_void}; @@ -44,6 +44,7 @@ impl BitfieldUnit { } } +#[cfg(not(GraalPy))] impl BitfieldUnit where Storage: AsRef<[u8]> + AsMut<[u8]>, @@ -117,23 +118,31 @@ where } } +#[cfg(not(GraalPy))] const STATE_INTERNED_INDEX: usize = 0; +#[cfg(not(GraalPy))] const STATE_INTERNED_WIDTH: u8 = 2; +#[cfg(not(GraalPy))] const STATE_KIND_INDEX: usize = STATE_INTERNED_WIDTH as usize; +#[cfg(not(GraalPy))] const STATE_KIND_WIDTH: u8 = 3; +#[cfg(not(GraalPy))] const STATE_COMPACT_INDEX: usize = (STATE_INTERNED_WIDTH + STATE_KIND_WIDTH) as usize; +#[cfg(not(GraalPy))] const STATE_COMPACT_WIDTH: u8 = 1; +#[cfg(not(GraalPy))] const STATE_ASCII_INDEX: usize = (STATE_INTERNED_WIDTH + STATE_KIND_WIDTH + STATE_COMPACT_WIDTH) as usize; +#[cfg(not(GraalPy))] const STATE_ASCII_WIDTH: u8 = 1; -#[cfg(not(Py_3_12))] +#[cfg(not(any(Py_3_12, GraalPy)))] const STATE_READY_INDEX: usize = (STATE_INTERNED_WIDTH + STATE_KIND_WIDTH + STATE_COMPACT_WIDTH + STATE_ASCII_WIDTH) as usize; -#[cfg(not(Py_3_12))] +#[cfg(not(any(Py_3_12, GraalPy)))] const STATE_READY_WIDTH: u8 = 1; // generated by bindgen v0.63.0 (with small adaptations) @@ -153,6 +162,7 @@ struct PyASCIIObjectState { } // c_uint and u32 are not necessarily the same type on all targets / architectures +#[cfg(not(GraalPy))] #[allow(clippy::useless_transmute)] impl PyASCIIObjectState { #[inline] @@ -241,8 +251,9 @@ impl From for u32 { #[repr(C)] pub struct PyASCIIObject { pub ob_base: PyObject, + #[cfg(not(GraalPy))] pub length: Py_ssize_t, - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub hash: Py_hash_t, /// A bit field with various properties. /// @@ -255,12 +266,14 @@ pub struct PyASCIIObject { /// unsigned int ascii:1; /// unsigned int ready:1; /// unsigned int :24; + #[cfg(not(GraalPy))] pub state: u32, - #[cfg(not(Py_3_12))] + #[cfg(not(any(Py_3_12, GraalPy)))] pub wstr: *mut wchar_t, } /// Interacting with the bitfield is not actually well-defined, so we mark these APIs unsafe. +#[cfg(not(GraalPy))] impl PyASCIIObject { #[cfg_attr(not(Py_3_12), allow(rustdoc::broken_intra_doc_links))] // SSTATE_INTERNED_IMMORTAL_STATIC requires 3.12 /// Get the `interned` field of the [`PyASCIIObject`] state bitfield. @@ -367,9 +380,11 @@ impl PyASCIIObject { #[repr(C)] pub struct PyCompactUnicodeObject { pub _base: PyASCIIObject, + #[cfg(not(GraalPy))] pub utf8_length: Py_ssize_t, + #[cfg(not(GraalPy))] pub utf8: *mut c_char, - #[cfg(not(Py_3_12))] + #[cfg(not(any(Py_3_12, GraalPy)))] pub wstr_length: Py_ssize_t, } @@ -384,11 +399,12 @@ pub union PyUnicodeObjectData { #[repr(C)] pub struct PyUnicodeObject { pub _base: PyCompactUnicodeObject, + #[cfg(not(GraalPy))] pub data: PyUnicodeObjectData, } extern "C" { - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub fn _PyUnicode_CheckConsistency(op: *mut PyObject, check_content: c_int) -> c_int; } @@ -403,6 +419,7 @@ pub const SSTATE_INTERNED_IMMORTAL: c_uint = 2; #[cfg(Py_3_12)] pub const SSTATE_INTERNED_IMMORTAL_STATIC: c_uint = 3; +#[cfg(not(GraalPy))] #[inline] pub unsafe fn PyUnicode_IS_ASCII(op: *mut PyObject) -> c_uint { debug_assert!(crate::PyUnicode_Check(op) != 0); @@ -412,11 +429,13 @@ pub unsafe fn PyUnicode_IS_ASCII(op: *mut PyObject) -> c_uint { (*(op as *mut PyASCIIObject)).ascii() } +#[cfg(not(GraalPy))] #[inline] pub unsafe fn PyUnicode_IS_COMPACT(op: *mut PyObject) -> c_uint { (*(op as *mut PyASCIIObject)).compact() } +#[cfg(not(GraalPy))] #[inline] pub unsafe fn PyUnicode_IS_COMPACT_ASCII(op: *mut PyObject) -> c_uint { ((*(op as *mut PyASCIIObject)).ascii() != 0 && PyUnicode_IS_COMPACT(op) != 0).into() @@ -430,21 +449,25 @@ pub const PyUnicode_1BYTE_KIND: c_uint = 1; pub const PyUnicode_2BYTE_KIND: c_uint = 2; pub const PyUnicode_4BYTE_KIND: c_uint = 4; +#[cfg(not(GraalPy))] #[inline] pub unsafe fn PyUnicode_1BYTE_DATA(op: *mut PyObject) -> *mut Py_UCS1 { PyUnicode_DATA(op) as *mut Py_UCS1 } +#[cfg(not(GraalPy))] #[inline] pub unsafe fn PyUnicode_2BYTE_DATA(op: *mut PyObject) -> *mut Py_UCS2 { PyUnicode_DATA(op) as *mut Py_UCS2 } +#[cfg(not(GraalPy))] #[inline] pub unsafe fn PyUnicode_4BYTE_DATA(op: *mut PyObject) -> *mut Py_UCS4 { PyUnicode_DATA(op) as *mut Py_UCS4 } +#[cfg(not(GraalPy))] #[inline] pub unsafe fn PyUnicode_KIND(op: *mut PyObject) -> c_uint { debug_assert!(crate::PyUnicode_Check(op) != 0); @@ -454,6 +477,7 @@ pub unsafe fn PyUnicode_KIND(op: *mut PyObject) -> c_uint { (*(op as *mut PyASCIIObject)).kind() } +#[cfg(not(GraalPy))] #[inline] pub unsafe fn _PyUnicode_COMPACT_DATA(op: *mut PyObject) -> *mut c_void { if PyUnicode_IS_ASCII(op) != 0 { @@ -463,6 +487,7 @@ pub unsafe fn _PyUnicode_COMPACT_DATA(op: *mut PyObject) -> *mut c_void { } } +#[cfg(not(GraalPy))] #[inline] pub unsafe fn _PyUnicode_NONCOMPACT_DATA(op: *mut PyObject) -> *mut c_void { debug_assert!(!(*(op as *mut PyUnicodeObject)).data.any.is_null()); @@ -470,6 +495,7 @@ pub unsafe fn _PyUnicode_NONCOMPACT_DATA(op: *mut PyObject) -> *mut c_void { (*(op as *mut PyUnicodeObject)).data.any } +#[cfg(not(GraalPy))] #[inline] pub unsafe fn PyUnicode_DATA(op: *mut PyObject) -> *mut c_void { debug_assert!(crate::PyUnicode_Check(op) != 0); @@ -485,6 +511,7 @@ pub unsafe fn PyUnicode_DATA(op: *mut PyObject) -> *mut c_void { // skipped PyUnicode_READ // skipped PyUnicode_READ_CHAR +#[cfg(not(GraalPy))] #[inline] pub unsafe fn PyUnicode_GET_LENGTH(op: *mut PyObject) -> Py_ssize_t { debug_assert!(crate::PyUnicode_Check(op) != 0); @@ -494,26 +521,26 @@ pub unsafe fn PyUnicode_GET_LENGTH(op: *mut PyObject) -> Py_ssize_t { (*(op as *mut PyASCIIObject)).length } -#[cfg(Py_3_12)] +#[cfg(any(Py_3_12, GraalPy))] #[inline] pub unsafe fn PyUnicode_IS_READY(_op: *mut PyObject) -> c_uint { // kept in CPython for backwards compatibility 1 } -#[cfg(not(Py_3_12))] +#[cfg(not(any(GraalPy, Py_3_12)))] #[inline] pub unsafe fn PyUnicode_IS_READY(op: *mut PyObject) -> c_uint { (*(op as *mut PyASCIIObject)).ready() } -#[cfg(Py_3_12)] +#[cfg(any(Py_3_12, GraalPy))] #[inline] pub unsafe fn PyUnicode_READY(_op: *mut PyObject) -> c_int { 0 } -#[cfg(not(Py_3_12))] +#[cfg(not(any(Py_3_12, GraalPy)))] #[inline] pub unsafe fn PyUnicode_READY(op: *mut PyObject) -> c_int { debug_assert!(crate::PyUnicode_Check(op) != 0); diff --git a/pyo3-ffi/src/cpython/weakrefobject.rs b/pyo3-ffi/src/cpython/weakrefobject.rs index 5a5f85c5..3a232c7e 100644 --- a/pyo3-ffi/src/cpython/weakrefobject.rs +++ b/pyo3-ffi/src/cpython/weakrefobject.rs @@ -1,4 +1,4 @@ -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] pub struct _PyWeakReference { pub ob_base: crate::PyObject, pub wr_object: *mut crate::PyObject, diff --git a/pyo3-ffi/src/datetime.rs b/pyo3-ffi/src/datetime.rs index 7e5a2509..a20b76aa 100644 --- a/pyo3-ffi/src/datetime.rs +++ b/pyo3-ffi/src/datetime.rs @@ -9,17 +9,16 @@ //! Support for `PyDateTime_CAPI` is limited as of PyPy 7.0.0. //! `DateTime_FromTimestamp` and `Date_FromTimestamp` are currently not supported. +#[cfg(GraalPy)] +use crate::{PyLong_AsLong, PyLong_Check, PyObject_GetAttrString, Py_DecRef}; use crate::{PyObject, PyObject_TypeCheck, PyTypeObject, Py_TYPE}; use std::cell::UnsafeCell; use std::os::raw::{c_char, c_int}; use std::ptr; #[cfg(not(PyPy))] -use { - crate::{PyCapsule_Import, Py_hash_t}, - std::ffi::CString, - std::os::raw::c_uchar, -}; - +use {crate::PyCapsule_Import, std::ffi::CString}; +#[cfg(not(any(PyPy, GraalPy)))] +use {crate::Py_hash_t, std::os::raw::c_uchar}; // Type struct wrappers const _PyDateTime_DATE_DATASIZE: usize = 4; const _PyDateTime_TIME_DATASIZE: usize = 6; @@ -30,26 +29,27 @@ const _PyDateTime_DATETIME_DATASIZE: usize = 10; /// Structure representing a `datetime.timedelta`. pub struct PyDateTime_Delta { pub ob_base: PyObject, - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub hashcode: Py_hash_t, + #[cfg(not(GraalPy))] pub days: c_int, + #[cfg(not(GraalPy))] pub seconds: c_int, + #[cfg(not(GraalPy))] pub microseconds: c_int, } // skipped non-limited PyDateTime_TZInfo // skipped non-limited _PyDateTime_BaseTZInfo -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] #[repr(C)] #[derive(Debug, Copy, Clone)] /// Structure representing a `datetime.time` without a `tzinfo` member. pub struct _PyDateTime_BaseTime { pub ob_base: PyObject, - #[cfg(not(PyPy))] pub hashcode: Py_hash_t, pub hastzinfo: c_char, - #[cfg(not(PyPy))] pub data: [c_uchar; _PyDateTime_TIME_DATASIZE], } @@ -58,17 +58,19 @@ pub struct _PyDateTime_BaseTime { /// Structure representing a `datetime.time`. pub struct PyDateTime_Time { pub ob_base: PyObject, - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub hashcode: Py_hash_t, + #[cfg(not(GraalPy))] pub hastzinfo: c_char, - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub data: [c_uchar; _PyDateTime_TIME_DATASIZE], - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub fold: c_uchar, /// # Safety /// /// Care should be taken when reading this field. If the time does not have a /// tzinfo then CPython may allocate as a `_PyDateTime_BaseTime` without this field. + #[cfg(not(GraalPy))] pub tzinfo: *mut PyObject, } @@ -77,24 +79,22 @@ pub struct PyDateTime_Time { /// Structure representing a `datetime.date` pub struct PyDateTime_Date { pub ob_base: PyObject, - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub hashcode: Py_hash_t, - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub hastzinfo: c_char, - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub data: [c_uchar; _PyDateTime_DATE_DATASIZE], } -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] #[repr(C)] #[derive(Debug, Copy, Clone)] /// Structure representing a `datetime.datetime` without a `tzinfo` member. pub struct _PyDateTime_BaseDateTime { pub ob_base: PyObject, - #[cfg(not(PyPy))] pub hashcode: Py_hash_t, pub hastzinfo: c_char, - #[cfg(not(PyPy))] pub data: [c_uchar; _PyDateTime_DATETIME_DATASIZE], } @@ -103,17 +103,19 @@ pub struct _PyDateTime_BaseDateTime { /// Structure representing a `datetime.datetime`. pub struct PyDateTime_DateTime { pub ob_base: PyObject, - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub hashcode: Py_hash_t, + #[cfg(not(GraalPy))] pub hastzinfo: c_char, - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub data: [c_uchar; _PyDateTime_DATETIME_DATASIZE], - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub fold: c_uchar, /// # Safety /// /// Care should be taken when reading this field. If the time does not have a /// tzinfo then CPython may allocate as a `_PyDateTime_BaseDateTime` without this field. + #[cfg(not(GraalPy))] pub tzinfo: *mut PyObject, } @@ -121,7 +123,7 @@ pub struct PyDateTime_DateTime { // Accessor functions for PyDateTime_Date and PyDateTime_DateTime #[inline] -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the year component of a `PyDateTime_Date` or `PyDateTime_DateTime`. /// Returns a signed integer greater than 0. pub unsafe fn PyDateTime_GET_YEAR(o: *mut PyObject) -> c_int { @@ -131,7 +133,7 @@ pub unsafe fn PyDateTime_GET_YEAR(o: *mut PyObject) -> c_int { } #[inline] -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the month component of a `PyDateTime_Date` or `PyDateTime_DateTime`. /// Returns a signed integer in the range `[1, 12]`. pub unsafe fn PyDateTime_GET_MONTH(o: *mut PyObject) -> c_int { @@ -140,7 +142,7 @@ pub unsafe fn PyDateTime_GET_MONTH(o: *mut PyObject) -> c_int { } #[inline] -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the day component of a `PyDateTime_Date` or `PyDateTime_DateTime`. /// Returns a signed integer in the interval `[1, 31]`. pub unsafe fn PyDateTime_GET_DAY(o: *mut PyObject) -> c_int { @@ -149,28 +151,28 @@ pub unsafe fn PyDateTime_GET_DAY(o: *mut PyObject) -> c_int { } // Accessor macros for times -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] macro_rules! _PyDateTime_GET_HOUR { ($o: expr, $offset:expr) => { c_int::from((*$o).data[$offset + 0]) }; } -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] macro_rules! _PyDateTime_GET_MINUTE { ($o: expr, $offset:expr) => { c_int::from((*$o).data[$offset + 1]) }; } -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] macro_rules! _PyDateTime_GET_SECOND { ($o: expr, $offset:expr) => { c_int::from((*$o).data[$offset + 2]) }; } -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] macro_rules! _PyDateTime_GET_MICROSECOND { ($o: expr, $offset:expr) => { (c_int::from((*$o).data[$offset + 3]) << 16) @@ -179,14 +181,14 @@ macro_rules! _PyDateTime_GET_MICROSECOND { }; } -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] macro_rules! _PyDateTime_GET_FOLD { ($o: expr) => { (*$o).fold }; } -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] macro_rules! _PyDateTime_GET_TZINFO { ($o: expr) => { if (*$o).hastzinfo != 0 { @@ -199,7 +201,7 @@ macro_rules! _PyDateTime_GET_TZINFO { // Accessor functions for DateTime #[inline] -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the hour component of a `PyDateTime_DateTime`. /// Returns a signed integer in the interval `[0, 23]` pub unsafe fn PyDateTime_DATE_GET_HOUR(o: *mut PyObject) -> c_int { @@ -207,7 +209,7 @@ pub unsafe fn PyDateTime_DATE_GET_HOUR(o: *mut PyObject) -> c_int { } #[inline] -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the minute component of a `PyDateTime_DateTime`. /// Returns a signed integer in the interval `[0, 59]` pub unsafe fn PyDateTime_DATE_GET_MINUTE(o: *mut PyObject) -> c_int { @@ -215,7 +217,7 @@ pub unsafe fn PyDateTime_DATE_GET_MINUTE(o: *mut PyObject) -> c_int { } #[inline] -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the second component of a `PyDateTime_DateTime`. /// Returns a signed integer in the interval `[0, 59]` pub unsafe fn PyDateTime_DATE_GET_SECOND(o: *mut PyObject) -> c_int { @@ -223,7 +225,7 @@ pub unsafe fn PyDateTime_DATE_GET_SECOND(o: *mut PyObject) -> c_int { } #[inline] -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the microsecond component of a `PyDateTime_DateTime`. /// Returns a signed integer in the interval `[0, 999999]` pub unsafe fn PyDateTime_DATE_GET_MICROSECOND(o: *mut PyObject) -> c_int { @@ -231,7 +233,7 @@ pub unsafe fn PyDateTime_DATE_GET_MICROSECOND(o: *mut PyObject) -> c_int { } #[inline] -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the fold component of a `PyDateTime_DateTime`. /// Returns a signed integer in the interval `[0, 1]` pub unsafe fn PyDateTime_DATE_GET_FOLD(o: *mut PyObject) -> c_uchar { @@ -239,7 +241,7 @@ pub unsafe fn PyDateTime_DATE_GET_FOLD(o: *mut PyObject) -> c_uchar { } #[inline] -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the tzinfo component of a `PyDateTime_DateTime`. /// Returns a pointer to a `PyObject` that should be either NULL or an instance /// of a `datetime.tzinfo` subclass. @@ -249,7 +251,7 @@ pub unsafe fn PyDateTime_DATE_GET_TZINFO(o: *mut PyObject) -> *mut PyObject { // Accessor functions for Time #[inline] -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the hour component of a `PyDateTime_Time`. /// Returns a signed integer in the interval `[0, 23]` pub unsafe fn PyDateTime_TIME_GET_HOUR(o: *mut PyObject) -> c_int { @@ -257,7 +259,7 @@ pub unsafe fn PyDateTime_TIME_GET_HOUR(o: *mut PyObject) -> c_int { } #[inline] -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the minute component of a `PyDateTime_Time`. /// Returns a signed integer in the interval `[0, 59]` pub unsafe fn PyDateTime_TIME_GET_MINUTE(o: *mut PyObject) -> c_int { @@ -265,7 +267,7 @@ pub unsafe fn PyDateTime_TIME_GET_MINUTE(o: *mut PyObject) -> c_int { } #[inline] -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the second component of a `PyDateTime_DateTime`. /// Returns a signed integer in the interval `[0, 59]` pub unsafe fn PyDateTime_TIME_GET_SECOND(o: *mut PyObject) -> c_int { @@ -273,14 +275,14 @@ pub unsafe fn PyDateTime_TIME_GET_SECOND(o: *mut PyObject) -> c_int { } #[inline] -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the microsecond component of a `PyDateTime_DateTime`. /// Returns a signed integer in the interval `[0, 999999]` pub unsafe fn PyDateTime_TIME_GET_MICROSECOND(o: *mut PyObject) -> c_int { _PyDateTime_GET_MICROSECOND!((o as *mut PyDateTime_Time), 0) } -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] #[inline] /// Retrieve the fold component of a `PyDateTime_Time`. /// Returns a signed integer in the interval `[0, 1]` @@ -289,7 +291,7 @@ pub unsafe fn PyDateTime_TIME_GET_FOLD(o: *mut PyObject) -> c_uchar { } #[inline] -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the tzinfo component of a `PyDateTime_Time`. /// Returns a pointer to a `PyObject` that should be either NULL or an instance /// of a `datetime.tzinfo` subclass. @@ -298,7 +300,7 @@ pub unsafe fn PyDateTime_TIME_GET_TZINFO(o: *mut PyObject) -> *mut PyObject { } // Accessor functions -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] macro_rules! _access_field { ($obj:expr, $type: ident, $field:ident) => { (*($obj as *mut $type)).$field @@ -306,7 +308,7 @@ macro_rules! _access_field { } // Accessor functions for PyDateTime_Delta -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] macro_rules! _access_delta_field { ($obj:expr, $field:ident) => { _access_field!($obj, PyDateTime_Delta, $field) @@ -314,7 +316,7 @@ macro_rules! _access_delta_field { } #[inline] -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the days component of a `PyDateTime_Delta`. /// /// Returns a signed integer in the interval [-999999999, 999999999]. @@ -326,7 +328,7 @@ pub unsafe fn PyDateTime_DELTA_GET_DAYS(o: *mut PyObject) -> c_int { } #[inline] -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the seconds component of a `PyDateTime_Delta`. /// /// Returns a signed integer in the interval [0, 86399]. @@ -338,7 +340,7 @@ pub unsafe fn PyDateTime_DELTA_GET_SECONDS(o: *mut PyObject) -> c_int { } #[inline] -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the seconds component of a `PyDateTime_Delta`. /// /// Returns a signed integer in the interval [0, 999999]. @@ -349,6 +351,132 @@ pub unsafe fn PyDateTime_DELTA_GET_MICROSECONDS(o: *mut PyObject) -> c_int { _access_delta_field!(o, microseconds) } +// Accessor functions for GraalPy. The macros on GraalPy work differently, +// but copying them seems suboptimal +#[inline] +#[cfg(GraalPy)] +pub unsafe fn _get_attr(obj: *mut PyObject, field: &str) -> c_int { + let result = PyObject_GetAttrString(obj, field.as_ptr() as *const c_char); + Py_DecRef(result); // the original macros are borrowing + if PyLong_Check(result) == 1 { + PyLong_AsLong(result) as c_int + } else { + 0 + } +} + +#[inline] +#[cfg(GraalPy)] +pub unsafe fn PyDateTime_GET_YEAR(o: *mut PyObject) -> c_int { + _get_attr(o, "year\0") +} + +#[inline] +#[cfg(GraalPy)] +pub unsafe fn PyDateTime_GET_MONTH(o: *mut PyObject) -> c_int { + _get_attr(o, "month\0") +} + +#[inline] +#[cfg(GraalPy)] +pub unsafe fn PyDateTime_GET_DAY(o: *mut PyObject) -> c_int { + _get_attr(o, "day\0") +} + +#[inline] +#[cfg(GraalPy)] +pub unsafe fn PyDateTime_DATE_GET_HOUR(o: *mut PyObject) -> c_int { + _get_attr(o, "hour\0") +} + +#[inline] +#[cfg(GraalPy)] +pub unsafe fn PyDateTime_DATE_GET_MINUTE(o: *mut PyObject) -> c_int { + _get_attr(o, "minute\0") +} + +#[inline] +#[cfg(GraalPy)] +pub unsafe fn PyDateTime_DATE_GET_SECOND(o: *mut PyObject) -> c_int { + _get_attr(o, "second\0") +} + +#[inline] +#[cfg(GraalPy)] +pub unsafe fn PyDateTime_DATE_GET_MICROSECOND(o: *mut PyObject) -> c_int { + _get_attr(o, "microsecond\0") +} + +#[inline] +#[cfg(GraalPy)] +pub unsafe fn PyDateTime_DATE_GET_FOLD(o: *mut PyObject) -> c_int { + _get_attr(o, "fold\0") +} + +#[inline] +#[cfg(GraalPy)] +pub unsafe fn PyDateTime_DATE_GET_TZINFO(o: *mut PyObject) -> *mut PyObject { + let res = PyObject_GetAttrString(o, "tzinfo\0".as_ptr() as *const c_char); + Py_DecRef(res); // the original macros are borrowing + res +} + +#[inline] +#[cfg(GraalPy)] +pub unsafe fn PyDateTime_TIME_GET_HOUR(o: *mut PyObject) -> c_int { + _get_attr(o, "hour\0") +} + +#[inline] +#[cfg(GraalPy)] +pub unsafe fn PyDateTime_TIME_GET_MINUTE(o: *mut PyObject) -> c_int { + _get_attr(o, "minute\0") +} + +#[inline] +#[cfg(GraalPy)] +pub unsafe fn PyDateTime_TIME_GET_SECOND(o: *mut PyObject) -> c_int { + _get_attr(o, "second\0") +} + +#[inline] +#[cfg(GraalPy)] +pub unsafe fn PyDateTime_TIME_GET_MICROSECOND(o: *mut PyObject) -> c_int { + _get_attr(o, "microsecond\0") +} + +#[inline] +#[cfg(GraalPy)] +pub unsafe fn PyDateTime_TIME_GET_FOLD(o: *mut PyObject) -> c_int { + _get_attr(o, "fold\0") +} + +#[inline] +#[cfg(GraalPy)] +pub unsafe fn PyDateTime_TIME_GET_TZINFO(o: *mut PyObject) -> *mut PyObject { + let res = PyObject_GetAttrString(o, "tzinfo\0".as_ptr() as *const c_char); + Py_DecRef(res); // the original macros are borrowing + res +} + +#[inline] +#[cfg(GraalPy)] +pub unsafe fn PyDateTime_DELTA_GET_DAYS(o: *mut PyObject) -> c_int { + _get_attr(o, "days\0") +} + +#[inline] +#[cfg(GraalPy)] +pub unsafe fn PyDateTime_DELTA_GET_SECONDS(o: *mut PyObject) -> c_int { + _get_attr(o, "seconds\0") +} + +#[inline] +#[cfg(GraalPy)] +pub unsafe fn PyDateTime_DELTA_GET_MICROSECONDS(o: *mut PyObject) -> c_int { + _get_attr(o, "microseconds\0") +} + #[cfg(PyPy)] extern "C" { // skipped _PyDateTime_HAS_TZINFO (not in PyPy) diff --git a/pyo3-ffi/src/dictobject.rs b/pyo3-ffi/src/dictobject.rs index 8d522df9..99fc56b2 100644 --- a/pyo3-ffi/src/dictobject.rs +++ b/pyo3-ffi/src/dictobject.rs @@ -109,6 +109,6 @@ extern "C" { pub static mut PyDictRevIterItem_Type: PyTypeObject; } -#[cfg(any(PyPy, Py_LIMITED_API))] +#[cfg(any(PyPy, GraalPy, Py_LIMITED_API))] // TODO: remove (see https://github.com/PyO3/pyo3/pull/1341#issuecomment-751515985) opaque_struct!(PyDictObject); diff --git a/pyo3-ffi/src/listobject.rs b/pyo3-ffi/src/listobject.rs index 32c6a2dc..a6f47ead 100644 --- a/pyo3-ffi/src/listobject.rs +++ b/pyo3-ffi/src/listobject.rs @@ -54,14 +54,16 @@ extern "C" { #[cfg_attr(PyPy, link_name = "PyPyList_AsTuple")] pub fn PyList_AsTuple(arg1: *mut PyObject) -> *mut PyObject; - // CPython macros exported as functions on PyPy - #[cfg(PyPy)] + // CPython macros exported as functions on PyPy or GraalPy + #[cfg(any(PyPy, GraalPy))] #[cfg_attr(PyPy, link_name = "PyPyList_GET_ITEM")] + #[cfg_attr(GraalPy, link_name = "PyList_GetItem")] pub fn PyList_GET_ITEM(arg1: *mut PyObject, arg2: Py_ssize_t) -> *mut PyObject; #[cfg(PyPy)] #[cfg_attr(PyPy, link_name = "PyPyList_GET_SIZE")] pub fn PyList_GET_SIZE(arg1: *mut PyObject) -> Py_ssize_t; - #[cfg(PyPy)] + #[cfg(any(PyPy, GraalPy))] #[cfg_attr(PyPy, link_name = "PyPyList_SET_ITEM")] + #[cfg_attr(GraalPy, link_name = "_PyList_SET_ITEM")] pub fn PyList_SET_ITEM(arg1: *mut PyObject, arg2: Py_ssize_t, arg3: *mut PyObject); } diff --git a/pyo3-ffi/src/methodobject.rs b/pyo3-ffi/src/methodobject.rs index e80d5668..3ed6b770 100644 --- a/pyo3-ffi/src/methodobject.rs +++ b/pyo3-ffi/src/methodobject.rs @@ -4,7 +4,7 @@ use crate::PyObject_TypeCheck; use std::os::raw::{c_char, c_int, c_void}; use std::{mem, ptr}; -#[cfg(all(Py_3_9, not(Py_LIMITED_API)))] +#[cfg(all(Py_3_9, not(Py_LIMITED_API), not(GraalPy)))] pub struct PyCFunctionObject { pub ob_base: PyObject, pub m_ml: *mut PyMethodDef, diff --git a/pyo3-ffi/src/object.rs b/pyo3-ffi/src/object.rs index 0e0243cd..b33ee558 100644 --- a/pyo3-ffi/src/object.rs +++ b/pyo3-ffi/src/object.rs @@ -79,6 +79,7 @@ pub struct PyObject { #[derive(Debug, Copy, Clone)] pub struct PyVarObject { pub ob_base: PyObject, + #[cfg(not(GraalPy))] pub ob_size: Py_ssize_t, } @@ -98,12 +99,18 @@ pub unsafe fn Py_REFCNT(ob: *mut PyObject) -> Py_ssize_t { #[inline] #[cfg(not(Py_3_12))] pub unsafe fn Py_REFCNT(ob: *mut PyObject) -> Py_ssize_t { - (*ob).ob_refcnt + #[cfg(not(GraalPy))] + return (*ob).ob_refcnt; + #[cfg(GraalPy)] + return _Py_REFCNT(ob); } #[inline] pub unsafe fn Py_TYPE(ob: *mut PyObject) -> *mut PyTypeObject { - (*ob).ob_type + #[cfg(not(GraalPy))] + return (*ob).ob_type; + #[cfg(GraalPy)] + return _Py_TYPE(ob); } // PyLong_Type defined in longobject.rs @@ -111,9 +118,14 @@ pub unsafe fn Py_TYPE(ob: *mut PyObject) -> *mut PyTypeObject { #[inline] pub unsafe fn Py_SIZE(ob: *mut PyObject) -> Py_ssize_t { - debug_assert_ne!((*ob).ob_type, std::ptr::addr_of_mut!(crate::PyLong_Type)); - debug_assert_ne!((*ob).ob_type, std::ptr::addr_of_mut!(crate::PyBool_Type)); - (*ob.cast::()).ob_size + #[cfg(not(GraalPy))] + { + debug_assert_ne!((*ob).ob_type, std::ptr::addr_of_mut!(crate::PyLong_Type)); + debug_assert_ne!((*ob).ob_type, std::ptr::addr_of_mut!(crate::PyBool_Type)); + (*ob.cast::()).ob_size + } + #[cfg(GraalPy)] + _Py_SIZE(ob) } #[inline] @@ -464,8 +476,10 @@ extern "C" { pub fn _Py_Dealloc(arg1: *mut PyObject); #[cfg_attr(PyPy, link_name = "PyPy_IncRef")] + #[cfg_attr(GraalPy, link_name = "_Py_IncRef")] pub fn Py_IncRef(o: *mut PyObject); #[cfg_attr(PyPy, link_name = "PyPy_DecRef")] + #[cfg_attr(GraalPy, link_name = "_Py_DecRef")] pub fn Py_DecRef(o: *mut PyObject); #[cfg(Py_3_10)] @@ -474,11 +488,21 @@ extern "C" { #[cfg(Py_3_10)] #[cfg_attr(PyPy, link_name = "_PyPy_DecRef")] pub fn _Py_DecRef(o: *mut PyObject); + + #[cfg(GraalPy)] + pub fn _Py_REFCNT(arg1: *const PyObject) -> Py_ssize_t; + + #[cfg(GraalPy)] + pub fn _Py_TYPE(arg1: *const PyObject) -> *mut PyTypeObject; + + #[cfg(GraalPy)] + pub fn _Py_SIZE(arg1: *const PyObject) -> Py_ssize_t; } #[inline(always)] pub unsafe fn Py_INCREF(op: *mut PyObject) { #[cfg(any( + GraalPy, all(Py_LIMITED_API, Py_3_12), all( py_sys_config = "Py_REF_DEBUG", @@ -499,6 +523,7 @@ pub unsafe fn Py_INCREF(op: *mut PyObject) { all(Py_LIMITED_API, not(Py_3_12)), all( not(Py_LIMITED_API), + not(GraalPy), any( not(py_sys_config = "Py_REF_DEBUG"), all(py_sys_config = "Py_REF_DEBUG", Py_3_12), @@ -544,6 +569,7 @@ pub unsafe fn Py_INCREF(op: *mut PyObject) { )] pub unsafe fn Py_DECREF(op: *mut PyObject) { #[cfg(any( + GraalPy, all(Py_LIMITED_API, Py_3_12), all( py_sys_config = "Py_REF_DEBUG", @@ -564,6 +590,7 @@ pub unsafe fn Py_DECREF(op: *mut PyObject) { all(Py_LIMITED_API, not(Py_3_12)), all( not(Py_LIMITED_API), + not(GraalPy), any( not(py_sys_config = "Py_REF_DEBUG"), all(py_sys_config = "Py_REF_DEBUG", Py_3_12), @@ -669,13 +696,20 @@ pub unsafe fn Py_XNewRef(obj: *mut PyObject) -> *mut PyObject { #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { + #[cfg(not(GraalPy))] #[cfg_attr(PyPy, link_name = "_PyPy_NoneStruct")] static mut _Py_NoneStruct: PyObject; + + #[cfg(GraalPy)] + static mut _Py_NoneStructReference: *mut PyObject; } #[inline] pub unsafe fn Py_None() -> *mut PyObject { - ptr::addr_of_mut!(_Py_NoneStruct) + #[cfg(not(GraalPy))] + return ptr::addr_of_mut!(_Py_NoneStruct); + #[cfg(GraalPy)] + return _Py_NoneStructReference; } #[inline] @@ -687,13 +721,20 @@ pub unsafe fn Py_IsNone(x: *mut PyObject) -> c_int { #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { + #[cfg(not(GraalPy))] #[cfg_attr(PyPy, link_name = "_PyPy_NotImplementedStruct")] static mut _Py_NotImplementedStruct: PyObject; + + #[cfg(GraalPy)] + static mut _Py_NotImplementedStructReference: *mut PyObject; } #[inline] pub unsafe fn Py_NotImplemented() -> *mut PyObject { - ptr::addr_of_mut!(_Py_NotImplementedStruct) + #[cfg(not(GraalPy))] + return ptr::addr_of_mut!(_Py_NotImplementedStruct); + #[cfg(GraalPy)] + return _Py_NotImplementedStructReference; } // skipped Py_RETURN_NOTIMPLEMENTED diff --git a/pyo3-ffi/src/pyframe.rs b/pyo3-ffi/src/pyframe.rs index 43a9d1f6..4dd3d2b3 100644 --- a/pyo3-ffi/src/pyframe.rs +++ b/pyo3-ffi/src/pyframe.rs @@ -1,3 +1,4 @@ +#[cfg(not(GraalPy))] #[cfg(any(Py_3_10, all(Py_3_9, not(Py_LIMITED_API))))] use crate::PyCodeObject; #[cfg(not(Py_LIMITED_API))] @@ -9,6 +10,7 @@ opaque_struct!(PyFrameObject); extern "C" { pub fn PyFrame_GetLineNumber(f: *mut PyFrameObject) -> c_int; + #[cfg(not(GraalPy))] #[cfg(any(Py_3_10, all(Py_3_9, not(Py_LIMITED_API))))] pub fn PyFrame_GetCode(f: *mut PyFrameObject) -> *mut PyCodeObject; } diff --git a/pyo3-ffi/src/pyhash.rs b/pyo3-ffi/src/pyhash.rs index f8072d85..f42f9730 100644 --- a/pyo3-ffi/src/pyhash.rs +++ b/pyo3-ffi/src/pyhash.rs @@ -1,6 +1,6 @@ -#[cfg(not(any(Py_LIMITED_API, PyPy)))] +#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] use crate::pyport::{Py_hash_t, Py_ssize_t}; -#[cfg(not(any(Py_LIMITED_API, PyPy)))] +#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] use std::os::raw::{c_char, c_void}; use std::os::raw::{c_int, c_ulong}; @@ -10,7 +10,7 @@ extern "C" { // skipped non-limited _Py_HashPointer // skipped non-limited _Py_HashPointerRaw - #[cfg(not(any(Py_LIMITED_API, PyPy)))] + #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] pub fn _Py_HashBytes(src: *const c_void, len: Py_ssize_t) -> Py_hash_t; } @@ -20,7 +20,7 @@ pub const _PyHASH_MULTIPLIER: c_ulong = 1000003; // skipped non-limited _Py_HashSecret_t -#[cfg(not(any(Py_LIMITED_API, PyPy)))] +#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyHash_FuncDef { @@ -30,7 +30,7 @@ pub struct PyHash_FuncDef { pub seed_bits: c_int, } -#[cfg(not(any(Py_LIMITED_API, PyPy)))] +#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] impl Default for PyHash_FuncDef { #[inline] fn default() -> Self { @@ -39,7 +39,7 @@ impl Default for PyHash_FuncDef { } extern "C" { - #[cfg(not(any(Py_LIMITED_API, PyPy)))] + #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] pub fn PyHash_GetFuncDef() -> *mut PyHash_FuncDef; } diff --git a/pyo3-ffi/src/pythonrun.rs b/pyo3-ffi/src/pythonrun.rs index e5f20de0..10985b60 100644 --- a/pyo3-ffi/src/pythonrun.rs +++ b/pyo3-ffi/src/pythonrun.rs @@ -1,12 +1,12 @@ use crate::object::*; #[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))] use libc::FILE; -#[cfg(all(not(PyPy), any(Py_LIMITED_API, not(Py_3_10))))] +#[cfg(all(not(PyPy), any(Py_LIMITED_API, not(Py_3_10), GraalPy)))] use std::os::raw::c_char; use std::os::raw::c_int; extern "C" { - #[cfg(all(Py_LIMITED_API, not(PyPy)))] + #[cfg(any(all(Py_LIMITED_API, not(PyPy)), GraalPy))] pub fn Py_CompileString(string: *const c_char, p: *const c_char, s: c_int) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyErr_Print")] diff --git a/pyo3-ffi/src/setobject.rs b/pyo3-ffi/src/setobject.rs index 84a368a7..9d5351fc 100644 --- a/pyo3-ffi/src/setobject.rs +++ b/pyo3-ffi/src/setobject.rs @@ -1,5 +1,5 @@ use crate::object::*; -#[cfg(not(any(Py_LIMITED_API, PyPy)))] +#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] use crate::pyport::Py_hash_t; use crate::pyport::Py_ssize_t; use std::os::raw::c_int; @@ -7,7 +7,7 @@ use std::ptr::addr_of_mut; pub const PySet_MINSIZE: usize = 8; -#[cfg(not(any(Py_LIMITED_API, PyPy)))] +#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] #[repr(C)] #[derive(Debug)] pub struct setentry { @@ -15,7 +15,7 @@ pub struct setentry { pub hash: Py_hash_t, } -#[cfg(not(any(Py_LIMITED_API, PyPy)))] +#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] #[repr(C)] #[derive(Debug)] pub struct PySetObject { @@ -32,7 +32,7 @@ pub struct PySetObject { // skipped #[inline] -#[cfg(all(not(PyPy), not(Py_LIMITED_API)))] +#[cfg(all(not(any(PyPy, GraalPy)), not(Py_LIMITED_API)))] pub unsafe fn PySet_GET_SIZE(so: *mut PyObject) -> Py_ssize_t { debug_assert_eq!(PyAnySet_Check(so), 1); let so = so.cast::(); @@ -92,7 +92,7 @@ extern "C" { } #[inline] -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] pub unsafe fn PyFrozenSet_CheckExact(ob: *mut PyObject) -> c_int { (Py_TYPE(ob) == addr_of_mut!(PyFrozenSet_Type)) as c_int } diff --git a/pyo3-ffi/src/sliceobject.rs b/pyo3-ffi/src/sliceobject.rs index 6f09906f..a3ea1539 100644 --- a/pyo3-ffi/src/sliceobject.rs +++ b/pyo3-ffi/src/sliceobject.rs @@ -5,21 +5,31 @@ use std::ptr::addr_of_mut; #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { + #[cfg(not(GraalPy))] #[cfg_attr(PyPy, link_name = "_PyPy_EllipsisObject")] static mut _Py_EllipsisObject: PyObject; + + #[cfg(GraalPy)] + static mut _Py_EllipsisObjectReference: *mut PyObject; } #[inline] pub unsafe fn Py_Ellipsis() -> *mut PyObject { - addr_of_mut!(_Py_EllipsisObject) + #[cfg(not(GraalPy))] + return addr_of_mut!(_Py_EllipsisObject); + #[cfg(GraalPy)] + return _Py_EllipsisObjectReference; } #[cfg(not(Py_LIMITED_API))] #[repr(C)] pub struct PySliceObject { pub ob_base: PyObject, + #[cfg(not(GraalPy))] pub start: *mut PyObject, + #[cfg(not(GraalPy))] pub stop: *mut PyObject, + #[cfg(not(GraalPy))] pub step: *mut PyObject, } diff --git a/pyo3-ffi/src/structseq.rs b/pyo3-ffi/src/structseq.rs index 6dfc1daf..f8566787 100644 --- a/pyo3-ffi/src/structseq.rs +++ b/pyo3-ffi/src/structseq.rs @@ -42,13 +42,13 @@ extern "C" { #[cfg(not(Py_LIMITED_API))] pub type PyStructSequence = crate::PyTupleObject; -#[cfg(not(any(Py_LIMITED_API, PyPy)))] +#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] #[inline] pub unsafe fn PyStructSequence_SET_ITEM(op: *mut PyObject, i: Py_ssize_t, v: *mut PyObject) { crate::PyTuple_SET_ITEM(op, i, v) } -#[cfg(not(any(Py_LIMITED_API, PyPy)))] +#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] #[inline] pub unsafe fn PyStructSequence_GET_ITEM(op: *mut PyObject, i: Py_ssize_t) -> *mut PyObject { crate::PyTuple_GET_ITEM(op, i) diff --git a/pyo3-ffi/src/weakrefobject.rs b/pyo3-ffi/src/weakrefobject.rs index d065ae23..7e11a901 100644 --- a/pyo3-ffi/src/weakrefobject.rs +++ b/pyo3-ffi/src/weakrefobject.rs @@ -3,10 +3,10 @@ use std::os::raw::c_int; #[cfg(not(PyPy))] use std::ptr::addr_of_mut; -#[cfg(all(not(PyPy), Py_LIMITED_API))] +#[cfg(all(not(PyPy), Py_LIMITED_API, not(GraalPy)))] opaque_struct!(PyWeakReference); -#[cfg(all(not(PyPy), not(Py_LIMITED_API)))] +#[cfg(all(not(PyPy), not(Py_LIMITED_API), not(GraalPy)))] pub use crate::_PyWeakReference as PyWeakReference; #[cfg_attr(windows, link(name = "pythonXY"))] diff --git a/pytests/tests/test_awaitable.py b/pytests/tests/test_awaitable.py index 2bada317..40f1e1cc 100644 --- a/pytests/tests/test_awaitable.py +++ b/pytests/tests/test_awaitable.py @@ -1,13 +1,22 @@ import pytest +import sys from pyo3_pytests.awaitable import IterAwaitable, FutureAwaitable +@pytest.mark.skipif( + sys.implementation.name == "graalpy", + reason="GraalPy's asyncio module has a bug with native classes, see oracle/graalpython#365", +) @pytest.mark.asyncio async def test_iter_awaitable(): assert await IterAwaitable(5) == 5 +@pytest.mark.skipif( + sys.implementation.name == "graalpy", + reason="GraalPy's asyncio module has a bug with native classes, see oracle/graalpython#365", +) @pytest.mark.asyncio async def test_future_awaitable(): assert await FutureAwaitable(5) == 5 diff --git a/pytests/tests/test_misc.py b/pytests/tests/test_misc.py index 6645f942..de75f1c8 100644 --- a/pytests/tests/test_misc.py +++ b/pytests/tests/test_misc.py @@ -27,8 +27,8 @@ def test_multiple_imports_same_interpreter_ok(): reason="Cannot identify subinterpreters on Python older than 3.9", ) @pytest.mark.skipif( - platform.python_implementation() == "PyPy", - reason="PyPy does not support subinterpreters", + platform.python_implementation() in ("PyPy", "GraalVM"), + reason="PyPy and GraalPy do not support subinterpreters", ) def test_import_in_subinterpreter_forbidden(): import _xxsubinterpreters diff --git a/pytests/tests/test_objstore.py b/pytests/tests/test_objstore.py index bfd8bad8..3f0d23fa 100644 --- a/pytests/tests/test_objstore.py +++ b/pytests/tests/test_objstore.py @@ -12,6 +12,11 @@ def test_objstore_doesnot_leak_memory(): # check refcount on PyPy getrefcount = getattr(sys, "getrefcount", lambda obj: 0) + if sys.implementation.name == "graalpy": + # GraalPy has an incomplete sys.getrefcount implementation + def getrefcount(obj): + return 0 + before = getrefcount(message) store = ObjStore() for _ in range(N): diff --git a/src/conversions/std/num.rs b/src/conversions/std/num.rs index 02798246..44843141 100644 --- a/src/conversions/std/num.rs +++ b/src/conversions/std/num.rs @@ -175,7 +175,7 @@ int_convert_u64_or_i64!( true ); -#[cfg(not(Py_LIMITED_API))] +#[cfg(all(not(Py_LIMITED_API), not(GraalPy)))] mod fast_128bit_int_conversion { use super::*; @@ -242,7 +242,7 @@ mod fast_128bit_int_conversion { } // For ABI3 we implement the conversion manually. -#[cfg(Py_LIMITED_API)] +#[cfg(any(Py_LIMITED_API, GraalPy))] mod slow_128bit_int_conversion { use super::*; const SHIFT: usize = 64; diff --git a/src/err/mod.rs b/src/err/mod.rs index de1e621f..8dd16b26 100644 --- a/src/err/mod.rs +++ b/src/err/mod.rs @@ -863,8 +863,17 @@ impl PyErr { /// associated with the exception, as accessible from Python through `__cause__`. pub fn cause(&self, py: Python<'_>) -> Option { use crate::ffi_ptr_ext::FfiPtrExt; - unsafe { ffi::PyException_GetCause(self.value_bound(py).as_ptr()).assume_owned_or_opt(py) } - .map(Self::from_value_bound) + let obj = unsafe { + ffi::PyException_GetCause(self.value_bound(py).as_ptr()).assume_owned_or_opt(py) + }; + // PyException_GetCause is documented as potentially returning PyNone, but only GraalPy seems to actually do that + #[cfg(GraalPy)] + if let Some(cause) = &obj { + if cause.is_none() { + return None; + } + } + obj.map(Self::from_value_bound) } /// Set the cause associated with the exception, pass `None` to clear it. diff --git a/src/exceptions.rs b/src/exceptions.rs index bd9c89c4..add95825 100644 --- a/src/exceptions.rs +++ b/src/exceptions.rs @@ -409,14 +409,14 @@ impl_native_exception!( PyExc_FloatingPointError, native_doc!("FloatingPointError") ); -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] impl_native_exception!( PyOSError, PyExc_OSError, native_doc!("OSError"), ffi::PyOSErrorObject ); -#[cfg(PyPy)] +#[cfg(any(PyPy, GraalPy))] impl_native_exception!(PyOSError, PyExc_OSError, native_doc!("OSError")); impl_native_exception!(PyImportError, PyExc_ImportError, native_doc!("ImportError")); @@ -455,14 +455,14 @@ impl_native_exception!( PyExc_NotImplementedError, native_doc!("NotImplementedError") ); -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] impl_native_exception!( PySyntaxError, PyExc_SyntaxError, native_doc!("SyntaxError"), ffi::PySyntaxErrorObject ); -#[cfg(PyPy)] +#[cfg(any(PyPy, GraalPy))] impl_native_exception!(PySyntaxError, PyExc_SyntaxError, native_doc!("SyntaxError")); impl_native_exception!( PyReferenceError, @@ -470,14 +470,14 @@ impl_native_exception!( native_doc!("ReferenceError") ); impl_native_exception!(PySystemError, PyExc_SystemError, native_doc!("SystemError")); -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] impl_native_exception!( PySystemExit, PyExc_SystemExit, native_doc!("SystemExit"), ffi::PySystemExitObject ); -#[cfg(PyPy)] +#[cfg(any(PyPy, GraalPy))] impl_native_exception!(PySystemExit, PyExc_SystemExit, native_doc!("SystemExit")); impl_native_exception!(PyTypeError, PyExc_TypeError, native_doc!("TypeError")); impl_native_exception!( @@ -485,14 +485,14 @@ impl_native_exception!( PyExc_UnboundLocalError, native_doc!("UnboundLocalError") ); -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] impl_native_exception!( PyUnicodeError, PyExc_UnicodeError, native_doc!("UnicodeError"), ffi::PyUnicodeErrorObject ); -#[cfg(PyPy)] +#[cfg(any(PyPy, GraalPy))] impl_native_exception!( PyUnicodeError, PyExc_UnicodeError, diff --git a/src/gil.rs b/src/gil.rs index 5ca3167e..bb07489f 100644 --- a/src/gil.rs +++ b/src/gil.rs @@ -78,7 +78,7 @@ fn gil_is_acquired() -> bool { /// Python::with_gil(|py| py.run_bound("print('Hello World')", None, None)) /// # } /// ``` -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] pub fn prepare_freethreaded_python() { // Protect against race conditions when Python is not yet initialized and multiple threads // concurrently call 'prepare_freethreaded_python()'. Note that we do not protect against @@ -125,7 +125,7 @@ pub fn prepare_freethreaded_python() { /// }); /// } /// ``` -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] pub unsafe fn with_embedded_python_interpreter(f: F) -> R where F: for<'p> FnOnce(Python<'p>) -> R, @@ -182,14 +182,14 @@ impl GILGuard { // auto-initialize so this avoids breaking existing builds. // - Otherwise, just check the GIL is initialized. cfg_if::cfg_if! { - if #[cfg(all(feature = "auto-initialize", not(PyPy)))] { + if #[cfg(all(feature = "auto-initialize", not(any(PyPy, GraalPy))))] { prepare_freethreaded_python(); } else { // This is a "hack" to make running `cargo test` for PyO3 convenient (i.e. no need // to specify `--features auto-initialize` manually. Tests within the crate itself // all depend on the auto-initialize feature for conciseness but Cargo does not // provide a mechanism to specify required features for tests. - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] if option_env!("CARGO_PRIMARY_PACKAGE").is_some() { prepare_freethreaded_python(); } diff --git a/src/impl_/pymodule.rs b/src/impl_/pymodule.rs index 9ca80e39..ba13f7a9 100644 --- a/src/impl_/pymodule.rs +++ b/src/impl_/pymodule.rs @@ -2,10 +2,14 @@ use std::cell::UnsafeCell; -#[cfg(all(not(PyPy), Py_3_9, not(all(windows, Py_LIMITED_API, not(Py_3_10)))))] +#[cfg(all( + not(any(PyPy, GraalPy)), + Py_3_9, + not(all(windows, Py_LIMITED_API, not(Py_3_10))) +))] use portable_atomic::{AtomicI64, Ordering}; -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] use crate::exceptions::PyImportError; use crate::{ffi, sync::GILOnceCell, types::PyModule, Bound, Py, PyResult, Python}; @@ -15,7 +19,11 @@ pub struct ModuleDef { ffi_def: UnsafeCell, initializer: ModuleInitializer, /// Interpreter ID where module was initialized (not applicable on PyPy). - #[cfg(all(not(PyPy), Py_3_9, not(all(windows, Py_LIMITED_API, not(Py_3_10)))))] + #[cfg(all( + not(any(PyPy, GraalPy)), + Py_3_9, + not(all(windows, Py_LIMITED_API, not(Py_3_10))) + ))] interpreter: AtomicI64, /// Initialized module object, cached to avoid reinitialization. module: GILOnceCell>, @@ -58,7 +66,11 @@ impl ModuleDef { ffi_def, initializer, // -1 is never expected to be a valid interpreter ID - #[cfg(all(not(PyPy), Py_3_9, not(all(windows, Py_LIMITED_API, not(Py_3_10)))))] + #[cfg(all( + not(any(PyPy, GraalPy)), + Py_3_9, + not(all(windows, Py_LIMITED_API, not(Py_3_10))) + ))] interpreter: AtomicI64::new(-1), module: GILOnceCell::new(), } @@ -85,7 +97,7 @@ impl ModuleDef { // that static data is not reused across interpreters. // // PyPy does not have subinterpreters, so no need to check interpreter ID. - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] { // PyInterpreterState_Get is only available on 3.9 and later, but is missing // from python3.dll for Windows stable API on 3.9 diff --git a/src/impl_/trampoline.rs b/src/impl_/trampoline.rs index 4d77f329..db493817 100644 --- a/src/impl_/trampoline.rs +++ b/src/impl_/trampoline.rs @@ -24,12 +24,14 @@ pub unsafe fn module_init( } #[inline] +#[allow(clippy::used_underscore_binding)] pub unsafe fn noargs( slf: *mut ffi::PyObject, - args: *mut ffi::PyObject, + _args: *mut ffi::PyObject, f: for<'py> unsafe fn(Python<'py>, *mut ffi::PyObject) -> PyResult<*mut ffi::PyObject>, ) -> *mut ffi::PyObject { - debug_assert!(args.is_null()); + #[cfg(not(GraalPy))] // this is not specified and GraalPy does not pass null here + debug_assert!(_args.is_null()); trampoline(|py| f(py, slf)) } diff --git a/src/lib.rs b/src/lib.rs index fd5a520f..e444912a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -321,7 +321,7 @@ pub use crate::err::{ }; #[allow(deprecated)] pub use crate::gil::GILPool; -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] pub use crate::gil::{prepare_freethreaded_python, with_embedded_python_interpreter}; pub use crate::instance::{Borrowed, Bound, Py, PyNativeType, PyObject}; pub use crate::marker::Python; diff --git a/src/macros.rs b/src/macros.rs index 648bac18..09e2acfb 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -201,7 +201,7 @@ macro_rules! wrap_pymodule { /// /// Use it before [`prepare_freethreaded_python`](crate::prepare_freethreaded_python) and /// leave feature `auto-initialize` off -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] #[macro_export] macro_rules! append_to_inittab { ($module:ident) => { diff --git a/src/marker.rs b/src/marker.rs index 08b90424..67119b5e 100644 --- a/src/marker.rs +++ b/src/marker.rs @@ -400,7 +400,7 @@ impl Python<'_> { /// If the [`auto-initialize`] feature is enabled and the Python runtime is not already /// initialized, this function will initialize it. See #[cfg_attr( - not(PyPy), + not(any(PyPy, GraalPy)), doc = "[`prepare_freethreaded_python`](crate::prepare_freethreaded_python)" )] #[cfg_attr(PyPy, doc = "`prepare_freethreaded_python`")] diff --git a/src/types/any.rs b/src/types/any.rs index 19855abb..ab4f5727 100644 --- a/src/types/any.rs +++ b/src/types/any.rs @@ -6,7 +6,7 @@ use crate::ffi_ptr_ext::FfiPtrExt; use crate::instance::Bound; use crate::py_result_ext::PyResultExt; use crate::type_object::{HasPyGilRef, PyTypeCheck, PyTypeInfo}; -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] use crate::types::PySuper; use crate::types::{PyDict, PyIterator, PyList, PyString, PyTuple, PyType}; use crate::{err, ffi, Py, PyNativeType, Python}; @@ -929,7 +929,7 @@ impl PyAny { /// Return a proxy object that delegates method calls to a parent or sibling class of type. /// /// This is equivalent to the Python expression `super()` - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub fn py_super(&self) -> PyResult<&PySuper> { self.as_borrowed().py_super().map(Bound::into_gil_ref) } @@ -1708,7 +1708,7 @@ pub trait PyAnyMethods<'py>: crate::sealed::Sealed { /// Return a proxy object that delegates method calls to a parent or sibling class of type. /// /// This is equivalent to the Python expression `super()` - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] fn py_super(&self) -> PyResult>; } @@ -1975,6 +1975,7 @@ impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> { cfg_if::cfg_if! { if #[cfg(all( not(PyPy), + not(GraalPy), any(Py_3_10, all(not(Py_LIMITED_API), Py_3_9)) // PyObject_CallNoArgs was added to python in 3.9 but to limited API in 3.10 ))] { // Optimized path on python 3.9+ @@ -2010,7 +2011,7 @@ impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> { N: IntoPy>, { cfg_if::cfg_if! { - if #[cfg(all(Py_3_9, not(any(Py_LIMITED_API, PyPy))))] { + if #[cfg(all(Py_3_9, not(any(Py_LIMITED_API, PyPy, GraalPy))))] { let py = self.py(); // Optimized path on python 3.9+ @@ -2265,7 +2266,7 @@ impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> { inner(self, value.to_object(py).into_bound(py)) } - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] fn py_super(&self) -> PyResult> { PySuper::new_bound(&self.get_type(), self) } diff --git a/src/types/complex.rs b/src/types/complex.rs index 80ecffdc..e711b054 100644 --- a/src/types/complex.rs +++ b/src/types/complex.rs @@ -53,7 +53,7 @@ impl PyComplex { } } -#[cfg(not(any(Py_LIMITED_API, PyPy)))] +#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] mod not_limited_impls { use crate::ffi_ptr_ext::FfiPtrExt; use crate::Borrowed; @@ -264,10 +264,10 @@ pub trait PyComplexMethods<'py>: crate::sealed::Sealed { /// Returns the imaginary part of the complex number. fn imag(&self) -> c_double; /// Returns `|self|`. - #[cfg(not(any(Py_LIMITED_API, PyPy)))] + #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] fn abs(&self) -> c_double; /// Returns `self` raised to the power of `other`. - #[cfg(not(any(Py_LIMITED_API, PyPy)))] + #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] fn pow(&self, other: &Bound<'py, PyComplex>) -> Bound<'py, PyComplex>; } @@ -280,7 +280,7 @@ impl<'py> PyComplexMethods<'py> for Bound<'py, PyComplex> { unsafe { ffi::PyComplex_ImagAsDouble(self.as_ptr()) } } - #[cfg(not(any(Py_LIMITED_API, PyPy)))] + #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] fn abs(&self) -> c_double { unsafe { let val = (*self.as_ptr().cast::()).cval; @@ -288,7 +288,7 @@ impl<'py> PyComplexMethods<'py> for Bound<'py, PyComplex> { } } - #[cfg(not(any(Py_LIMITED_API, PyPy)))] + #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] fn pow(&self, other: &Bound<'py, PyComplex>) -> Bound<'py, PyComplex> { use crate::ffi_ptr_ext::FfiPtrExt; unsafe { diff --git a/src/types/datetime.rs b/src/types/datetime.rs index d46a2b77..e1620a6f 100644 --- a/src/types/datetime.rs +++ b/src/types/datetime.rs @@ -11,6 +11,8 @@ use crate::ffi::{ PyDateTime_DATE_GET_FOLD, PyDateTime_DATE_GET_HOUR, PyDateTime_DATE_GET_MICROSECOND, PyDateTime_DATE_GET_MINUTE, PyDateTime_DATE_GET_SECOND, }; +#[cfg(GraalPy)] +use crate::ffi::{PyDateTime_DATE_GET_TZINFO, PyDateTime_TIME_GET_TZINFO, Py_IsNone}; use crate::ffi::{ PyDateTime_DELTA_GET_DAYS, PyDateTime_DELTA_GET_MICROSECONDS, PyDateTime_DELTA_GET_SECONDS, }; @@ -552,6 +554,7 @@ impl<'py> PyTzInfoAccess<'py> for &'py PyDateTime { impl<'py> PyTzInfoAccess<'py> for Bound<'py, PyDateTime> { fn get_tzinfo_bound(&self) -> Option> { let ptr = self.as_ptr() as *mut ffi::PyDateTime_DateTime; + #[cfg(not(GraalPy))] unsafe { if (*ptr).hastzinfo != 0 { Some( @@ -565,6 +568,20 @@ impl<'py> PyTzInfoAccess<'py> for Bound<'py, PyDateTime> { None } } + + #[cfg(GraalPy)] + unsafe { + let res = PyDateTime_DATE_GET_TZINFO(ptr as *mut ffi::PyObject); + if Py_IsNone(res) == 1 { + None + } else { + Some( + res.assume_borrowed(self.py()) + .to_owned() + .downcast_into_unchecked(), + ) + } + } } } @@ -740,6 +757,7 @@ impl<'py> PyTzInfoAccess<'py> for &'py PyTime { impl<'py> PyTzInfoAccess<'py> for Bound<'py, PyTime> { fn get_tzinfo_bound(&self) -> Option> { let ptr = self.as_ptr() as *mut ffi::PyDateTime_Time; + #[cfg(not(GraalPy))] unsafe { if (*ptr).hastzinfo != 0 { Some( @@ -753,6 +771,20 @@ impl<'py> PyTzInfoAccess<'py> for Bound<'py, PyTime> { None } } + + #[cfg(GraalPy)] + unsafe { + let res = PyDateTime_TIME_GET_TZINFO(ptr as *mut ffi::PyObject); + if Py_IsNone(res) == 1 { + None + } else { + Some( + res.assume_borrowed(self.py()) + .to_owned() + .downcast_into_unchecked(), + ) + } + } } } diff --git a/src/types/dict.rs b/src/types/dict.rs index 43bade5a..a4ba72a5 100644 --- a/src/types/dict.rs +++ b/src/types/dict.rs @@ -20,11 +20,11 @@ pyobject_native_type!( ); /// Represents a Python `dict_keys`. -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] #[repr(transparent)] pub struct PyDictKeys(PyAny); -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] pyobject_native_type_core!( PyDictKeys, pyobject_native_static_type_object!(ffi::PyDictKeys_Type), @@ -32,11 +32,11 @@ pyobject_native_type_core!( ); /// Represents a Python `dict_values`. -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] #[repr(transparent)] pub struct PyDictValues(PyAny); -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] pyobject_native_type_core!( PyDictValues, pyobject_native_static_type_object!(ffi::PyDictValues_Type), @@ -44,11 +44,11 @@ pyobject_native_type_core!( ); /// Represents a Python `dict_items`. -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] #[repr(transparent)] pub struct PyDictItems(PyAny); -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] pyobject_native_type_core!( PyDictItems, pyobject_native_static_type_object!(ffi::PyDictItems_Type), @@ -76,14 +76,14 @@ impl PyDict { /// Deprecated form of [`from_sequence_bound`][PyDict::from_sequence_bound]. #[cfg_attr( - all(not(PyPy), not(feature = "gil-refs")), + all(not(any(PyPy, GraalPy)), not(feature = "gil-refs")), deprecated( since = "0.21.0", note = "`PyDict::from_sequence` will be replaced by `PyDict::from_sequence_bound` in a future PyO3 version" ) )] #[inline] - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub fn from_sequence(seq: &PyAny) -> PyResult<&PyDict> { Self::from_sequence_bound(&seq.as_borrowed()).map(Bound::into_gil_ref) } @@ -95,7 +95,7 @@ impl PyDict { /// /// Returns an error on invalid input. In the case of key collisions, /// this keeps the last entry seen. - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub fn from_sequence_bound<'py>(seq: &Bound<'py, PyAny>) -> PyResult> { let py = seq.py(); let dict = Self::new_bound(py); @@ -542,12 +542,12 @@ impl<'a, 'py> Borrowed<'a, 'py, PyDict> { } fn dict_len(dict: &Bound<'_, PyDict>) -> Py_ssize_t { - #[cfg(any(not(Py_3_8), PyPy, Py_LIMITED_API))] + #[cfg(any(not(Py_3_8), PyPy, GraalPy, Py_LIMITED_API))] unsafe { ffi::PyDict_Size(dict.as_ptr()) } - #[cfg(all(Py_3_8, not(PyPy), not(Py_LIMITED_API)))] + #[cfg(all(Py_3_8, not(PyPy), not(GraalPy), not(Py_LIMITED_API)))] unsafe { (*dict.as_ptr().cast::()).ma_used } @@ -824,7 +824,7 @@ where #[cfg_attr(not(feature = "gil-refs"), allow(deprecated))] mod tests { use super::*; - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] use crate::exceptions; use crate::types::PyTuple; use std::collections::{BTreeMap, HashMap}; @@ -850,7 +850,7 @@ mod tests { } #[test] - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] fn test_from_sequence() { Python::with_gil(|py| { let items = PyList::new(py, &vec![("a", 1), ("b", 2)]); @@ -881,7 +881,7 @@ mod tests { } #[test] - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] fn test_from_sequence_err() { Python::with_gil(|py| { let items = PyList::new(py, &vec!["a", "b"]); @@ -955,7 +955,7 @@ mod tests { #[test] #[allow(deprecated)] - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] fn test_get_item_with_error() { Python::with_gil(|py| { let mut v = HashMap::new(); @@ -1388,7 +1388,7 @@ mod tests { }); } - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] fn abc_dict(py: Python<'_>) -> Bound<'_, PyDict> { let mut map = HashMap::<&'static str, i32>::new(); map.insert("a", 1); @@ -1398,7 +1398,7 @@ mod tests { } #[test] - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] fn dict_keys_view() { Python::with_gil(|py| { let dict = abc_dict(py); @@ -1410,7 +1410,7 @@ mod tests { } #[test] - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] fn dict_values_view() { Python::with_gil(|py| { let dict = abc_dict(py); @@ -1422,7 +1422,7 @@ mod tests { } #[test] - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] fn dict_items_view() { Python::with_gil(|py| { let dict = abc_dict(py); diff --git a/src/types/frozenset.rs b/src/types/frozenset.rs index 8a60efb8..36d5578f 100644 --- a/src/types/frozenset.rs +++ b/src/types/frozenset.rs @@ -60,7 +60,7 @@ impl<'py> PyFrozenSetBuilder<'py> { #[repr(transparent)] pub struct PyFrozenSet(PyAny); -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] pyobject_native_type!( PyFrozenSet, ffi::PySetObject, @@ -68,7 +68,7 @@ pyobject_native_type!( #checkfunction=ffi::PyFrozenSet_Check ); -#[cfg(PyPy)] +#[cfg(any(PyPy, GraalPy))] pyobject_native_type_core!( PyFrozenSet, pyobject_native_static_type_object!(ffi::PyFrozenSet_Type), diff --git a/src/types/mod.rs b/src/types/mod.rs index cee45e86..5448999d 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -5,7 +5,7 @@ pub use self::boolobject::{PyBool, PyBoolMethods}; pub use self::bytearray::{PyByteArray, PyByteArrayMethods}; pub use self::bytes::{PyBytes, PyBytesMethods}; pub use self::capsule::{PyCapsule, PyCapsuleMethods}; -#[cfg(all(not(Py_LIMITED_API), not(PyPy)))] +#[cfg(all(not(Py_LIMITED_API), not(PyPy), not(GraalPy)))] pub use self::code::PyCode; pub use self::complex::{PyComplex, PyComplexMethods}; #[allow(deprecated)] @@ -17,15 +17,15 @@ pub use self::datetime::{ PyTimeAccess, PyTzInfo, PyTzInfoAccess, }; pub use self::dict::{IntoPyDict, PyDict, PyDictMethods}; -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] pub use self::dict::{PyDictItems, PyDictKeys, PyDictValues}; pub use self::ellipsis::PyEllipsis; pub use self::float::{PyFloat, PyFloatMethods}; -#[cfg(all(not(Py_LIMITED_API), not(PyPy)))] +#[cfg(all(not(Py_LIMITED_API), not(PyPy), not(GraalPy)))] pub use self::frame::PyFrame; pub use self::frozenset::{PyFrozenSet, PyFrozenSetBuilder, PyFrozenSetMethods}; pub use self::function::PyCFunction; -#[cfg(all(not(Py_LIMITED_API), not(PyPy)))] +#[cfg(all(not(Py_LIMITED_API), not(PyPy), not(GraalPy)))] pub use self::function::PyFunction; pub use self::iterator::PyIterator; pub use self::list::{PyList, PyListMethods}; @@ -36,7 +36,7 @@ pub use self::none::PyNone; pub use self::notimplemented::PyNotImplemented; pub use self::num::PyLong; pub use self::num::PyLong as PyInt; -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] pub use self::pysuper::PySuper; pub use self::sequence::{PySequence, PySequenceMethods}; pub use self::set::{PySet, PySetMethods}; @@ -328,7 +328,7 @@ pub(crate) mod boolobject; pub(crate) mod bytearray; pub(crate) mod bytes; pub(crate) mod capsule; -#[cfg(all(not(Py_LIMITED_API), not(PyPy)))] +#[cfg(all(not(Py_LIMITED_API), not(PyPy), not(GraalPy)))] mod code; pub(crate) mod complex; #[cfg(not(Py_LIMITED_API))] @@ -336,7 +336,7 @@ pub(crate) mod datetime; pub(crate) mod dict; mod ellipsis; pub(crate) mod float; -#[cfg(all(not(Py_LIMITED_API), not(PyPy)))] +#[cfg(all(not(Py_LIMITED_API), not(PyPy), not(GraalPy)))] mod frame; pub(crate) mod frozenset; mod function; @@ -348,7 +348,7 @@ pub(crate) mod module; mod none; mod notimplemented; mod num; -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] mod pysuper; pub(crate) mod sequence; pub(crate) mod set; diff --git a/src/types/sequence.rs b/src/types/sequence.rs index 62abb66f..2b37b6d1 100644 --- a/src/types/sequence.rs +++ b/src/types/sequence.rs @@ -134,7 +134,7 @@ impl PySequence { /// Returns the number of occurrences of `value` in self, that is, return the /// number of keys for which `self[key] == value`. #[inline] - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] pub fn count(&self, value: V) -> PyResult where V: ToPyObject, @@ -870,7 +870,7 @@ mod tests { } #[test] - #[cfg(not(PyPy))] + #[cfg(not(any(PyPy, GraalPy)))] fn test_seq_count() { Python::with_gil(|py| { let v: Vec = vec![1, 1, 2, 3, 5, 8]; diff --git a/src/types/set.rs b/src/types/set.rs index c043fa5b..4f1fcf84 100644 --- a/src/types/set.rs +++ b/src/types/set.rs @@ -14,7 +14,7 @@ use std::ptr; #[repr(transparent)] pub struct PySet(PyAny); -#[cfg(not(PyPy))] +#[cfg(not(any(PyPy, GraalPy)))] pyobject_native_type!( PySet, ffi::PySetObject, @@ -22,7 +22,7 @@ pyobject_native_type!( #checkfunction=ffi::PySet_Check ); -#[cfg(PyPy)] +#[cfg(any(PyPy, GraalPy))] pyobject_native_type_core!( PySet, pyobject_native_static_type_object!(ffi::PySet_Type), diff --git a/src/types/string.rs b/src/types/string.rs index 81c41adb..4bbc6fb8 100644 --- a/src/types/string.rs +++ b/src/types/string.rs @@ -270,7 +270,7 @@ impl PyString { /// /// By using this API, you accept responsibility for testing that PyStringData behaves as /// expected on the targets where you plan to distribute your software. - #[cfg(not(Py_LIMITED_API))] + #[cfg(not(any(Py_LIMITED_API, GraalPy)))] pub unsafe fn data(&self) -> PyResult> { self.as_borrowed().data() } @@ -319,7 +319,7 @@ pub trait PyStringMethods<'py>: crate::sealed::Sealed { /// /// By using this API, you accept responsibility for testing that PyStringData behaves as /// expected on the targets where you plan to distribute your software. - #[cfg(not(Py_LIMITED_API))] + #[cfg(not(any(Py_LIMITED_API, GraalPy)))] unsafe fn data(&self) -> PyResult>; } @@ -345,7 +345,7 @@ impl<'py> PyStringMethods<'py> for Bound<'py, PyString> { } } - #[cfg(not(Py_LIMITED_API))] + #[cfg(not(any(Py_LIMITED_API, GraalPy)))] unsafe fn data(&self) -> PyResult> { self.as_borrowed().data() } @@ -408,7 +408,7 @@ impl<'a> Borrowed<'a, '_, PyString> { Cow::Owned(String::from_utf8_lossy(bytes.as_bytes()).into_owned()) } - #[cfg(not(Py_LIMITED_API))] + #[cfg(not(any(Py_LIMITED_API, GraalPy)))] unsafe fn data(self) -> PyResult> { let ptr = self.as_ptr(); diff --git a/src/types/tuple.rs b/src/types/tuple.rs index 4dfe4436..636a2f3e 100644 --- a/src/types/tuple.rs +++ b/src/types/tuple.rs @@ -34,9 +34,9 @@ fn new_from_iter<'py>( let mut counter: Py_ssize_t = 0; for obj in elements.take(len as usize) { - #[cfg(not(any(Py_LIMITED_API, PyPy)))] + #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] ffi::PyTuple_SET_ITEM(ptr, counter, obj.into_ptr()); - #[cfg(any(Py_LIMITED_API, PyPy))] + #[cfg(any(Py_LIMITED_API, PyPy, GraalPy))] ffi::PyTuple_SetItem(ptr, counter, obj.into_ptr()); counter += 1; } @@ -186,7 +186,7 @@ impl PyTuple { /// # Safety /// /// Caller must verify that the index is within the bounds of the tuple. - #[cfg(not(any(Py_LIMITED_API, PyPy)))] + #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] pub unsafe fn get_item_unchecked(&self, index: usize) -> &PyAny { self.as_borrowed() .get_borrowed_item_unchecked(index) @@ -194,7 +194,7 @@ impl PyTuple { } /// Returns `self` as a slice of objects. - #[cfg(not(Py_LIMITED_API))] + #[cfg(not(any(Py_LIMITED_API, GraalPy)))] pub fn as_slice(&self) -> &[&PyAny] { // This is safe because &PyAny has the same memory layout as *mut ffi::PyObject, // and because tuples are immutable. @@ -293,7 +293,7 @@ pub trait PyTupleMethods<'py>: crate::sealed::Sealed { /// # Safety /// /// Caller must verify that the index is within the bounds of the tuple. - #[cfg(not(any(Py_LIMITED_API, PyPy)))] + #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] unsafe fn get_item_unchecked(&self, index: usize) -> Bound<'py, PyAny>; /// Like [`get_item_unchecked`][PyTupleMethods::get_item_unchecked], but returns a borrowed object, @@ -302,11 +302,11 @@ pub trait PyTupleMethods<'py>: crate::sealed::Sealed { /// # Safety /// /// Caller must verify that the index is within the bounds of the tuple. - #[cfg(not(any(Py_LIMITED_API, PyPy)))] + #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] unsafe fn get_borrowed_item_unchecked<'a>(&'a self, index: usize) -> Borrowed<'a, 'py, PyAny>; /// Returns `self` as a slice of objects. - #[cfg(not(Py_LIMITED_API))] + #[cfg(not(any(Py_LIMITED_API, GraalPy)))] fn as_slice(&self) -> &[Bound<'py, PyAny>]; /// Determines if self contains `value`. @@ -339,9 +339,9 @@ pub trait PyTupleMethods<'py>: crate::sealed::Sealed { impl<'py> PyTupleMethods<'py> for Bound<'py, PyTuple> { fn len(&self) -> usize { unsafe { - #[cfg(not(any(Py_LIMITED_API, PyPy)))] + #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] let size = ffi::PyTuple_GET_SIZE(self.as_ptr()); - #[cfg(any(Py_LIMITED_API, PyPy))] + #[cfg(any(Py_LIMITED_API, PyPy, GraalPy))] let size = ffi::PyTuple_Size(self.as_ptr()); // non-negative Py_ssize_t should always fit into Rust uint size as usize @@ -376,17 +376,17 @@ impl<'py> PyTupleMethods<'py> for Bound<'py, PyTuple> { self.as_borrowed().get_borrowed_item(index) } - #[cfg(not(any(Py_LIMITED_API, PyPy)))] + #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] unsafe fn get_item_unchecked(&self, index: usize) -> Bound<'py, PyAny> { self.get_borrowed_item_unchecked(index).to_owned() } - #[cfg(not(any(Py_LIMITED_API, PyPy)))] + #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] unsafe fn get_borrowed_item_unchecked<'a>(&'a self, index: usize) -> Borrowed<'a, 'py, PyAny> { self.as_borrowed().get_borrowed_item_unchecked(index) } - #[cfg(not(Py_LIMITED_API))] + #[cfg(not(any(Py_LIMITED_API, GraalPy)))] fn as_slice(&self) -> &[Bound<'py, PyAny>] { // This is safe because Bound<'py, PyAny> has the same memory layout as *mut ffi::PyObject, // and because tuples are immutable. @@ -436,7 +436,7 @@ impl<'a, 'py> Borrowed<'a, 'py, PyTuple> { } } - #[cfg(not(any(Py_LIMITED_API, PyPy)))] + #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] unsafe fn get_borrowed_item_unchecked(self, index: usize) -> Borrowed<'a, 'py, PyAny> { ffi::PyTuple_GET_ITEM(self.as_ptr(), index as Py_ssize_t).assume_borrowed(self.py()) } @@ -591,9 +591,9 @@ impl<'a, 'py> BorrowedTupleIterator<'a, 'py> { tuple: Borrowed<'a, 'py, PyTuple>, index: usize, ) -> Borrowed<'a, 'py, PyAny> { - #[cfg(any(Py_LIMITED_API, PyPy))] + #[cfg(any(Py_LIMITED_API, PyPy, GraalPy))] let item = tuple.get_borrowed_item(index).expect("tuple.get failed"); - #[cfg(not(any(Py_LIMITED_API, PyPy)))] + #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] let item = tuple.get_borrowed_item_unchecked(index); item } @@ -696,10 +696,10 @@ fn type_output() -> TypeInfo { { let t = obj.downcast::()?; if t.len() == $length { - #[cfg(any(Py_LIMITED_API, PyPy))] + #[cfg(any(Py_LIMITED_API, PyPy, GraalPy))] return Ok(($(t.get_borrowed_item($n)?.extract::<$T>()?,)+)); - #[cfg(not(any(Py_LIMITED_API, PyPy)))] + #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] unsafe {return Ok(($(t.get_borrowed_item_unchecked($n).extract::<$T>()?,)+));} } else { Err(wrong_tuple_length(t, $length)) @@ -718,9 +718,9 @@ fn array_into_tuple(py: Python<'_>, array: [PyObject; N]) -> Py< let ptr = ffi::PyTuple_New(N.try_into().expect("0 < N <= 12")); let tup = Py::from_owned_ptr(py, ptr); for (index, obj) in array.into_iter().enumerate() { - #[cfg(not(any(Py_LIMITED_API, PyPy)))] + #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] ffi::PyTuple_SET_ITEM(ptr, index as ffi::Py_ssize_t, obj.into_ptr()); - #[cfg(any(Py_LIMITED_API, PyPy))] + #[cfg(any(Py_LIMITED_API, PyPy, GraalPy))] ffi::PyTuple_SetItem(ptr, index as ffi::Py_ssize_t, obj.into_ptr()); } tup @@ -1010,7 +1010,7 @@ mod tests { } #[test] - #[cfg(not(Py_LIMITED_API))] + #[cfg(not(any(Py_LIMITED_API, GraalPy)))] fn test_as_slice() { Python::with_gil(|py| { let ob = (1, 2, 3).to_object(py); @@ -1112,7 +1112,7 @@ mod tests { }); } - #[cfg(not(any(Py_LIMITED_API, PyPy)))] + #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] #[test] fn test_tuple_get_item_unchecked_sanity() { Python::with_gil(|py| { @@ -1457,7 +1457,7 @@ mod tests { .unwrap(), 2 ); - #[cfg(not(any(Py_LIMITED_API, PyPy)))] + #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] { assert_eq!( unsafe { tuple.get_item_unchecked(2) }