This commit is contained in:
Michael Šimáček 2024-09-20 12:51:17 +00:00 committed by GitHub
commit cfa5cd38c0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
41 changed files with 158 additions and 50 deletions

View File

@ -39,6 +39,7 @@ jobs:
- 'pypy-3.8' - 'pypy-3.8'
- 'pypy-3.9' - 'pypy-3.9'
- 'pypy-3.10' - 'pypy-3.10'
- 'graalpy-24.1'
# Items in here will either be added to the build matrix (if not # Items in here will either be added to the build matrix (if not
# present), or add new keys to an existing matrix element if all the # present), or add new keys to an existing matrix element if all the
@ -67,6 +68,10 @@ jobs:
# Extra ubuntu latest job # Extra ubuntu latest job
- runs-on: ubuntu-latest - runs-on: ubuntu-latest
python: '3.11' python: '3.11'
exclude:
# The setup-python action currently doesn't have graalpy for windows
- python: 'graalpy-24.1'
runs-on: 'windows-2022'
name: "🐍 ${{ matrix.python }} • ${{ matrix.runs-on }} • x64 ${{ matrix.args }}" name: "🐍 ${{ matrix.python }} • ${{ matrix.runs-on }} • x64 ${{ matrix.args }}"

View File

@ -343,7 +343,7 @@ public:
#else #else
// Alternate approach for CPython: this does the same as the above, but optimized // Alternate approach for CPython: this does the same as the above, but optimized
// using the CPython API so as to avoid an unneeded attribute lookup. // using the CPython API so as to avoid an unneeded attribute lookup.
else if (auto *tp_as_number = src.ptr()->ob_type->tp_as_number) { else if (auto *tp_as_number = Py_TYPE(src.ptr())->tp_as_number) {
if (PYBIND11_NB_BOOL(tp_as_number)) { if (PYBIND11_NB_BOOL(tp_as_number)) {
res = (*PYBIND11_NB_BOOL(tp_as_number))(src.ptr()); res = (*PYBIND11_NB_BOOL(tp_as_number))(src.ptr());
} }

View File

@ -299,7 +299,7 @@ PYBIND11_WARNING_DISABLE_MSVC(4505)
# define PYBIND11_INTERNAL_NUMPY_1_ONLY_DETECTED # define PYBIND11_INTERNAL_NUMPY_1_ONLY_DETECTED
#endif #endif
#if defined(PYPY_VERSION) && !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT) #if (defined(PYPY_VERSION) || defined(GRAALVM_PYTHON)) && !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
# define PYBIND11_SIMPLE_GIL_MANAGEMENT # define PYBIND11_SIMPLE_GIL_MANAGEMENT
#endif #endif

View File

@ -454,7 +454,7 @@ inline void translate_local_exception(std::exception_ptr p) {
inline object get_python_state_dict() { inline object get_python_state_dict() {
object state_dict; object state_dict;
#if PYBIND11_INTERNALS_VERSION <= 4 || defined(PYPY_VERSION) #if PYBIND11_INTERNALS_VERSION <= 4 || defined(PYPY_VERSION) || defined(GRAALVM_PYTHON)
state_dict = reinterpret_borrow<object>(PyEval_GetBuiltins()); state_dict = reinterpret_borrow<object>(PyEval_GetBuiltins());
#else #else
# if PY_VERSION_HEX < 0x03090000 # if PY_VERSION_HEX < 0x03090000

View File

@ -459,7 +459,7 @@ PYBIND11_NOINLINE handle get_object_handle(const void *ptr, const detail::type_i
} }
inline PyThreadState *get_thread_state_unchecked() { inline PyThreadState *get_thread_state_unchecked() {
#if defined(PYPY_VERSION) #if defined(PYPY_VERSION) || defined(GRAALVM_PYTHON)
return PyThreadState_GET(); return PyThreadState_GET();
#elif PY_VERSION_HEX < 0x030D0000 #elif PY_VERSION_HEX < 0x030D0000
return _PyThreadState_UncheckedGet(); return _PyThreadState_UncheckedGet();

View File

@ -94,18 +94,18 @@ void exec(const char (&s)[N], object global = globals(), object local = object()
eval<eval_statements>(s, std::move(global), std::move(local)); eval<eval_statements>(s, std::move(global), std::move(local));
} }
#if defined(PYPY_VERSION) #if defined(PYPY_VERSION) || defined(GRAALVM_PYTHON)
template <eval_mode mode = eval_statements> template <eval_mode mode = eval_statements>
object eval_file(str, object, object) { object eval_file(str, object, object) {
pybind11_fail("eval_file not supported in PyPy3. Use eval"); pybind11_fail("eval_file not supported in PyPy3 or GraalPy. Use eval");
} }
template <eval_mode mode = eval_statements> template <eval_mode mode = eval_statements>
object eval_file(str, object) { object eval_file(str, object) {
pybind11_fail("eval_file not supported in PyPy3. Use eval"); pybind11_fail("eval_file not supported in PyPy3 or GraalPy. Use eval");
} }
template <eval_mode mode = eval_statements> template <eval_mode mode = eval_statements>
object eval_file(str) { object eval_file(str) {
pybind11_fail("eval_file not supported in PyPy3. Use eval"); pybind11_fail("eval_file not supported in PyPy3 or GraalPy. Use eval");
} }
#else #else
template <eval_mode mode = eval_statements> template <eval_mode mode = eval_statements>

View File

@ -573,8 +573,7 @@ protected:
// chain. // chain.
chain_start = rec; chain_start = rec;
rec->next = chain; rec->next = chain;
auto rec_capsule auto rec_capsule = reinterpret_borrow<capsule>(PyCFunction_GET_SELF(m_ptr));
= reinterpret_borrow<capsule>(((PyCFunctionObject *) m_ptr)->m_self);
rec_capsule.set_pointer(unique_rec.release()); rec_capsule.set_pointer(unique_rec.release());
guarded_strdup.release(); guarded_strdup.release();
} else { } else {
@ -636,10 +635,16 @@ protected:
/* Install docstring */ /* Install docstring */
auto *func = (PyCFunctionObject *) m_ptr; auto *func = (PyCFunctionObject *) m_ptr;
#if !defined(GRAALVM_PYTHON)
std::free(const_cast<char *>(func->m_ml->ml_doc)); std::free(const_cast<char *>(func->m_ml->ml_doc));
// Install docstring if it's non-empty (when at least one option is enabled) // Install docstring if it's non-empty (when at least one option is enabled)
func->m_ml->ml_doc func->m_ml->ml_doc
= signatures.empty() ? nullptr : PYBIND11_COMPAT_STRDUP(signatures.c_str()); = signatures.empty() ? nullptr : PYBIND11_COMPAT_STRDUP(signatures.c_str());
#else
std::free(const_cast<char *>(GraalPyCFunction_GetDoc(m_ptr)));
GraalPyCFunction_SetDoc(
m_ptr, signatures.empty() ? nullptr : PYBIND11_COMPAT_STRDUP(signatures.c_str()));
#endif
if (rec->is_method) { if (rec->is_method) {
m_ptr = PYBIND11_INSTANCE_METHOD_NEW(m_ptr, rec->scope.ptr()); m_ptr = PYBIND11_INSTANCE_METHOD_NEW(m_ptr, rec->scope.ptr());
@ -2780,8 +2785,8 @@ get_type_override(const void *this_ptr, const type_info *this_type, const char *
} }
/* Don't call dispatch code if invoked from overridden function. /* Don't call dispatch code if invoked from overridden function.
Unfortunately this doesn't work on PyPy. */ Unfortunately this doesn't work on PyPy and GraalPy. */
#if !defined(PYPY_VERSION) #if !defined(PYPY_VERSION) && !defined(GRAALVM_PYTHON)
# if PY_VERSION_HEX >= 0x03090000 # if PY_VERSION_HEX >= 0x03090000
PyFrameObject *frame = PyThreadState_GetFrame(PyThreadState_Get()); PyFrameObject *frame = PyThreadState_GetFrame(PyThreadState_Get());
if (frame != nullptr) { if (frame != nullptr) {

View File

@ -643,7 +643,7 @@ struct error_fetch_and_normalize {
bool have_trace = false; bool have_trace = false;
if (m_trace) { if (m_trace) {
#if !defined(PYPY_VERSION) #if !defined(PYPY_VERSION) && !defined(GRAALVM_PYTHON)
auto *tb = reinterpret_cast<PyTracebackObject *>(m_trace.ptr()); auto *tb = reinterpret_cast<PyTracebackObject *>(m_trace.ptr());
// Get the deepest trace possible. // Get the deepest trace possible.
@ -1356,7 +1356,7 @@ inline bool PyUnicode_Check_Permissive(PyObject *o) {
# define PYBIND11_STR_CHECK_FUN PyUnicode_Check # define PYBIND11_STR_CHECK_FUN PyUnicode_Check
#endif #endif
inline bool PyStaticMethod_Check(PyObject *o) { return o->ob_type == &PyStaticMethod_Type; } inline bool PyStaticMethod_Check(PyObject *o) { return Py_TYPE(o) == &PyStaticMethod_Type; }
class kwargs_proxy : public handle { class kwargs_proxy : public handle {
public: public:

View File

@ -28,8 +28,8 @@ except Exception:
@pytest.fixture(scope="session", autouse=True) @pytest.fixture(scope="session", autouse=True)
def use_multiprocessing_forkserver_on_linux(): def use_multiprocessing_forkserver_on_linux():
if sys.platform != "linux": if sys.platform != "linux" or sys.implementation.name == "graalpy":
# The default on Windows and macOS is "spawn": If it's not broken, don't fix it. # The default on Windows, macOS and GraalPy is "spawn": If it's not broken, don't fix it.
return return
# Full background: https://github.com/pybind/pybind11/issues/4105#issuecomment-1301004592 # Full background: https://github.com/pybind/pybind11/issues/4105#issuecomment-1301004592

View File

@ -12,6 +12,7 @@ WIN = sys.platform.startswith("win32") or sys.platform.startswith("cygwin")
CPYTHON = platform.python_implementation() == "CPython" CPYTHON = platform.python_implementation() == "CPython"
PYPY = platform.python_implementation() == "PyPy" PYPY = platform.python_implementation() == "PyPy"
GRAALPY = sys.implementation.name == "graalpy"
PY_GIL_DISABLED = bool(sysconfig.get_config_var("Py_GIL_DISABLED")) PY_GIL_DISABLED = bool(sysconfig.get_config_var("Py_GIL_DISABLED"))

View File

@ -2,11 +2,12 @@
build~=1.0; python_version>="3.8" build~=1.0; python_version>="3.8"
numpy~=1.23.0; python_version=="3.8" and platform_python_implementation=="PyPy" numpy~=1.23.0; python_version=="3.8" and platform_python_implementation=="PyPy"
numpy~=1.25.0; python_version=="3.9" and platform_python_implementation=='PyPy' numpy~=1.25.0; python_version=="3.9" and platform_python_implementation=='PyPy'
numpy~=1.21.5; platform_python_implementation!="PyPy" and python_version>="3.8" and python_version<"3.10" numpy~=1.26.0; platform_python_implementation=="GraalVM" and sys_platform=="linux"
numpy~=1.22.2; platform_python_implementation!="PyPy" and python_version=="3.10" numpy~=1.21.5; platform_python_implementation!="PyPy" and platform_python_implementation!="GraalVM" and python_version>="3.8" and python_version<"3.10"
numpy~=1.26.0; platform_python_implementation!="PyPy" and python_version>="3.11" and python_version<"3.13" numpy~=1.22.2; platform_python_implementation!="PyPy" and platform_python_implementation!="GraalVM" and python_version=="3.10"
numpy~=1.26.0; platform_python_implementation!="PyPy" and platform_python_implementation!="GraalVM" and python_version>="3.11" and python_version<"3.13"
pytest~=7.0 pytest~=7.0
pytest-timeout pytest-timeout
scipy~=1.5.4; platform_python_implementation!="PyPy" and python_version<"3.10" scipy~=1.5.4; platform_python_implementation!="PyPy" and platform_python_implementation!="GraalVM" and python_version<"3.10"
scipy~=1.8.0; platform_python_implementation!="PyPy" and python_version=="3.10" and sys_platform!='win32' scipy~=1.8.0; platform_python_implementation!="PyPy" and platform_python_implementation!="GraalVM" and python_version=="3.10" and sys_platform!='win32'
scipy~=1.11.1; platform_python_implementation!="PyPy" and python_version>="3.11" and python_version<"3.13" and sys_platform!='win32' scipy~=1.11.1; platform_python_implementation!="PyPy" and platform_python_implementation!="GraalVM" and python_version>="3.11" and python_version<"3.13" and sys_platform!='win32'

View File

@ -70,6 +70,7 @@ def test_format_descriptor_format_buffer_info_equiv(cpp_name, np_dtype):
assert not np_array_is_matching assert not np_array_is_matching
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_from_python(): def test_from_python():
with pytest.raises(RuntimeError) as excinfo: with pytest.raises(RuntimeError) as excinfo:
m.Matrix(np.array([1, 2, 3])) # trying to assign a 1D array m.Matrix(np.array([1, 2, 3])) # trying to assign a 1D array
@ -98,6 +99,7 @@ def test_from_python():
@pytest.mark.xfail( @pytest.mark.xfail(
env.PYPY, reason="PyPy 7.3.7 doesn't clear this anymore", strict=False env.PYPY, reason="PyPy 7.3.7 doesn't clear this anymore", strict=False
) )
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_to_python(): def test_to_python():
mat = m.Matrix(5, 4) mat = m.Matrix(5, 4)
assert memoryview(mat).shape == (5, 4) assert memoryview(mat).shape == (5, 4)

View File

@ -95,8 +95,8 @@ TEST_SUBMODULE(call_policies, m) {
}, },
py::call_guard<DependentGuard, CustomGuard>()); py::call_guard<DependentGuard, CustomGuard>());
#if !defined(PYPY_VERSION) #if !defined(PYPY_VERSION) && !defined(GRAALVM_PYTHON)
// `py::call_guard<py::gil_scoped_release>()` should work in PyPy as well, // `py::call_guard<py::gil_scoped_release>()` should work in PyPy/GraalPy as well,
// but it's unclear how to test it without `PyGILState_GetThisThreadState`. // but it's unclear how to test it without `PyGILState_GetThisThreadState`.
auto report_gil_status = []() { auto report_gil_status = []() {
auto is_gil_held = false; auto is_gil_held = false;

View File

@ -8,6 +8,7 @@ from pybind11_tests import call_policies as m
@pytest.mark.xfail("env.PYPY", reason="sometimes comes out 1 off on PyPy", strict=False) @pytest.mark.xfail("env.PYPY", reason="sometimes comes out 1 off on PyPy", strict=False)
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_keep_alive_argument(capture): def test_keep_alive_argument(capture):
n_inst = ConstructorStats.detail_reg_inst() n_inst = ConstructorStats.detail_reg_inst()
with capture: with capture:
@ -60,6 +61,7 @@ def test_keep_alive_argument(capture):
assert str(excinfo.value) == "Could not activate keep_alive!" assert str(excinfo.value) == "Could not activate keep_alive!"
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_keep_alive_return_value(capture): def test_keep_alive_return_value(capture):
n_inst = ConstructorStats.detail_reg_inst() n_inst = ConstructorStats.detail_reg_inst()
with capture: with capture:
@ -118,6 +120,7 @@ def test_keep_alive_return_value(capture):
# https://foss.heptapod.net/pypy/pypy/-/issues/2447 # https://foss.heptapod.net/pypy/pypy/-/issues/2447
@pytest.mark.xfail("env.PYPY", reason="_PyObject_GetDictPtr is unimplemented") @pytest.mark.xfail("env.PYPY", reason="_PyObject_GetDictPtr is unimplemented")
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_alive_gc(capture): def test_alive_gc(capture):
n_inst = ConstructorStats.detail_reg_inst() n_inst = ConstructorStats.detail_reg_inst()
p = m.ParentGC() p = m.ParentGC()
@ -137,6 +140,7 @@ def test_alive_gc(capture):
) )
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_alive_gc_derived(capture): def test_alive_gc_derived(capture):
class Derived(m.Parent): class Derived(m.Parent):
pass pass
@ -159,6 +163,7 @@ def test_alive_gc_derived(capture):
) )
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_alive_gc_multi_derived(capture): def test_alive_gc_multi_derived(capture):
class Derived(m.Parent, m.Child): class Derived(m.Parent, m.Child):
def __init__(self): def __init__(self):

View File

@ -90,6 +90,7 @@ def test_keyword_args_and_generalized_unpacking():
) )
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_lambda_closure_cleanup(): def test_lambda_closure_cleanup():
m.test_lambda_closure_cleanup() m.test_lambda_closure_cleanup()
cstats = m.payload_cstats() cstats = m.payload_cstats()
@ -98,6 +99,7 @@ def test_lambda_closure_cleanup():
assert cstats.move_constructions >= 1 assert cstats.move_constructions >= 1
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_cpp_callable_cleanup(): def test_cpp_callable_cleanup():
alive_counts = m.test_cpp_callable_cleanup() alive_counts = m.test_cpp_callable_cleanup()
assert alive_counts == [0, 1, 2, 1, 2, 1, 0] assert alive_counts == [0, 1, 2, 1, 2, 1, 0]

View File

@ -361,7 +361,7 @@ def test_brace_initialization():
assert b.vec == [123, 456] assert b.vec == [123, 456]
@pytest.mark.xfail("env.PYPY") @pytest.mark.xfail("env.PYPY or env.GRAALPY")
def test_class_refcount(): def test_class_refcount():
"""Instances must correctly increase/decrease the reference count of their types (#1029)""" """Instances must correctly increase/decrease the reference count of their types (#1029)"""
from sys import getrefcount from sys import getrefcount

View File

@ -55,8 +55,10 @@ possibly_uninitialized(PYTHON_MODULE_EXTENSION Python_INTERPRETER_ID)
pybind11_add_build_test(subdirectory_function) pybind11_add_build_test(subdirectory_function)
pybind11_add_build_test(subdirectory_target) pybind11_add_build_test(subdirectory_target)
if("${PYTHON_MODULE_EXTENSION}" MATCHES "pypy" OR "${Python_INTERPRETER_ID}" STREQUAL "PyPy") if("${PYTHON_MODULE_EXTENSION}" MATCHES "pypy"
message(STATUS "Skipping embed test on PyPy") OR "${Python_INTERPRETER_ID}" STREQUAL "PyPy"
OR "${PYTHON_MODULE_EXTENSION}" MATCHES "graalpy")
message(STATUS "Skipping embed test on PyPy or GraalPy")
else() else()
pybind11_add_build_test(subdirectory_embed) pybind11_add_build_test(subdirectory_embed)
endif() endif()
@ -68,8 +70,10 @@ if(PYBIND11_INSTALL)
pybind11_add_build_test(installed_function INSTALL) pybind11_add_build_test(installed_function INSTALL)
pybind11_add_build_test(installed_target INSTALL) pybind11_add_build_test(installed_target INSTALL)
if(NOT ("${PYTHON_MODULE_EXTENSION}" MATCHES "pypy" OR "${Python_INTERPRETER_ID}" STREQUAL "PyPy" if(NOT
)) ("${PYTHON_MODULE_EXTENSION}" MATCHES "pypy"
OR "${Python_INTERPRETER_ID}" STREQUAL "PyPy"
OR "${PYTHON_MODULE_EXTENSION}" MATCHES "graalpy"))
pybind11_add_build_test(installed_embed INSTALL) pybind11_add_build_test(installed_embed INSTALL)
endif() endif()
endif() endif()

View File

@ -7,6 +7,7 @@ import exo_planet_pybind11
import home_planet_very_lonely_traveler import home_planet_very_lonely_traveler
import pytest import pytest
import env # noqa: F401
from pybind11_tests import cpp_conduit as home_planet from pybind11_tests import cpp_conduit as home_planet
@ -20,6 +21,7 @@ def test_premium_traveler_getattr_actually_exists():
assert t_h.secret_name == "PremiumTraveler GetAttr: secret_name points: 7" assert t_h.secret_name == "PremiumTraveler GetAttr: secret_name points: 7"
@pytest.mark.xfail("env.GRAALPY", reason="TODO should get fixed on GraalPy side")
def test_call_cpp_conduit_success(): def test_call_cpp_conduit_success():
t_h = home_planet.Traveler("home") t_h = home_planet.Traveler("home")
cap = t_h._pybind11_conduit_v1_( cap = t_h._pybind11_conduit_v1_(

View File

@ -34,7 +34,7 @@ def gc_tester():
# PyPy does not seem to reliably garbage collect. # PyPy does not seem to reliably garbage collect.
@pytest.mark.skipif("env.PYPY") @pytest.mark.skipif("env.PYPY or env.GRAALPY")
def test_self_cycle(gc_tester): def test_self_cycle(gc_tester):
obj = m.OwnsPythonObjects() obj = m.OwnsPythonObjects()
obj.value = obj obj.value = obj
@ -42,7 +42,7 @@ def test_self_cycle(gc_tester):
# PyPy does not seem to reliably garbage collect. # PyPy does not seem to reliably garbage collect.
@pytest.mark.skipif("env.PYPY") @pytest.mark.skipif("env.PYPY or env.GRAALPY")
def test_indirect_cycle(gc_tester): def test_indirect_cycle(gc_tester):
obj = m.OwnsPythonObjects() obj = m.OwnsPythonObjects()
obj_list = [obj] obj_list = [obj]

View File

@ -2,6 +2,7 @@ from __future__ import annotations
import pytest import pytest
import env # noqa: F401
from pybind11_tests import ConstructorStats from pybind11_tests import ConstructorStats
np = pytest.importorskip("numpy") np = pytest.importorskip("numpy")
@ -409,6 +410,7 @@ def assert_keeps_alive(cl, method, *args):
assert cstats.alive() == start_with assert cstats.alive() == start_with
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_eigen_keepalive(): def test_eigen_keepalive():
a = m.ReturnTester() a = m.ReturnTester()
cstats = ConstructorStats.get(m.ReturnTester) cstats = ConstructorStats.get(m.ReturnTester)

View File

@ -4,6 +4,8 @@ import sys
import pytest import pytest
import env # noqa: F401
np = pytest.importorskip("numpy") np = pytest.importorskip("numpy")
eigen_tensor = pytest.importorskip("pybind11_tests.eigen_tensor") eigen_tensor = pytest.importorskip("pybind11_tests.eigen_tensor")
submodules = [eigen_tensor.c_style, eigen_tensor.f_style] submodules = [eigen_tensor.c_style, eigen_tensor.f_style]
@ -61,6 +63,7 @@ def assert_equal_tensor_ref(mat, writeable=True, modified=None):
@pytest.mark.parametrize("m", submodules) @pytest.mark.parametrize("m", submodules)
@pytest.mark.parametrize("member_name", ["member", "member_view"]) @pytest.mark.parametrize("member_name", ["member", "member_view"])
@pytest.mark.skipif("env.GRAALPY", reason="Different refcounting mechanism")
def test_reference_internal(m, member_name): def test_reference_internal(m, member_name):
if not hasattr(sys, "getrefcount"): if not hasattr(sys, "getrefcount"):
pytest.skip("No reference counting") pytest.skip("No reference counting")

View File

@ -1,8 +1,10 @@
possibly_uninitialized(PYTHON_MODULE_EXTENSION Python_INTERPRETER_ID) possibly_uninitialized(PYTHON_MODULE_EXTENSION Python_INTERPRETER_ID)
if("${PYTHON_MODULE_EXTENSION}" MATCHES "pypy" OR "${Python_INTERPRETER_ID}" STREQUAL "PyPy") if("${PYTHON_MODULE_EXTENSION}" MATCHES "pypy"
message(STATUS "Skipping embed test on PyPy") OR "${Python_INTERPRETER_ID}" STREQUAL "PyPy"
add_custom_target(cpptest) # Dummy target on PyPy. Embedding is not supported. OR "${PYTHON_MODULE_EXTENSION}" MATCHES "graalpy")
message(STATUS "Skipping embed test on PyPy or GraalPy")
add_custom_target(cpptest) # Dummy target on PyPy or GraalPy. Embedding is not supported.
set(_suppress_unused_variable_warning "${DOWNLOAD_CATCH}") set(_suppress_unused_variable_warning "${DOWNLOAD_CATCH}")
return() return()
endif() endif()

View File

@ -3,9 +3,11 @@ from __future__ import annotations
import pytest import pytest
import env # noqa: F401
from pybind11_tests import enums as m from pybind11_tests import enums as m
@pytest.mark.xfail("env.GRAALPY", reason="TODO should get fixed on GraalPy side")
def test_unscoped_enum(): def test_unscoped_enum():
assert str(m.UnscopedEnum.EOne) == "UnscopedEnum.EOne" assert str(m.UnscopedEnum.EOne) == "UnscopedEnum.EOne"
assert str(m.UnscopedEnum.ETwo) == "UnscopedEnum.ETwo" assert str(m.UnscopedEnum.ETwo) == "UnscopedEnum.ETwo"
@ -193,6 +195,7 @@ def test_implicit_conversion():
assert repr(x) == "{<EMode.EFirstMode: 1>: 3, <EMode.ESecondMode: 2>: 4}" assert repr(x) == "{<EMode.EFirstMode: 1>: 3, <EMode.ESecondMode: 2>: 4}"
@pytest.mark.xfail("env.GRAALPY", reason="TODO should get fixed on GraalPy side")
def test_binary_operators(): def test_binary_operators():
assert int(m.Flags.Read) == 4 assert int(m.Flags.Read) == 4
assert int(m.Flags.Write) == 2 assert int(m.Flags.Write) == 2

View File

@ -19,7 +19,7 @@ def test_evals(capture):
assert m.test_eval_failure() assert m.test_eval_failure()
@pytest.mark.xfail("env.PYPY", raises=RuntimeError) @pytest.mark.xfail("env.PYPY or env.GRAALPY", raises=RuntimeError)
def test_eval_file(): def test_eval_file():
filename = os.path.join(os.path.dirname(__file__), "test_eval_call.py") filename = os.path.join(os.path.dirname(__file__), "test_eval_call.py")
assert m.test_eval_file(filename) assert m.test_eval_file(filename)

View File

@ -201,6 +201,7 @@ def test_custom(msg):
assert msg(excinfo.value) == "[PythonMyException7]: abc" assert msg(excinfo.value) == "[PythonMyException7]: abc"
@pytest.mark.xfail("env.GRAALPY", reason="TODO should get fixed on GraalPy side")
def test_nested_throws(capture): def test_nested_throws(capture):
"""Tests nested (e.g. C++ -> Python -> C++) exception handling""" """Tests nested (e.g. C++ -> Python -> C++) exception handling"""
@ -369,6 +370,7 @@ def _test_flaky_exception_failure_point_init_py_3_12():
"env.PYPY and sys.version_info[:2] < (3, 12)", "env.PYPY and sys.version_info[:2] < (3, 12)",
reason="PyErr_NormalizeException Segmentation fault", reason="PyErr_NormalizeException Segmentation fault",
) )
@pytest.mark.xfail("env.GRAALPY", reason="TODO should be fixed on GraalPy side")
def test_flaky_exception_failure_point_init(): def test_flaky_exception_failure_point_init():
if sys.version_info[:2] < (3, 12): if sys.version_info[:2] < (3, 12):
_test_flaky_exception_failure_point_init_before_py_3_12() _test_flaky_exception_failure_point_init_before_py_3_12()
@ -376,6 +378,7 @@ def test_flaky_exception_failure_point_init():
_test_flaky_exception_failure_point_init_py_3_12() _test_flaky_exception_failure_point_init_py_3_12()
@pytest.mark.xfail("env.GRAALPY", reason="TODO should be fixed on GraalPy side")
def test_flaky_exception_failure_point_str(): def test_flaky_exception_failure_point_str():
what, py_err_set_after_what = m.error_already_set_what( what, py_err_set_after_what = m.error_already_set_what(
FlakyException, ("failure_point_str",) FlakyException, ("failure_point_str",)

View File

@ -4,11 +4,13 @@ import re
import pytest import pytest
import env # noqa: F401
from pybind11_tests import ConstructorStats from pybind11_tests import ConstructorStats
from pybind11_tests import factory_constructors as m from pybind11_tests import factory_constructors as m
from pybind11_tests.factory_constructors import tag from pybind11_tests.factory_constructors import tag
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_init_factory_basic(): def test_init_factory_basic():
"""Tests py::init_factory() wrapper around various ways of returning the object""" """Tests py::init_factory() wrapper around various ways of returning the object"""
@ -102,6 +104,7 @@ def test_init_factory_signature(msg):
) )
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_init_factory_casting(): def test_init_factory_casting():
"""Tests py::init_factory() wrapper with various upcasting and downcasting returns""" """Tests py::init_factory() wrapper with various upcasting and downcasting returns"""
@ -150,6 +153,7 @@ def test_init_factory_casting():
] ]
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_init_factory_alias(): def test_init_factory_alias():
"""Tests py::init_factory() wrapper with value conversions and alias types""" """Tests py::init_factory() wrapper with value conversions and alias types"""

View File

@ -211,6 +211,11 @@ def _run_in_threads(test_fn, num_threads, parallel):
@pytest.mark.skipif(sys.platform.startswith("emscripten"), reason="Requires threads") @pytest.mark.skipif(sys.platform.startswith("emscripten"), reason="Requires threads")
@pytest.mark.parametrize("test_fn", ALL_BASIC_TESTS_PLUS_INTENTIONAL_DEADLOCK) @pytest.mark.parametrize("test_fn", ALL_BASIC_TESTS_PLUS_INTENTIONAL_DEADLOCK)
@pytest.mark.xfail(
"env.GRAALPY",
reason="GraalPy transiently complains about unfinished threads at process exit",
strict=False,
)
def test_run_in_process_one_thread(test_fn): def test_run_in_process_one_thread(test_fn):
"""Makes sure there is no GIL deadlock when running in a thread. """Makes sure there is no GIL deadlock when running in a thread.
@ -221,6 +226,11 @@ def test_run_in_process_one_thread(test_fn):
@pytest.mark.skipif(sys.platform.startswith("emscripten"), reason="Requires threads") @pytest.mark.skipif(sys.platform.startswith("emscripten"), reason="Requires threads")
@pytest.mark.parametrize("test_fn", ALL_BASIC_TESTS_PLUS_INTENTIONAL_DEADLOCK) @pytest.mark.parametrize("test_fn", ALL_BASIC_TESTS_PLUS_INTENTIONAL_DEADLOCK)
@pytest.mark.xfail(
"env.GRAALPY",
reason="GraalPy transiently complains about unfinished threads at process exit",
strict=False,
)
def test_run_in_process_multiple_threads_parallel(test_fn): def test_run_in_process_multiple_threads_parallel(test_fn):
"""Makes sure there is no GIL deadlock when running in a thread multiple times in parallel. """Makes sure there is no GIL deadlock when running in a thread multiple times in parallel.
@ -231,6 +241,11 @@ def test_run_in_process_multiple_threads_parallel(test_fn):
@pytest.mark.skipif(sys.platform.startswith("emscripten"), reason="Requires threads") @pytest.mark.skipif(sys.platform.startswith("emscripten"), reason="Requires threads")
@pytest.mark.parametrize("test_fn", ALL_BASIC_TESTS_PLUS_INTENTIONAL_DEADLOCK) @pytest.mark.parametrize("test_fn", ALL_BASIC_TESTS_PLUS_INTENTIONAL_DEADLOCK)
@pytest.mark.xfail(
"env.GRAALPY",
reason="GraalPy transiently complains about unfinished threads at process exit",
strict=False,
)
def test_run_in_process_multiple_threads_sequential(test_fn): def test_run_in_process_multiple_threads_sequential(test_fn):
"""Makes sure there is no GIL deadlock when running in a thread multiple times sequentially. """Makes sure there is no GIL deadlock when running in a thread multiple times sequentially.
@ -241,6 +256,11 @@ def test_run_in_process_multiple_threads_sequential(test_fn):
@pytest.mark.skipif(sys.platform.startswith("emscripten"), reason="Requires threads") @pytest.mark.skipif(sys.platform.startswith("emscripten"), reason="Requires threads")
@pytest.mark.parametrize("test_fn", ALL_BASIC_TESTS_PLUS_INTENTIONAL_DEADLOCK) @pytest.mark.parametrize("test_fn", ALL_BASIC_TESTS_PLUS_INTENTIONAL_DEADLOCK)
@pytest.mark.xfail(
"env.GRAALPY",
reason="GraalPy transiently complains about unfinished threads at process exit",
strict=False,
)
def test_run_in_process_direct(test_fn): def test_run_in_process_direct(test_fn):
"""Makes sure there is no GIL deadlock when using processes. """Makes sure there is no GIL deadlock when using processes.

View File

@ -6,8 +6,14 @@ from io import StringIO
import pytest import pytest
import env # noqa: F401
from pybind11_tests import iostream as m from pybind11_tests import iostream as m
pytestmark = pytest.mark.skipif(
"env.GRAALPY",
reason="Delayed prints from finalizers from other tests can end up in the output",
)
def test_captured(capsys): def test_captured(capsys):
msg = "I've been redirected to Python, I hope!" msg = "I've been redirected to Python, I hope!"

View File

@ -2,6 +2,7 @@ from __future__ import annotations
import pytest import pytest
import env # noqa: F401
from pybind11_tests import kwargs_and_defaults as m from pybind11_tests import kwargs_and_defaults as m
@ -378,6 +379,7 @@ def test_signatures():
) )
@pytest.mark.skipif("env.GRAALPY", reason="Different refcounting mechanism")
def test_args_refcount(): def test_args_refcount():
"""Issue/PR #1216 - py::args elements get double-inc_ref()ed when combined with regular """Issue/PR #1216 - py::args elements get double-inc_ref()ed when combined with regular
arguments""" arguments"""

View File

@ -19,6 +19,7 @@ NO_DELETER_MSG = (
) )
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_methods_and_attributes(): def test_methods_and_attributes():
instance1 = m.ExampleMandA() instance1 = m.ExampleMandA()
instance2 = m.ExampleMandA(32) instance2 = m.ExampleMandA(32)
@ -295,6 +296,7 @@ def test_property_rvalue_policy():
# https://foss.heptapod.net/pypy/pypy/-/issues/2447 # https://foss.heptapod.net/pypy/pypy/-/issues/2447
@pytest.mark.xfail("env.PYPY") @pytest.mark.xfail("env.PYPY")
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_dynamic_attributes(): def test_dynamic_attributes():
instance = m.DynamicClass() instance = m.DynamicClass()
assert not hasattr(instance, "foo") assert not hasattr(instance, "foo")
@ -337,6 +339,7 @@ def test_dynamic_attributes():
# https://foss.heptapod.net/pypy/pypy/-/issues/2447 # https://foss.heptapod.net/pypy/pypy/-/issues/2447
@pytest.mark.xfail("env.PYPY") @pytest.mark.xfail("env.PYPY")
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_cyclic_gc(): def test_cyclic_gc():
# One object references itself # One object references itself
instance = m.DynamicClass() instance = m.DynamicClass()

View File

@ -25,6 +25,7 @@ def test_nested_modules():
assert ms.submodule_func() == "submodule_func()" assert ms.submodule_func() == "submodule_func()"
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_reference_internal(): def test_reference_internal():
b = ms.B() b = ms.B()
assert str(b.get_a1()) == "A[1]" assert str(b.get_a1()) == "A[1]"
@ -97,9 +98,9 @@ def test_def_submodule_failures():
sm = m.def_submodule(m, b"ScratchSubModuleName") # Using bytes to show it works. sm = m.def_submodule(m, b"ScratchSubModuleName") # Using bytes to show it works.
assert sm.__name__ == m.__name__ + "." + "ScratchSubModuleName" assert sm.__name__ == m.__name__ + "." + "ScratchSubModuleName"
malformed_utf8 = b"\x80" malformed_utf8 = b"\x80"
if env.PYPY: if env.PYPY or env.GRAALPY:
# It is not worth the effort finding a trigger for a failure when running with PyPy. # It is not worth the effort finding a trigger for a failure when running with PyPy.
pytest.skip("Sufficiently exercised on platforms other than PyPy.") pytest.skip("Sufficiently exercised on platforms other than PyPy/GraalPy.")
else: else:
# Meant to trigger PyModule_GetName() failure: # Meant to trigger PyModule_GetName() failure:
sm_name_orig = sm.__name__ sm_name_orig = sm.__name__

View File

@ -272,6 +272,7 @@ def test_mi_dynamic_attributes():
assert d.dynamic == 1 assert d.dynamic == 1
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_mi_unaligned_base(): def test_mi_unaligned_base():
"""Returning an offset (non-first MI) base class pointer should recognize the instance""" """Returning an offset (non-first MI) base class pointer should recognize the instance"""
@ -297,6 +298,7 @@ def test_mi_unaligned_base():
assert ConstructorStats.detail_reg_inst() == n_inst assert ConstructorStats.detail_reg_inst() == n_inst
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_mi_base_return(): def test_mi_base_return():
"""Tests returning an offset (non-first MI) base class pointer to a derived instance""" """Tests returning an offset (non-first MI) base class pointer to a derived instance"""

View File

@ -242,6 +242,7 @@ def test_wrap():
assert_references(a1m, a2, a1) assert_references(a1m, a2, a1)
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_numpy_view(capture): def test_numpy_view(capture):
with capture: with capture:
ac = m.ArrayClass() ac = m.ArrayClass()
@ -465,7 +466,7 @@ def test_array_resize():
assert b.shape == (8, 8) assert b.shape == (8, 8)
@pytest.mark.xfail("env.PYPY") @pytest.mark.xfail("env.PYPY or env.GRAALPY")
def test_array_create_and_resize(): def test_array_create_and_resize():
a = m.create_and_resize(2) a = m.create_and_resize(2)
assert a.size == 4 assert a.size == 4

View File

@ -2,10 +2,12 @@ from __future__ import annotations
import pytest import pytest
import env # noqa: F401
from pybind11_tests import ConstructorStats from pybind11_tests import ConstructorStats
from pybind11_tests import operators as m from pybind11_tests import operators as m
@pytest.mark.xfail("env.GRAALPY", reason="TODO should get fixed on GraalPy side")
def test_operator_overloading(): def test_operator_overloading():
v1 = m.Vector2(1, 2) v1 = m.Vector2(1, 2)
v2 = m.Vector(3, -1) v2 = m.Vector(3, -1)
@ -83,6 +85,7 @@ def test_operator_overloading():
assert cstats.move_assignments == 0 assert cstats.move_assignments == 0
@pytest.mark.xfail("env.GRAALPY", reason="TODO should get fixed on GraalPy side")
def test_operators_notimplemented(): def test_operators_notimplemented():
"""#393: need to return NotSupported to ensure correct arithmetic operator behavior""" """#393: need to return NotSupported to ensure correct arithmetic operator behavior"""

View File

@ -20,7 +20,7 @@ def test_pickle_simple_callable():
# all C Python versions. # all C Python versions.
with pytest.raises(TypeError) as excinfo: with pytest.raises(TypeError) as excinfo:
pickle.dumps(m.simple_callable) pickle.dumps(m.simple_callable)
assert re.search("can.*t pickle .*PyCapsule.* object", str(excinfo.value)) assert re.search("can.*t pickle .*[Cc]apsule.* object", str(excinfo.value))
@pytest.mark.parametrize("cls_name", ["Pickleable", "PickleableNew"]) @pytest.mark.parametrize("cls_name", ["Pickleable", "PickleableNew"])

View File

@ -262,6 +262,7 @@ def test_str(doc):
m.str_from_std_string_input, m.str_from_std_string_input,
], ],
) )
@pytest.mark.xfail("env.GRAALPY", reason="TODO should be fixed on GraalPy side")
def test_surrogate_pairs_unicode_error(func): def test_surrogate_pairs_unicode_error(func):
input_str = "\ud83d\ude4f".encode("utf-8", "surrogatepass") input_str = "\ud83d\ude4f".encode("utf-8", "surrogatepass")
with pytest.raises(UnicodeDecodeError): with pytest.raises(UnicodeDecodeError):
@ -420,6 +421,7 @@ def test_accessor_moves():
pytest.skip("Not defined: PYBIND11_HANDLE_REF_DEBUG") pytest.skip("Not defined: PYBIND11_HANDLE_REF_DEBUG")
@pytest.mark.xfail("env.GRAALPY", reason="TODO should be fixed on GraalPy side")
def test_constructors(): def test_constructors():
"""C++ default and converting constructors are equivalent to type calls in Python""" """C++ default and converting constructors are equivalent to type calls in Python"""
types = [bytes, bytearray, str, bool, int, float, tuple, list, dict, set] types = [bytes, bytearray, str, bool, int, float, tuple, list, dict, set]
@ -712,6 +714,7 @@ def test_pass_bytes_or_unicode_to_string_types():
m.pass_to_pybind11_str(malformed_utf8) m.pass_to_pybind11_str(malformed_utf8)
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
@pytest.mark.parametrize( @pytest.mark.parametrize(
("create_weakref", "create_weakref_with_callback"), ("create_weakref", "create_weakref_with_callback"),
[ [
@ -765,7 +768,10 @@ def test_weakref_err(create_weakref, has_callback):
ob = C() ob = C()
# Should raise TypeError on CPython # Should raise TypeError on CPython
with pytest.raises(TypeError) if not env.PYPY else contextlib.nullcontext(): cm = pytest.raises(TypeError)
if env.PYPY or env.GRAALPY:
cm = contextlib.nullcontext()
with cm:
_ = create_weakref(ob, callback) if has_callback else create_weakref(ob) _ = create_weakref(ob, callback) if has_callback else create_weakref(ob)

View File

@ -3,6 +3,7 @@ from __future__ import annotations
import pytest import pytest
from pytest import approx # noqa: PT013 from pytest import approx # noqa: PT013
import env # noqa: F401
from pybind11_tests import ConstructorStats from pybind11_tests import ConstructorStats
from pybind11_tests import sequences_and_iterators as m from pybind11_tests import sequences_and_iterators as m
@ -106,6 +107,7 @@ def test_sliceable():
assert sliceable[50:60:-1] == (50, 60, -1) assert sliceable[50:60:-1] == (50, 60, -1)
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_sequence(): def test_sequence():
cstats = ConstructorStats.get(m.Sequence) cstats = ConstructorStats.get(m.Sequence)

View File

@ -2,10 +2,13 @@ from __future__ import annotations
import pytest import pytest
import env # noqa: F401
m = pytest.importorskip("pybind11_tests.smart_ptr") m = pytest.importorskip("pybind11_tests.smart_ptr")
from pybind11_tests import ConstructorStats # noqa: E402 from pybind11_tests import ConstructorStats # noqa: E402
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_smart_ptr(capture): def test_smart_ptr(capture):
# Object1 # Object1
for i, o in enumerate( for i, o in enumerate(
@ -118,6 +121,7 @@ def test_smart_ptr_refcounting():
assert m.test_object1_refcounting() assert m.test_object1_refcounting()
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_unique_nodelete(): def test_unique_nodelete():
o = m.MyObject4(23) o = m.MyObject4(23)
assert o.value == 23 assert o.value == 23
@ -129,6 +133,7 @@ def test_unique_nodelete():
assert cstats.alive() == 0 assert cstats.alive() == 0
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_unique_nodelete4a(): def test_unique_nodelete4a():
o = m.MyObject4a(23) o = m.MyObject4a(23)
assert o.value == 23 assert o.value == 23
@ -140,6 +145,7 @@ def test_unique_nodelete4a():
assert cstats.alive() == 0 assert cstats.alive() == 0
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_unique_deleter(): def test_unique_deleter():
m.MyObject4a(0) m.MyObject4a(0)
o = m.MyObject4b(23) o = m.MyObject4b(23)
@ -156,6 +162,7 @@ def test_unique_deleter():
assert cstats4b.alive() == 0 assert cstats4b.alive() == 0
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_large_holder(): def test_large_holder():
o = m.MyObject5(5) o = m.MyObject5(5)
assert o.value == 5 assert o.value == 5
@ -165,6 +172,7 @@ def test_large_holder():
assert cstats.alive() == 0 assert cstats.alive() == 0
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_shared_ptr_and_references(): def test_shared_ptr_and_references():
s = m.SharedPtrRef() s = m.SharedPtrRef()
stats = ConstructorStats.get(m.A) stats = ConstructorStats.get(m.A)
@ -196,6 +204,7 @@ def test_shared_ptr_and_references():
assert stats.alive() == 0 assert stats.alive() == 0
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_shared_ptr_from_this_and_references(): def test_shared_ptr_from_this_and_references():
s = m.SharedFromThisRef() s = m.SharedFromThisRef()
stats = ConstructorStats.get(m.B) stats = ConstructorStats.get(m.B)
@ -242,6 +251,7 @@ def test_shared_ptr_from_this_and_references():
assert y is z assert y is z
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_move_only_holder(): def test_move_only_holder():
a = m.TypeWithMoveOnlyHolder.make() a = m.TypeWithMoveOnlyHolder.make()
b = m.TypeWithMoveOnlyHolder.make_as_object() b = m.TypeWithMoveOnlyHolder.make_as_object()
@ -253,6 +263,7 @@ def test_move_only_holder():
assert stats.alive() == 0 assert stats.alive() == 0
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_holder_with_addressof_operator(): def test_holder_with_addressof_operator():
# this test must not throw exception from c++ # this test must not throw exception from c++
a = m.TypeForHolderWithAddressOf.make() a = m.TypeForHolderWithAddressOf.make()
@ -283,6 +294,7 @@ def test_holder_with_addressof_operator():
assert stats.alive() == 0 assert stats.alive() == 0
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_move_only_holder_with_addressof_operator(): def test_move_only_holder_with_addressof_operator():
a = m.TypeForMoveOnlyHolderWithAddressOf.make() a = m.TypeForMoveOnlyHolderWithAddressOf.make()
a.print_object() a.print_object()

View File

@ -2,6 +2,7 @@ from __future__ import annotations
import pytest import pytest
import env # noqa: F401
from pybind11_tests import ConstructorStats, UserType from pybind11_tests import ConstructorStats, UserType
from pybind11_tests import stl as m from pybind11_tests import stl as m
@ -362,6 +363,7 @@ def test_function_with_string_and_vector_string_arg():
assert m.func_with_string_or_vector_string_arg_overload("A") == 3 assert m.func_with_string_or_vector_string_arg_overload("A") == 3
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_stl_ownership(): def test_stl_ownership():
cstats = ConstructorStats.get(m.Placeholder) cstats = ConstructorStats.get(m.Placeholder)
assert cstats.alive() == 0 assert cstats.alive() == 0

View File

@ -37,7 +37,8 @@ struct WithPyObjectPtrReturnTrampoline : WithPyObjectPtrReturn {
std::string call_return_pyobject_ptr(const WithPyObjectPtrReturn *base_class_ptr) { std::string call_return_pyobject_ptr(const WithPyObjectPtrReturn *base_class_ptr) {
PyObject *returned_obj = base_class_ptr->return_pyobject_ptr(); PyObject *returned_obj = base_class_ptr->return_pyobject_ptr();
#if !defined(PYPY_VERSION) // It is not worth the trouble doing something special for PyPy. // It is not worth the trouble doing something special for PyPy/GraalPy
#if !defined(PYPY_VERSION) && !defined(GRAALVM_PYTHON)
if (Py_REFCNT(returned_obj) != 1) { if (Py_REFCNT(returned_obj) != 1) {
py::pybind11_fail(__FILE__ ":" PYBIND11_TOSTRING(__LINE__)); py::pybind11_fail(__FILE__ ":" PYBIND11_TOSTRING(__LINE__));
} }

View File

@ -4,7 +4,7 @@ import sys
import pytest import pytest
import env # noqa: F401 import env
m = pytest.importorskip("pybind11_tests.virtual_functions") m = pytest.importorskip("pybind11_tests.virtual_functions")
from pybind11_tests import ConstructorStats # noqa: E402 from pybind11_tests import ConstructorStats # noqa: E402
@ -82,15 +82,17 @@ def test_override(capture, msg):
""" """
) )
cstats = ConstructorStats.get(m.ExampleVirt) if not env.GRAALPY:
assert cstats.alive() == 3 cstats = ConstructorStats.get(m.ExampleVirt)
del ex12, ex12p, ex12p2 assert cstats.alive() == 3
assert cstats.alive() == 0 del ex12, ex12p, ex12p2
assert cstats.values() == ["10", "11", "17"] assert cstats.alive() == 0
assert cstats.copy_constructions == 0 assert cstats.values() == ["10", "11", "17"]
assert cstats.move_constructions >= 0 assert cstats.copy_constructions == 0
assert cstats.move_constructions >= 0
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_alias_delay_initialization1(capture): def test_alias_delay_initialization1(capture):
"""`A` only initializes its trampoline class when we inherit from it """`A` only initializes its trampoline class when we inherit from it
@ -130,6 +132,7 @@ def test_alias_delay_initialization1(capture):
) )
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
def test_alias_delay_initialization2(capture): def test_alias_delay_initialization2(capture):
"""`A2`, unlike the above, is configured to always initialize the alias """`A2`, unlike the above, is configured to always initialize the alias
@ -188,7 +191,7 @@ def test_alias_delay_initialization2(capture):
# PyPy: Reference count > 1 causes call with noncopyable instance # PyPy: Reference count > 1 causes call with noncopyable instance
# to fail in ncv1.print_nc() # to fail in ncv1.print_nc()
@pytest.mark.xfail("env.PYPY") @pytest.mark.xfail("env.PYPY or env.GRAALPY")
@pytest.mark.skipif( @pytest.mark.skipif(
not hasattr(m, "NCVirt"), reason="NCVirt does not work on Intel/PGI/NVCC compilers" not hasattr(m, "NCVirt"), reason="NCVirt does not work on Intel/PGI/NVCC compilers"
) )