mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-21 20:55:11 +00:00
Add support for GraalPy (#5380)
* Initial support for GraalPy * Mark tests that currently fail on GraalPy with xfail * Add graalpy to CI * Limit test deps on graalpy to available binary wheels * Skip cmake test installed_function on GraalPy CMake won't find libpython on GraalPy, it either fails or silently picks CPython's libpython. * Factor out setting function docstrings into a macro * Try to narrow down skipped tests
This commit is contained in:
parent
7e418f4924
commit
c4a05f9344
5
.github/workflows/ci.yml
vendored
5
.github/workflows/ci.yml
vendored
@ -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 }}"
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
|
||||||
@ -387,6 +387,20 @@ PYBIND11_WARNING_POP
|
|||||||
#define PYBIND11_CONCAT(first, second) first##second
|
#define PYBIND11_CONCAT(first, second) first##second
|
||||||
#define PYBIND11_ENSURE_INTERNALS_READY pybind11::detail::get_internals();
|
#define PYBIND11_ENSURE_INTERNALS_READY pybind11::detail::get_internals();
|
||||||
|
|
||||||
|
#if !defined(GRAALVM_PYTHON)
|
||||||
|
# define PYBIND11_PYCFUNCTION_GET_DOC(func) ((func)->m_ml->ml_doc)
|
||||||
|
# define PYBIND11_PYCFUNCTION_SET_DOC(func, doc) \
|
||||||
|
do { \
|
||||||
|
(func)->m_ml->ml_doc = (doc); \
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
# define PYBIND11_PYCFUNCTION_GET_DOC(func) (GraalPyCFunction_GetDoc((PyObject *) (func)))
|
||||||
|
# define PYBIND11_PYCFUNCTION_SET_DOC(func, doc) \
|
||||||
|
do { \
|
||||||
|
GraalPyCFunction_SetDoc((PyObject *) (func), (doc)); \
|
||||||
|
} while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define PYBIND11_CHECK_PYTHON_VERSION \
|
#define PYBIND11_CHECK_PYTHON_VERSION \
|
||||||
{ \
|
{ \
|
||||||
const char *compiled_ver \
|
const char *compiled_ver \
|
||||||
|
@ -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
|
||||||
@ -727,7 +727,8 @@ const char *c_str(Args &&...args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline const char *get_function_record_capsule_name() {
|
inline const char *get_function_record_capsule_name() {
|
||||||
#if PYBIND11_INTERNALS_VERSION > 4
|
// On GraalPy, pointer equality of the names is currently not guaranteed
|
||||||
|
#if PYBIND11_INTERNALS_VERSION > 4 && !defined(GRAALVM_PYTHON)
|
||||||
return get_internals().function_record_capsule_name.c_str();
|
return get_internals().function_record_capsule_name.c_str();
|
||||||
#else
|
#else
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -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();
|
||||||
|
@ -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 this interpreter. 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 this interpreter. 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 this interpreter. Use eval");
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
template <eval_mode mode = eval_statements>
|
template <eval_mode mode = eval_statements>
|
||||||
|
@ -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 {
|
||||||
@ -634,12 +633,11 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Install docstring */
|
|
||||||
auto *func = (PyCFunctionObject *) m_ptr;
|
auto *func = (PyCFunctionObject *) m_ptr;
|
||||||
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
|
auto *doc = signatures.empty() ? nullptr : PYBIND11_COMPAT_STRDUP(signatures.c_str());
|
||||||
= signatures.empty() ? nullptr : PYBIND11_COMPAT_STRDUP(signatures.c_str());
|
std::free(const_cast<char *>(PYBIND11_PYCFUNCTION_GET_DOC(func)));
|
||||||
|
PYBIND11_PYCFUNCTION_SET_DOC(func, doc);
|
||||||
|
|
||||||
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 +2778,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) {
|
||||||
|
@ -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:
|
||||||
|
@ -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
|
||||||
|
@ -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"))
|
||||||
|
|
||||||
|
|
||||||
|
@ -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'
|
||||||
|
@ -82,6 +82,8 @@ def test_from_python():
|
|||||||
for j in range(m4.cols()):
|
for j in range(m4.cols()):
|
||||||
assert m3[i, j] == m4[i, j]
|
assert m3[i, j] == m4[i, j]
|
||||||
|
|
||||||
|
if env.GRAALPY:
|
||||||
|
pytest.skip("ConstructorStats is incompatible with GraalPy.")
|
||||||
cstats = ConstructorStats.get(m.Matrix)
|
cstats = ConstructorStats.get(m.Matrix)
|
||||||
assert cstats.alive() == 1
|
assert cstats.alive() == 1
|
||||||
del m3, m4
|
del m3, m4
|
||||||
@ -118,6 +120,8 @@ def test_to_python():
|
|||||||
mat2[2, 3] = 5
|
mat2[2, 3] = 5
|
||||||
assert mat2[2, 3] == 5
|
assert mat2[2, 3] == 5
|
||||||
|
|
||||||
|
if env.GRAALPY:
|
||||||
|
pytest.skip("ConstructorStats is incompatible with GraalPy.")
|
||||||
cstats = ConstructorStats.get(m.Matrix)
|
cstats = ConstructorStats.get(m.Matrix)
|
||||||
assert cstats.alive() == 1
|
assert cstats.alive() == 1
|
||||||
del mat
|
del mat
|
||||||
|
@ -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;
|
||||||
|
@ -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):
|
||||||
|
@ -270,7 +270,7 @@ TEST_SUBMODULE(callbacks, m) {
|
|||||||
m.add_object("custom_function", PyCFunction_New(custom_def, rec_capsule.ptr()));
|
m.add_object("custom_function", PyCFunction_New(custom_def, rec_capsule.ptr()));
|
||||||
|
|
||||||
// This test requires a new ABI version to pass
|
// This test requires a new ABI version to pass
|
||||||
#if PYBIND11_INTERNALS_VERSION > 4
|
#if PYBIND11_INTERNALS_VERSION > 4 && !defined(GRAALVM_PYTHON)
|
||||||
// rec_capsule with nullptr name
|
// rec_capsule with nullptr name
|
||||||
py::capsule rec_capsule2(std::malloc(1), [](void *data) { std::free(data); });
|
py::capsule rec_capsule2(std::malloc(1), [](void *data) { std::free(data); });
|
||||||
m.add_object("custom_function2", PyCFunction_New(custom_def, rec_capsule2.ptr()));
|
m.add_object("custom_function2", PyCFunction_New(custom_def, rec_capsule2.ptr()));
|
||||||
|
@ -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]
|
||||||
|
@ -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
|
||||||
|
@ -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()
|
||||||
@ -66,10 +68,14 @@ if(PYBIND11_INSTALL)
|
|||||||
mock_install ${CMAKE_COMMAND} "-DCMAKE_INSTALL_PREFIX=${pybind11_BINARY_DIR}/mock_install" -P
|
mock_install ${CMAKE_COMMAND} "-DCMAKE_INSTALL_PREFIX=${pybind11_BINARY_DIR}/mock_install" -P
|
||||||
"${pybind11_BINARY_DIR}/cmake_install.cmake")
|
"${pybind11_BINARY_DIR}/cmake_install.cmake")
|
||||||
|
|
||||||
pybind11_add_build_test(installed_function INSTALL)
|
if(NOT "${PYTHON_MODULE_EXTENSION}" MATCHES "graalpy")
|
||||||
|
pybind11_add_build_test(installed_function INSTALL)
|
||||||
|
endif()
|
||||||
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()
|
||||||
|
@ -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
|
||||||
from pybind11_tests import cpp_conduit as home_planet
|
from pybind11_tests import cpp_conduit as home_planet
|
||||||
|
|
||||||
|
|
||||||
@ -27,7 +28,10 @@ def test_call_cpp_conduit_success():
|
|||||||
home_planet.cpp_type_info_capsule_Traveler,
|
home_planet.cpp_type_info_capsule_Traveler,
|
||||||
b"raw_pointer_ephemeral",
|
b"raw_pointer_ephemeral",
|
||||||
)
|
)
|
||||||
assert cap.__class__.__name__ == "PyCapsule"
|
assert cap.__class__.__name__ == "PyCapsule" or (
|
||||||
|
# Note: this will become unnecessary in the next GraalPy release
|
||||||
|
env.GRAALPY and cap.__class__.__name__ == "capsule"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_call_cpp_conduit_platform_abi_id_mismatch():
|
def test_call_cpp_conduit_platform_abi_id_mismatch():
|
||||||
|
@ -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]
|
||||||
|
@ -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)
|
||||||
|
@ -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")
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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",)
|
||||||
|
@ -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"""
|
||||||
|
|
||||||
@ -220,6 +224,7 @@ def test_init_factory_alias():
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
|
||||||
def test_init_factory_dual():
|
def test_init_factory_dual():
|
||||||
"""Tests init factory functions with dual main/alias factory functions"""
|
"""Tests init factory functions with dual main/alias factory functions"""
|
||||||
from pybind11_tests.factory_constructors import TestFactory7
|
from pybind11_tests.factory_constructors import TestFactory7
|
||||||
@ -302,6 +307,7 @@ def test_init_factory_dual():
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
|
||||||
def test_no_placement_new(capture):
|
def test_no_placement_new(capture):
|
||||||
"""Prior to 2.2, `py::init<...>` relied on the type supporting placement
|
"""Prior to 2.2, `py::init<...>` relied on the type supporting placement
|
||||||
new; this tests a class without placement new support."""
|
new; this tests a class without placement new support."""
|
||||||
@ -350,6 +356,7 @@ def strip_comments(s):
|
|||||||
return re.sub(r"\s+#.*", "", s)
|
return re.sub(r"\s+#.*", "", s)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
|
||||||
def test_reallocation_a(capture, msg):
|
def test_reallocation_a(capture, msg):
|
||||||
"""When the constructor is overloaded, previous overloads can require a preallocated value.
|
"""When the constructor is overloaded, previous overloads can require a preallocated value.
|
||||||
This test makes sure that such preallocated values only happen when they might be necessary,
|
This test makes sure that such preallocated values only happen when they might be necessary,
|
||||||
@ -372,6 +379,7 @@ def test_reallocation_a(capture, msg):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
|
||||||
def test_reallocation_b(capture, msg):
|
def test_reallocation_b(capture, msg):
|
||||||
with capture:
|
with capture:
|
||||||
create_and_destroy(1.5)
|
create_and_destroy(1.5)
|
||||||
@ -388,6 +396,7 @@ def test_reallocation_b(capture, msg):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
|
||||||
def test_reallocation_c(capture, msg):
|
def test_reallocation_c(capture, msg):
|
||||||
with capture:
|
with capture:
|
||||||
create_and_destroy(2, 3)
|
create_and_destroy(2, 3)
|
||||||
@ -402,6 +411,7 @@ def test_reallocation_c(capture, msg):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
|
||||||
def test_reallocation_d(capture, msg):
|
def test_reallocation_d(capture, msg):
|
||||||
with capture:
|
with capture:
|
||||||
create_and_destroy(2.5, 3)
|
create_and_destroy(2.5, 3)
|
||||||
@ -417,6 +427,7 @@ def test_reallocation_d(capture, msg):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
|
||||||
def test_reallocation_e(capture, msg):
|
def test_reallocation_e(capture, msg):
|
||||||
with capture:
|
with capture:
|
||||||
create_and_destroy(3.5, 4.5)
|
create_and_destroy(3.5, 4.5)
|
||||||
@ -432,6 +443,7 @@ def test_reallocation_e(capture, msg):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
|
||||||
def test_reallocation_f(capture, msg):
|
def test_reallocation_f(capture, msg):
|
||||||
with capture:
|
with capture:
|
||||||
create_and_destroy(4, 0.5)
|
create_and_destroy(4, 0.5)
|
||||||
@ -448,6 +460,7 @@ def test_reallocation_f(capture, msg):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
|
||||||
def test_reallocation_g(capture, msg):
|
def test_reallocation_g(capture, msg):
|
||||||
with capture:
|
with capture:
|
||||||
create_and_destroy(5, "hi")
|
create_and_destroy(5, "hi")
|
||||||
|
@ -211,6 +211,10 @@ 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.skipif(
|
||||||
|
"env.GRAALPY",
|
||||||
|
reason="GraalPy transiently complains about unfinished threads at process exit",
|
||||||
|
)
|
||||||
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 +225,10 @@ 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.skipif(
|
||||||
|
"env.GRAALPY",
|
||||||
|
reason="GraalPy transiently complains about unfinished threads at process exit",
|
||||||
|
)
|
||||||
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 +239,10 @@ 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.skipif(
|
||||||
|
"env.GRAALPY",
|
||||||
|
reason="GraalPy transiently complains about unfinished threads at process exit",
|
||||||
|
)
|
||||||
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 +253,10 @@ 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.skipif(
|
||||||
|
"env.GRAALPY",
|
||||||
|
reason="GraalPy transiently complains about unfinished threads at process exit",
|
||||||
|
)
|
||||||
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.
|
||||||
|
|
||||||
|
@ -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!"
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
@ -383,6 +384,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"""
|
||||||
|
@ -4,7 +4,7 @@ import sys
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import env # noqa: F401
|
import env
|
||||||
from pybind11_tests import ConstructorStats
|
from pybind11_tests import ConstructorStats
|
||||||
from pybind11_tests import methods_and_attributes as m
|
from pybind11_tests import methods_and_attributes as m
|
||||||
|
|
||||||
@ -68,6 +68,9 @@ def test_methods_and_attributes():
|
|||||||
instance1.value = 100
|
instance1.value = 100
|
||||||
assert str(instance1) == "ExampleMandA[value=100]"
|
assert str(instance1) == "ExampleMandA[value=100]"
|
||||||
|
|
||||||
|
if env.GRAALPY:
|
||||||
|
pytest.skip("ConstructorStats is incompatible with GraalPy.")
|
||||||
|
|
||||||
cstats = ConstructorStats.get(m.ExampleMandA)
|
cstats = ConstructorStats.get(m.ExampleMandA)
|
||||||
assert cstats.alive() == 2
|
assert cstats.alive() == 2
|
||||||
del instance1, instance2
|
del instance1, instance2
|
||||||
@ -316,6 +319,8 @@ def test_dynamic_attributes():
|
|||||||
instance.__dict__ = []
|
instance.__dict__ = []
|
||||||
assert str(excinfo.value) == "__dict__ must be set to a dictionary, not a 'list'"
|
assert str(excinfo.value) == "__dict__ must be set to a dictionary, not a 'list'"
|
||||||
|
|
||||||
|
if env.GRAALPY:
|
||||||
|
pytest.skip("ConstructorStats is incompatible with GraalPy.")
|
||||||
cstats = ConstructorStats.get(m.DynamicClass)
|
cstats = ConstructorStats.get(m.DynamicClass)
|
||||||
assert cstats.alive() == 1
|
assert cstats.alive() == 1
|
||||||
del instance
|
del instance
|
||||||
@ -337,6 +342,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()
|
||||||
|
@ -39,6 +39,9 @@ def test_reference_internal():
|
|||||||
assert str(b.get_a2()) == "A[43]"
|
assert str(b.get_a2()) == "A[43]"
|
||||||
assert str(b.a2) == "A[43]"
|
assert str(b.a2) == "A[43]"
|
||||||
|
|
||||||
|
if env.GRAALPY:
|
||||||
|
pytest.skip("ConstructorStats is incompatible with GraalPy.")
|
||||||
|
|
||||||
astats, bstats = ConstructorStats.get(ms.A), ConstructorStats.get(ms.B)
|
astats, bstats = ConstructorStats.get(ms.A), ConstructorStats.get(ms.B)
|
||||||
assert astats.alive() == 2
|
assert astats.alive() == 2
|
||||||
assert bstats.alive() == 1
|
assert bstats.alive() == 1
|
||||||
@ -97,9 +100,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__
|
||||||
|
@ -2,7 +2,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import env # noqa: F401
|
import env
|
||||||
from pybind11_tests import ConstructorStats
|
from pybind11_tests import ConstructorStats
|
||||||
from pybind11_tests import multiple_inheritance as m
|
from pybind11_tests import multiple_inheritance as m
|
||||||
|
|
||||||
@ -279,8 +279,9 @@ def test_mi_unaligned_base():
|
|||||||
|
|
||||||
c = m.I801C()
|
c = m.I801C()
|
||||||
d = m.I801D()
|
d = m.I801D()
|
||||||
# + 4 below because we have the two instances, and each instance has offset base I801B2
|
if not env.GRAALPY:
|
||||||
assert ConstructorStats.detail_reg_inst() == n_inst + 4
|
# + 4 below because we have the two instances, and each instance has offset base I801B2
|
||||||
|
assert ConstructorStats.detail_reg_inst() == n_inst + 4
|
||||||
b1c = m.i801b1_c(c)
|
b1c = m.i801b1_c(c)
|
||||||
assert b1c is c
|
assert b1c is c
|
||||||
b2c = m.i801b2_c(c)
|
b2c = m.i801b2_c(c)
|
||||||
@ -290,6 +291,9 @@ def test_mi_unaligned_base():
|
|||||||
b2d = m.i801b2_d(d)
|
b2d = m.i801b2_d(d)
|
||||||
assert b2d is d
|
assert b2d is d
|
||||||
|
|
||||||
|
if env.GRAALPY:
|
||||||
|
pytest.skip("ConstructorStats is incompatible with GraalPy.")
|
||||||
|
|
||||||
assert ConstructorStats.detail_reg_inst() == n_inst + 4 # no extra instances
|
assert ConstructorStats.detail_reg_inst() == n_inst + 4 # no extra instances
|
||||||
del c, b1c, b2c
|
del c, b1c, b2c
|
||||||
assert ConstructorStats.detail_reg_inst() == n_inst + 2
|
assert ConstructorStats.detail_reg_inst() == n_inst + 2
|
||||||
@ -312,7 +316,8 @@ def test_mi_base_return():
|
|||||||
assert d1.a == 1
|
assert d1.a == 1
|
||||||
assert d1.b == 2
|
assert d1.b == 2
|
||||||
|
|
||||||
assert ConstructorStats.detail_reg_inst() == n_inst + 4
|
if not env.GRAALPY:
|
||||||
|
assert ConstructorStats.detail_reg_inst() == n_inst + 4
|
||||||
|
|
||||||
c2 = m.i801c_b2()
|
c2 = m.i801c_b2()
|
||||||
assert type(c2) is m.I801C
|
assert type(c2) is m.I801C
|
||||||
@ -324,12 +329,13 @@ def test_mi_base_return():
|
|||||||
assert d2.a == 1
|
assert d2.a == 1
|
||||||
assert d2.b == 2
|
assert d2.b == 2
|
||||||
|
|
||||||
assert ConstructorStats.detail_reg_inst() == n_inst + 8
|
if not env.GRAALPY:
|
||||||
|
assert ConstructorStats.detail_reg_inst() == n_inst + 8
|
||||||
|
|
||||||
del c2
|
del c2
|
||||||
assert ConstructorStats.detail_reg_inst() == n_inst + 6
|
assert ConstructorStats.detail_reg_inst() == n_inst + 6
|
||||||
del c1, d1, d2
|
del c1, d1, d2
|
||||||
assert ConstructorStats.detail_reg_inst() == n_inst
|
assert ConstructorStats.detail_reg_inst() == n_inst
|
||||||
|
|
||||||
# Returning an unregistered derived type with a registered base; we won't
|
# Returning an unregistered derived type with a registered base; we won't
|
||||||
# pick up the derived type, obviously, but should still work (as an object
|
# pick up the derived type, obviously, but should still work (as an object
|
||||||
|
@ -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
|
||||||
|
@ -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"""
|
||||||
|
|
||||||
|
@ -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"])
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
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
|
||||||
|
|
||||||
@ -110,7 +111,8 @@ def test_sequence():
|
|||||||
cstats = ConstructorStats.get(m.Sequence)
|
cstats = ConstructorStats.get(m.Sequence)
|
||||||
|
|
||||||
s = m.Sequence(5)
|
s = m.Sequence(5)
|
||||||
assert cstats.values() == ["of size", "5"]
|
if not env.GRAALPY:
|
||||||
|
assert cstats.values() == ["of size", "5"]
|
||||||
|
|
||||||
assert "Sequence" in repr(s)
|
assert "Sequence" in repr(s)
|
||||||
assert len(s) == 5
|
assert len(s) == 5
|
||||||
@ -123,16 +125,19 @@ def test_sequence():
|
|||||||
assert s[3] == approx(56.78, rel=1e-05)
|
assert s[3] == approx(56.78, rel=1e-05)
|
||||||
|
|
||||||
rev = reversed(s)
|
rev = reversed(s)
|
||||||
assert cstats.values() == ["of size", "5"]
|
if not env.GRAALPY:
|
||||||
|
assert cstats.values() == ["of size", "5"]
|
||||||
|
|
||||||
rev2 = s[::-1]
|
rev2 = s[::-1]
|
||||||
assert cstats.values() == ["of size", "5"]
|
if not env.GRAALPY:
|
||||||
|
assert cstats.values() == ["of size", "5"]
|
||||||
|
|
||||||
it = iter(m.Sequence(0))
|
it = iter(m.Sequence(0))
|
||||||
for _ in range(3): # __next__ must continue to raise StopIteration
|
for _ in range(3): # __next__ must continue to raise StopIteration
|
||||||
with pytest.raises(StopIteration):
|
with pytest.raises(StopIteration):
|
||||||
next(it)
|
next(it)
|
||||||
assert cstats.values() == ["of size", "0"]
|
if not env.GRAALPY:
|
||||||
|
assert cstats.values() == ["of size", "0"]
|
||||||
|
|
||||||
expected = [0, 56.78, 0, 0, 12.34]
|
expected = [0, 56.78, 0, 0, 12.34]
|
||||||
assert rev == approx(expected, rel=1e-05)
|
assert rev == approx(expected, rel=1e-05)
|
||||||
@ -140,10 +145,14 @@ def test_sequence():
|
|||||||
assert rev == rev2
|
assert rev == rev2
|
||||||
|
|
||||||
rev[0::2] = m.Sequence([2.0, 2.0, 2.0])
|
rev[0::2] = m.Sequence([2.0, 2.0, 2.0])
|
||||||
assert cstats.values() == ["of size", "3", "from std::vector"]
|
if not env.GRAALPY:
|
||||||
|
assert cstats.values() == ["of size", "3", "from std::vector"]
|
||||||
|
|
||||||
assert rev == approx([2, 56.78, 2, 0, 2], rel=1e-05)
|
assert rev == approx([2, 56.78, 2, 0, 2], rel=1e-05)
|
||||||
|
|
||||||
|
if env.GRAALPY:
|
||||||
|
pytest.skip("ConstructorStats is incompatible with GraalPy.")
|
||||||
|
|
||||||
assert cstats.alive() == 4
|
assert cstats.alive() == 4
|
||||||
del it
|
del it
|
||||||
assert cstats.alive() == 3
|
assert cstats.alive() == 3
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
||||||
|
@ -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__));
|
||||||
}
|
}
|
||||||
|
@ -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,6 +82,9 @@ def test_override(capture, msg):
|
|||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if env.GRAALPY:
|
||||||
|
pytest.skip("ConstructorStats is incompatible with GraalPy.")
|
||||||
|
|
||||||
cstats = ConstructorStats.get(m.ExampleVirt)
|
cstats = ConstructorStats.get(m.ExampleVirt)
|
||||||
assert cstats.alive() == 3
|
assert cstats.alive() == 3
|
||||||
del ex12, ex12p, ex12p2
|
del ex12, ex12p, ex12p2
|
||||||
@ -91,6 +94,7 @@ def test_override(capture, msg):
|
|||||||
assert cstats.move_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 +134,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 +193,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"
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user