Skip to content

Commit 585cc4f

Browse files
Merge branch 'pybind:master' into master
2 parents 9362b78 + c4a05f9 commit 585cc4f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+211
-66
lines changed

.github/workflows/ci.yml

+5
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ jobs:
3939
- 'pypy-3.8'
4040
- 'pypy-3.9'
4141
- 'pypy-3.10'
42+
- 'graalpy-24.1'
4243

4344
# Items in here will either be added to the build matrix (if not
4445
# present), or add new keys to an existing matrix element if all the
@@ -67,6 +68,10 @@ jobs:
6768
# Extra ubuntu latest job
6869
- runs-on: ubuntu-latest
6970
python: '3.11'
71+
exclude:
72+
# The setup-python action currently doesn't have graalpy for windows
73+
- python: 'graalpy-24.1'
74+
runs-on: 'windows-2022'
7075

7176

7277
name: "🐍 ${{ matrix.python }} • ${{ matrix.runs-on }} • x64 ${{ matrix.args }}"

include/pybind11/cast.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ class type_caster<bool> {
343343
#else
344344
// Alternate approach for CPython: this does the same as the above, but optimized
345345
// using the CPython API so as to avoid an unneeded attribute lookup.
346-
else if (auto *tp_as_number = src.ptr()->ob_type->tp_as_number) {
346+
else if (auto *tp_as_number = Py_TYPE(src.ptr())->tp_as_number) {
347347
if (PYBIND11_NB_BOOL(tp_as_number)) {
348348
res = (*PYBIND11_NB_BOOL(tp_as_number))(src.ptr());
349349
}

include/pybind11/detail/common.h

+15-1
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ PYBIND11_WARNING_DISABLE_MSVC(4505)
299299
# define PYBIND11_INTERNAL_NUMPY_1_ONLY_DETECTED
300300
#endif
301301

302-
#if defined(PYPY_VERSION) && !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
302+
#if (defined(PYPY_VERSION) || defined(GRAALVM_PYTHON)) && !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
303303
# define PYBIND11_SIMPLE_GIL_MANAGEMENT
304304
#endif
305305

@@ -387,6 +387,20 @@ PYBIND11_WARNING_POP
387387
#define PYBIND11_CONCAT(first, second) first##second
388388
#define PYBIND11_ENSURE_INTERNALS_READY pybind11::detail::get_internals();
389389

390+
#if !defined(GRAALVM_PYTHON)
391+
# define PYBIND11_PYCFUNCTION_GET_DOC(func) ((func)->m_ml->ml_doc)
392+
# define PYBIND11_PYCFUNCTION_SET_DOC(func, doc) \
393+
do { \
394+
(func)->m_ml->ml_doc = (doc); \
395+
} while (0)
396+
#else
397+
# define PYBIND11_PYCFUNCTION_GET_DOC(func) (GraalPyCFunction_GetDoc((PyObject *) (func)))
398+
# define PYBIND11_PYCFUNCTION_SET_DOC(func, doc) \
399+
do { \
400+
GraalPyCFunction_SetDoc((PyObject *) (func), (doc)); \
401+
} while (0)
402+
#endif
403+
390404
#define PYBIND11_CHECK_PYTHON_VERSION \
391405
{ \
392406
const char *compiled_ver \

include/pybind11/detail/internals.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ inline void translate_local_exception(std::exception_ptr p) {
454454

455455
inline object get_python_state_dict() {
456456
object state_dict;
457-
#if PYBIND11_INTERNALS_VERSION <= 4 || defined(PYPY_VERSION)
457+
#if PYBIND11_INTERNALS_VERSION <= 4 || defined(PYPY_VERSION) || defined(GRAALVM_PYTHON)
458458
state_dict = reinterpret_borrow<object>(PyEval_GetBuiltins());
459459
#else
460460
# if PY_VERSION_HEX < 0x03090000
@@ -727,7 +727,8 @@ const char *c_str(Args &&...args) {
727727
}
728728

729729
inline const char *get_function_record_capsule_name() {
730-
#if PYBIND11_INTERNALS_VERSION > 4
730+
// On GraalPy, pointer equality of the names is currently not guaranteed
731+
#if PYBIND11_INTERNALS_VERSION > 4 && !defined(GRAALVM_PYTHON)
731732
return get_internals().function_record_capsule_name.c_str();
732733
#else
733734
return nullptr;

include/pybind11/detail/type_caster_base.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ PYBIND11_NOINLINE handle get_object_handle(const void *ptr, const detail::type_i
459459
}
460460

461461
inline PyThreadState *get_thread_state_unchecked() {
462-
#if defined(PYPY_VERSION)
462+
#if defined(PYPY_VERSION) || defined(GRAALVM_PYTHON)
463463
return PyThreadState_GET();
464464
#elif PY_VERSION_HEX < 0x030D0000
465465
return _PyThreadState_UncheckedGet();

include/pybind11/eval.h

+4-4
Original file line numberDiff line numberDiff line change
@@ -94,18 +94,18 @@ void exec(const char (&s)[N], object global = globals(), object local = object()
9494
eval<eval_statements>(s, std::move(global), std::move(local));
9595
}
9696

97-
#if defined(PYPY_VERSION)
97+
#if defined(PYPY_VERSION) || defined(GRAALVM_PYTHON)
9898
template <eval_mode mode = eval_statements>
9999
object eval_file(str, object, object) {
100-
pybind11_fail("eval_file not supported in PyPy3. Use eval");
100+
pybind11_fail("eval_file not supported in this interpreter. Use eval");
101101
}
102102
template <eval_mode mode = eval_statements>
103103
object eval_file(str, object) {
104-
pybind11_fail("eval_file not supported in PyPy3. Use eval");
104+
pybind11_fail("eval_file not supported in this interpreter. Use eval");
105105
}
106106
template <eval_mode mode = eval_statements>
107107
object eval_file(str) {
108-
pybind11_fail("eval_file not supported in PyPy3. Use eval");
108+
pybind11_fail("eval_file not supported in this interpreter. Use eval");
109109
}
110110
#else
111111
template <eval_mode mode = eval_statements>

include/pybind11/pybind11.h

+6-8
Original file line numberDiff line numberDiff line change
@@ -573,8 +573,7 @@ class cpp_function : public function {
573573
// chain.
574574
chain_start = rec;
575575
rec->next = chain;
576-
auto rec_capsule
577-
= reinterpret_borrow<capsule>(((PyCFunctionObject *) m_ptr)->m_self);
576+
auto rec_capsule = reinterpret_borrow<capsule>(PyCFunction_GET_SELF(m_ptr));
578577
rec_capsule.set_pointer(unique_rec.release());
579578
guarded_strdup.release();
580579
} else {
@@ -634,12 +633,11 @@ class cpp_function : public function {
634633
}
635634
}
636635

637-
/* Install docstring */
638636
auto *func = (PyCFunctionObject *) m_ptr;
639-
std::free(const_cast<char *>(func->m_ml->ml_doc));
640637
// Install docstring if it's non-empty (when at least one option is enabled)
641-
func->m_ml->ml_doc
642-
= signatures.empty() ? nullptr : PYBIND11_COMPAT_STRDUP(signatures.c_str());
638+
auto *doc = signatures.empty() ? nullptr : PYBIND11_COMPAT_STRDUP(signatures.c_str());
639+
std::free(const_cast<char *>(PYBIND11_PYCFUNCTION_GET_DOC(func)));
640+
PYBIND11_PYCFUNCTION_SET_DOC(func, doc);
643641

644642
if (rec->is_method) {
645643
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 *
27802778
}
27812779

27822780
/* Don't call dispatch code if invoked from overridden function.
2783-
Unfortunately this doesn't work on PyPy. */
2784-
#if !defined(PYPY_VERSION)
2781+
Unfortunately this doesn't work on PyPy and GraalPy. */
2782+
#if !defined(PYPY_VERSION) && !defined(GRAALVM_PYTHON)
27852783
# if PY_VERSION_HEX >= 0x03090000
27862784
PyFrameObject *frame = PyThreadState_GetFrame(PyThreadState_Get());
27872785
if (frame != nullptr) {

include/pybind11/pytypes.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,7 @@ struct error_fetch_and_normalize {
643643

644644
bool have_trace = false;
645645
if (m_trace) {
646-
#if !defined(PYPY_VERSION)
646+
#if !defined(PYPY_VERSION) && !defined(GRAALVM_PYTHON)
647647
auto *tb = reinterpret_cast<PyTracebackObject *>(m_trace.ptr());
648648

649649
// Get the deepest trace possible.
@@ -1356,7 +1356,7 @@ inline bool PyUnicode_Check_Permissive(PyObject *o) {
13561356
# define PYBIND11_STR_CHECK_FUN PyUnicode_Check
13571357
#endif
13581358

1359-
inline bool PyStaticMethod_Check(PyObject *o) { return o->ob_type == &PyStaticMethod_Type; }
1359+
inline bool PyStaticMethod_Check(PyObject *o) { return Py_TYPE(o) == &PyStaticMethod_Type; }
13601360

13611361
class kwargs_proxy : public handle {
13621362
public:

tests/conftest.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828

2929
@pytest.fixture(scope="session", autouse=True)
3030
def use_multiprocessing_forkserver_on_linux():
31-
if sys.platform != "linux":
32-
# The default on Windows and macOS is "spawn": If it's not broken, don't fix it.
31+
if sys.platform != "linux" or sys.implementation.name == "graalpy":
32+
# The default on Windows, macOS and GraalPy is "spawn": If it's not broken, don't fix it.
3333
return
3434

3535
# Full background: https://github.com/pybind/pybind11/issues/4105#issuecomment-1301004592

tests/env.py

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
CPYTHON = platform.python_implementation() == "CPython"
1414
PYPY = platform.python_implementation() == "PyPy"
15+
GRAALPY = sys.implementation.name == "graalpy"
1516
PY_GIL_DISABLED = bool(sysconfig.get_config_var("Py_GIL_DISABLED"))
1617

1718

tests/requirements.txt

+7-6
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
build~=1.0; python_version>="3.8"
33
numpy~=1.23.0; python_version=="3.8" and platform_python_implementation=="PyPy"
44
numpy~=1.25.0; python_version=="3.9" and platform_python_implementation=='PyPy'
5-
numpy~=1.21.5; platform_python_implementation!="PyPy" and python_version>="3.8" and python_version<"3.10"
6-
numpy~=1.22.2; platform_python_implementation!="PyPy" and python_version=="3.10"
7-
numpy~=1.26.0; platform_python_implementation!="PyPy" and python_version>="3.11" and python_version<"3.13"
5+
numpy~=1.26.0; platform_python_implementation=="GraalVM" and sys_platform=="linux"
6+
numpy~=1.21.5; platform_python_implementation!="PyPy" and platform_python_implementation!="GraalVM" and python_version>="3.8" and python_version<"3.10"
7+
numpy~=1.22.2; platform_python_implementation!="PyPy" and platform_python_implementation!="GraalVM" and python_version=="3.10"
8+
numpy~=1.26.0; platform_python_implementation!="PyPy" and platform_python_implementation!="GraalVM" and python_version>="3.11" and python_version<"3.13"
89
pytest~=7.0
910
pytest-timeout
10-
scipy~=1.5.4; platform_python_implementation!="PyPy" and python_version<"3.10"
11-
scipy~=1.8.0; platform_python_implementation!="PyPy" and python_version=="3.10" and sys_platform!='win32'
12-
scipy~=1.11.1; platform_python_implementation!="PyPy" and python_version>="3.11" and python_version<"3.13" and sys_platform!='win32'
11+
scipy~=1.5.4; platform_python_implementation!="PyPy" and platform_python_implementation!="GraalVM" and python_version<"3.10"
12+
scipy~=1.8.0; platform_python_implementation!="PyPy" and platform_python_implementation!="GraalVM" and python_version=="3.10" and sys_platform!='win32'
13+
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'

tests/test_buffers.py

+4
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ def test_from_python():
8282
for j in range(m4.cols()):
8383
assert m3[i, j] == m4[i, j]
8484

85+
if env.GRAALPY:
86+
pytest.skip("ConstructorStats is incompatible with GraalPy.")
8587
cstats = ConstructorStats.get(m.Matrix)
8688
assert cstats.alive() == 1
8789
del m3, m4
@@ -118,6 +120,8 @@ def test_to_python():
118120
mat2[2, 3] = 5
119121
assert mat2[2, 3] == 5
120122

123+
if env.GRAALPY:
124+
pytest.skip("ConstructorStats is incompatible with GraalPy.")
121125
cstats = ConstructorStats.get(m.Matrix)
122126
assert cstats.alive() == 1
123127
del mat

tests/test_call_policies.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ TEST_SUBMODULE(call_policies, m) {
9595
},
9696
py::call_guard<DependentGuard, CustomGuard>());
9797

98-
#if !defined(PYPY_VERSION)
99-
// `py::call_guard<py::gil_scoped_release>()` should work in PyPy as well,
98+
#if !defined(PYPY_VERSION) && !defined(GRAALVM_PYTHON)
99+
// `py::call_guard<py::gil_scoped_release>()` should work in PyPy/GraalPy as well,
100100
// but it's unclear how to test it without `PyGILState_GetThisThreadState`.
101101
auto report_gil_status = []() {
102102
auto is_gil_held = false;

tests/test_call_policies.py

+5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99

1010
@pytest.mark.xfail("env.PYPY", reason="sometimes comes out 1 off on PyPy", strict=False)
11+
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
1112
def test_keep_alive_argument(capture):
1213
n_inst = ConstructorStats.detail_reg_inst()
1314
with capture:
@@ -60,6 +61,7 @@ def test_keep_alive_argument(capture):
6061
assert str(excinfo.value) == "Could not activate keep_alive!"
6162

6263

64+
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
6365
def test_keep_alive_return_value(capture):
6466
n_inst = ConstructorStats.detail_reg_inst()
6567
with capture:
@@ -118,6 +120,7 @@ def test_keep_alive_return_value(capture):
118120

119121
# https://foss.heptapod.net/pypy/pypy/-/issues/2447
120122
@pytest.mark.xfail("env.PYPY", reason="_PyObject_GetDictPtr is unimplemented")
123+
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
121124
def test_alive_gc(capture):
122125
n_inst = ConstructorStats.detail_reg_inst()
123126
p = m.ParentGC()
@@ -137,6 +140,7 @@ def test_alive_gc(capture):
137140
)
138141

139142

143+
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
140144
def test_alive_gc_derived(capture):
141145
class Derived(m.Parent):
142146
pass
@@ -159,6 +163,7 @@ class Derived(m.Parent):
159163
)
160164

161165

166+
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
162167
def test_alive_gc_multi_derived(capture):
163168
class Derived(m.Parent, m.Child):
164169
def __init__(self):

tests/test_callbacks.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ TEST_SUBMODULE(callbacks, m) {
270270
m.add_object("custom_function", PyCFunction_New(custom_def, rec_capsule.ptr()));
271271

272272
// This test requires a new ABI version to pass
273-
#if PYBIND11_INTERNALS_VERSION > 4
273+
#if PYBIND11_INTERNALS_VERSION > 4 && !defined(GRAALVM_PYTHON)
274274
// rec_capsule with nullptr name
275275
py::capsule rec_capsule2(std::malloc(1), [](void *data) { std::free(data); });
276276
m.add_object("custom_function2", PyCFunction_New(custom_def, rec_capsule2.ptr()));

tests/test_callbacks.py

+2
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ def f(*args, **kwargs):
9090
)
9191

9292

93+
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
9394
def test_lambda_closure_cleanup():
9495
m.test_lambda_closure_cleanup()
9596
cstats = m.payload_cstats()
@@ -98,6 +99,7 @@ def test_lambda_closure_cleanup():
9899
assert cstats.move_constructions >= 1
99100

100101

102+
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
101103
def test_cpp_callable_cleanup():
102104
alive_counts = m.test_cpp_callable_cleanup()
103105
assert alive_counts == [0, 1, 2, 1, 2, 1, 0]

tests/test_class.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ def test_brace_initialization():
361361
assert b.vec == [123, 456]
362362

363363

364-
@pytest.mark.xfail("env.PYPY")
364+
@pytest.mark.xfail("env.PYPY or env.GRAALPY")
365365
def test_class_refcount():
366366
"""Instances must correctly increase/decrease the reference count of their types (#1029)"""
367367
from sys import getrefcount

tests/test_cmake_build/CMakeLists.txt

+11-5
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,10 @@ possibly_uninitialized(PYTHON_MODULE_EXTENSION Python_INTERPRETER_ID)
5555

5656
pybind11_add_build_test(subdirectory_function)
5757
pybind11_add_build_test(subdirectory_target)
58-
if("${PYTHON_MODULE_EXTENSION}" MATCHES "pypy" OR "${Python_INTERPRETER_ID}" STREQUAL "PyPy")
59-
message(STATUS "Skipping embed test on PyPy")
58+
if("${PYTHON_MODULE_EXTENSION}" MATCHES "pypy"
59+
OR "${Python_INTERPRETER_ID}" STREQUAL "PyPy"
60+
OR "${PYTHON_MODULE_EXTENSION}" MATCHES "graalpy")
61+
message(STATUS "Skipping embed test on PyPy or GraalPy")
6062
else()
6163
pybind11_add_build_test(subdirectory_embed)
6264
endif()
@@ -66,10 +68,14 @@ if(PYBIND11_INSTALL)
6668
mock_install ${CMAKE_COMMAND} "-DCMAKE_INSTALL_PREFIX=${pybind11_BINARY_DIR}/mock_install" -P
6769
"${pybind11_BINARY_DIR}/cmake_install.cmake")
6870

69-
pybind11_add_build_test(installed_function INSTALL)
71+
if(NOT "${PYTHON_MODULE_EXTENSION}" MATCHES "graalpy")
72+
pybind11_add_build_test(installed_function INSTALL)
73+
endif()
7074
pybind11_add_build_test(installed_target INSTALL)
71-
if(NOT ("${PYTHON_MODULE_EXTENSION}" MATCHES "pypy" OR "${Python_INTERPRETER_ID}" STREQUAL "PyPy"
72-
))
75+
if(NOT
76+
("${PYTHON_MODULE_EXTENSION}" MATCHES "pypy"
77+
OR "${Python_INTERPRETER_ID}" STREQUAL "PyPy"
78+
OR "${PYTHON_MODULE_EXTENSION}" MATCHES "graalpy"))
7379
pybind11_add_build_test(installed_embed INSTALL)
7480
endif()
7581
endif()

tests/test_cpp_conduit.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import home_planet_very_lonely_traveler
88
import pytest
99

10+
import env
1011
from pybind11_tests import cpp_conduit as home_planet
1112

1213

@@ -27,7 +28,10 @@ def test_call_cpp_conduit_success():
2728
home_planet.cpp_type_info_capsule_Traveler,
2829
b"raw_pointer_ephemeral",
2930
)
30-
assert cap.__class__.__name__ == "PyCapsule"
31+
assert cap.__class__.__name__ == "PyCapsule" or (
32+
# Note: this will become unnecessary in the next GraalPy release
33+
env.GRAALPY and cap.__class__.__name__ == "capsule"
34+
)
3135

3236

3337
def test_call_cpp_conduit_platform_abi_id_mismatch():

tests/test_custom_type_setup.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,15 @@ def add_ref(obj):
3434

3535

3636
# PyPy does not seem to reliably garbage collect.
37-
@pytest.mark.skipif("env.PYPY")
37+
@pytest.mark.skipif("env.PYPY or env.GRAALPY")
3838
def test_self_cycle(gc_tester):
3939
obj = m.OwnsPythonObjects()
4040
obj.value = obj
4141
gc_tester(obj)
4242

4343

4444
# PyPy does not seem to reliably garbage collect.
45-
@pytest.mark.skipif("env.PYPY")
45+
@pytest.mark.skipif("env.PYPY or env.GRAALPY")
4646
def test_indirect_cycle(gc_tester):
4747
obj = m.OwnsPythonObjects()
4848
obj_list = [obj]

tests/test_eigen_matrix.py

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import pytest
44

5+
import env # noqa: F401
56
from pybind11_tests import ConstructorStats
67

78
np = pytest.importorskip("numpy")
@@ -409,6 +410,7 @@ def assert_keeps_alive(cl, method, *args):
409410
assert cstats.alive() == start_with
410411

411412

413+
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
412414
def test_eigen_keepalive():
413415
a = m.ReturnTester()
414416
cstats = ConstructorStats.get(m.ReturnTester)

0 commit comments

Comments
 (0)