From c82bbaa5e56504ed9053dbb1f0b65be12117c297 Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Wed, 27 Oct 2021 09:48:36 -0400 Subject: [PATCH 01/21] ci: support development releases of Python --- .github/workflows/ci.yml | 10 ++- .github/workflows/upstream.yml | 112 +++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/upstream.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3694f16363..e5388ede00 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,15 +31,14 @@ jobs: - '3.9' - '3.10' # - '3.11-dev' - - 'pypy-3.7-v7.3.5' - # - 'pypy-3.8' + - 'pypy-3.7-v7.3.7' + - 'pypy-3.8-v7.3.7' # 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 # existing keys match. # - # We support three optional keys: args (both build), args1 (first - # build), and args2 (second build). + # We support an optional keys: args, for cmake args include: # Just add a key - runs-on: ubuntu-latest @@ -122,7 +121,7 @@ jobs: run: git clean -fdx # Second build - C++17 mode and in a build directory - - name: Configure ${{ matrix.args2 }} + - name: Configure C++17 run: > cmake -S . -B build2 -DPYBIND11_WERROR=ON @@ -130,7 +129,6 @@ jobs: -DDOWNLOAD_EIGEN=ON -DCMAKE_CXX_STANDARD=17 ${{ matrix.args }} - ${{ matrix.args2 }} - name: Build run: cmake --build build2 -j 2 diff --git a/.github/workflows/upstream.yml b/.github/workflows/upstream.yml new file mode 100644 index 0000000000..f5c0d6794b --- /dev/null +++ b/.github/workflows/upstream.yml @@ -0,0 +1,112 @@ + +name: Upstream + +on: + workflow_dispatch: + pull_request: + +concurrency: + group: upstream-${{ github.ref }} + cancel-in-progress: true + +env: + PIP_ONLY_BINARY: numpy + +jobs: + standard: + name: "🐍 3.11 dev • ubuntu-latest • x64" + runs-on: ubuntu-latest + if: "contains(github.event.pull_request.labels.*.name, 'python dev')" + + steps: + - uses: actions/checkout@v2 + + - name: Setup Python 3.11 + uses: actions/setup-python@v2 + with: + python-version: "3.11-dev" + + - name: Setup Boost (Linux) + if: runner.os == 'Linux' + run: sudo apt-get install libboost-dev + + - name: Update CMake + uses: jwlawson/actions-setup-cmake@v1.11 + + - name: Prepare env + run: | + python -m pip install -r tests/requirements.txt + + - name: Setup annotations on Linux + if: runner.os == 'Linux' + run: python -m pip install pytest-github-actions-annotate-failures + + # First build - C++11 mode and inplace + - name: Configure C++11 + run: > + cmake -S . -B . + -DPYBIND11_WERROR=ON + -DDOWNLOAD_CATCH=ON + -DDOWNLOAD_EIGEN=ON + -DCMAKE_CXX_STANDARD=11 + + - name: Build C++11 + run: cmake --build . -j 2 + + - name: Python tests C++11 + run: cmake --build . --target pytest -j 2 + + - name: C++11 tests + run: cmake --build . --target cpptest -j 2 + + - name: Interface test C++11 + run: cmake --build . --target test_cmake_build + + - name: Clean directory + run: git clean -fdx + + # Second build - C++17 mode and in a build directory + - name: Configure C+=17 + run: > + cmake -S . -B build2 + -DPYBIND11_WERROR=ON + -DDOWNLOAD_CATCH=ON + -DDOWNLOAD_EIGEN=ON + -DCMAKE_CXX_STANDARD=17 + ${{ matrix.args }} + ${{ matrix.args2 }} + + - name: Build + run: cmake --build build2 -j 2 + + - name: Python tests + run: cmake --build build2 --target pytest + + - name: C++ tests + run: cmake --build build2 --target cpptest + + # Third build - C++17 mode with unstable ABI + - name: Configure (unstable ABI) + run: > + cmake -S . -B build3 + -DPYBIND11_WERROR=ON + -DDOWNLOAD_CATCH=ON + -DDOWNLOAD_EIGEN=ON + -DCMAKE_CXX_STANDARD=17 + -DPYBIND11_INTERNALS_VERSION=10000000 + "-DPYBIND11_TEST_OVERRIDE=test_call_policies.cpp;test_gil_scoped.cpp;test_thread.cpp" + ${{ matrix.args }} + + - name: Build (unstable ABI) + run: cmake --build build3 -j 2 + + - name: Python tests (unstable ABI) + run: cmake --build build3 --target pytest + + - name: Interface test + run: cmake --build build2 --target test_cmake_build + + # This makes sure the setup_helpers module can build packages using + # setuptools + - name: Setuptools helpers test + run: pytest tests/extra_setuptools From ee1fb1b04548e5f29e22410d44b7c6c1f61b59da Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Wed, 27 Oct 2021 15:54:23 -0400 Subject: [PATCH 02/21] fix: better PyPy support --- include/pybind11/eval.h | 4 ++-- tests/requirements.txt | 2 +- tests/test_buffers.py | 1 + tests/test_builtin_casters.py | 4 ++-- tests/test_embed/CMakeLists.txt | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/include/pybind11/eval.h b/include/pybind11/eval.h index 6cc672e2d5..4248551e9b 100644 --- a/include/pybind11/eval.h +++ b/include/pybind11/eval.h @@ -19,11 +19,11 @@ PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(detail) inline void ensure_builtins_in_globals(object &global) { - #if PY_VERSION_HEX < 0x03080000 + #if defined(PYPY_VERSION) || PY_VERSION_HEX < 0x03080000 // Running exec and eval on Python 2 and 3 adds `builtins` module under // `__builtins__` key to globals if not yet present. // Python 3.8 made PyRun_String behave similarly. Let's also do that for - // older versions, for consistency. + // older versions, for consistency. This was missing from PyPy3.8 7.3.7. if (!global.contains("__builtins__")) global["__builtins__"] = module_::import(PYBIND11_BUILTINS_MODULE); #else diff --git a/tests/requirements.txt b/tests/requirements.txt index 8d2742a71c..98ca46d28a 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -2,7 +2,7 @@ numpy==1.16.6; python_version<"3.6" and sys_platform!="win32" and platform_pytho numpy==1.19.0; platform_python_implementation=="PyPy" and sys_platform=="linux" and python_version=="3.6" numpy==1.20.0; platform_python_implementation=="PyPy" and sys_platform=="linux" and python_version=="3.7" numpy==1.19.3; platform_python_implementation!="PyPy" and python_version=="3.6" -numpy==1.21.3; platform_python_implementation!="PyPy" and python_version>="3.7" +numpy==1.21.3; platform_python_implementation!="PyPy" and python_version>="3.7" and python_version<"3.11" py @ git+https://github.com/pytest-dev/py; python_version>="3.11" pytest==4.6.9; python_version<"3.5" pytest==6.1.2; python_version=="3.5" diff --git a/tests/test_buffers.py b/tests/test_buffers.py index adf7cadff2..41cc23f4f4 100644 --- a/tests/test_buffers.py +++ b/tests/test_buffers.py @@ -62,6 +62,7 @@ def test_to_python(): assert cstats.alive() == 1 del mat2 # holds a mat reference pytest.gc_collect() + pytest.gc_collect() # Needed for PyPy assert cstats.alive() == 0 assert cstats.values() == ["5x4 matrix"] assert cstats.copy_constructions == 0 diff --git a/tests/test_builtin_casters.py b/tests/test_builtin_casters.py index 2a061c193e..db5ab48dac 100644 --- a/tests/test_builtin_casters.py +++ b/tests/test_builtin_casters.py @@ -299,7 +299,7 @@ def cant_convert(v): assert noconvert(7) == 7 cant_convert(3.14159) # TODO: Avoid DeprecationWarning in `PyLong_AsLong` (and similar) - if (3, 8) <= env.PY < (3, 10): + if (3, 8) <= env.PY < (3, 10) and env.CPYTHON: with env.deprecated_call(): assert convert(Int()) == 42 else: @@ -334,7 +334,7 @@ def require_implicit(v): # The implicit conversion from np.float32 is undesirable but currently accepted. # TODO: Avoid DeprecationWarning in `PyLong_AsLong` (and similar) - if (3, 8) <= env.PY < (3, 10): + if (3, 8) <= env.PY < (3, 10) and env.CPYTHON: with env.deprecated_call(): assert convert(np.float32(3.14159)) == 3 else: diff --git a/tests/test_embed/CMakeLists.txt b/tests/test_embed/CMakeLists.txt index 3b89d6e584..41e4d22cbe 100644 --- a/tests/test_embed/CMakeLists.txt +++ b/tests/test_embed/CMakeLists.txt @@ -7,7 +7,7 @@ if("${PYTHON_MODULE_EXTENSION}" MATCHES "pypy" OR "${Python_INTERPRETER_ID}" STR return() endif() -find_package(Catch 2.13.2) +find_package(Catch 2.13.7) if(CATCH_FOUND) message(STATUS "Building interpreter tests using Catch v${CATCH_VERSION}") From 3dfb03c210dff15976c22338dea98408ab6387aa Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Thu, 28 Oct 2021 10:25:36 -0400 Subject: [PATCH 03/21] fix: patch over a few more pypy issues --- include/pybind11/cast.h | 3 ++- tests/test_buffers.py | 1 + tests/test_exceptions.py | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 20fbb32587..8ce2fd9298 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -150,7 +150,8 @@ struct type_caster::value && !is_std_char_t return false; } else { handle src_or_index = src; -#if PY_VERSION_HEX < 0x03080000 + // PyPy: 7.3.7's 3.8 does not implement PyLong_*'s __index__ calls. +#if PY_VERSION_HEX < 0x03080000 || defined(PYPY_VERSION) object index; if (!PYBIND11_LONG_CHECK(src.ptr())) { // So: index_check(src.ptr()) index = reinterpret_steal(PyNumber_Index(src.ptr())); diff --git a/tests/test_buffers.py b/tests/test_buffers.py index 41cc23f4f4..62c772d0d3 100644 --- a/tests/test_buffers.py +++ b/tests/test_buffers.py @@ -63,6 +63,7 @@ def test_to_python(): del mat2 # holds a mat reference pytest.gc_collect() pytest.gc_collect() # Needed for PyPy + pytest.gc_collect() # Needed for PyPy assert cstats.alive() == 0 assert cstats.values() == ["5x4 matrix"] assert cstats.copy_constructions == 0 diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py index 3821eadaa4..29d69a1474 100644 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -109,6 +109,7 @@ def test_python_alreadyset_in_destructor(monkeypatch, capsys): def hook(unraisable_hook_args): exc_type, exc_value, exc_tb, err_msg, obj = unraisable_hook_args + print(locals()) if obj == "already_set demo": triggered[0] = True default_hook(unraisable_hook_args) From 80aac367231837a8de9c40663568873def029167 Mon Sep 17 00:00:00 2001 From: Aaron Gokaslan Date: Wed, 10 Nov 2021 12:34:27 -0500 Subject: [PATCH 04/21] Try to patch --- include/pybind11/pybind11.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index bfc1c368c0..5002422f33 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -2343,7 +2343,7 @@ inline function get_type_override(const void *this_ptr, const type_info *this_ty // f_code is guaranteed to not be NULL if ((std::string) str(f_code->co_name) == name && f_code->co_argcount > 0) { PyObject* locals = PyEval_GetLocals(); - if (locals != nullptr) { + if (locals != nullptr && f_code->co_varnames != nullptr && PyTuple_GET_SIZE(f_code->co_varnames) != 0) { PyObject *self_caller = dict_getitem( locals, PyTuple_GET_ITEM(f_code->co_varnames, 0) ); From ad0e5ae5781ecf970f385b6152d17355a4f29e68 Mon Sep 17 00:00:00 2001 From: Aaron Gokaslan Date: Wed, 10 Nov 2021 12:42:59 -0500 Subject: [PATCH 05/21] Properly follow pep667 --- include/pybind11/pybind11.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 5002422f33..47189d23d7 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -2342,8 +2342,8 @@ inline function get_type_override(const void *this_ptr, const type_info *this_ty PyCodeObject *f_code = PyFrame_GetCode(frame); // f_code is guaranteed to not be NULL if ((std::string) str(f_code->co_name) == name && f_code->co_argcount > 0) { - PyObject* locals = PyEval_GetLocals(); - if (locals != nullptr && f_code->co_varnames != nullptr && PyTuple_GET_SIZE(f_code->co_varnames) != 0) { + PyObject* locals = PyEval_GetLocals(frame); + if (locals != nullptr) { PyObject *self_caller = dict_getitem( locals, PyTuple_GET_ITEM(f_code->co_varnames, 0) ); From 2ffefc0d820f4868e514056db9cc12beb9c512aa Mon Sep 17 00:00:00 2001 From: Aaron Gokaslan Date: Wed, 10 Nov 2021 12:46:49 -0500 Subject: [PATCH 06/21] Fix typo --- include/pybind11/pybind11.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 47189d23d7..9c9121e211 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -2342,7 +2342,7 @@ inline function get_type_override(const void *this_ptr, const type_info *this_ty PyCodeObject *f_code = PyFrame_GetCode(frame); // f_code is guaranteed to not be NULL if ((std::string) str(f_code->co_name) == name && f_code->co_argcount > 0) { - PyObject* locals = PyEval_GetLocals(frame); + PyObject* locals = PyFrame_GetLocals(frame); if (locals != nullptr) { PyObject *self_caller = dict_getitem( locals, PyTuple_GET_ITEM(f_code->co_varnames, 0) From e47fe71cea126ae06c91c42f031923714ca1ddcc Mon Sep 17 00:00:00 2001 From: Aaron Gokaslan Date: Wed, 10 Nov 2021 12:51:08 -0500 Subject: [PATCH 07/21] Whoops, 667 not in yet --- include/pybind11/pybind11.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 9c9121e211..5002422f33 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -2342,8 +2342,8 @@ inline function get_type_override(const void *this_ptr, const type_info *this_ty PyCodeObject *f_code = PyFrame_GetCode(frame); // f_code is guaranteed to not be NULL if ((std::string) str(f_code->co_name) == name && f_code->co_argcount > 0) { - PyObject* locals = PyFrame_GetLocals(frame); - if (locals != nullptr) { + PyObject* locals = PyEval_GetLocals(); + if (locals != nullptr && f_code->co_varnames != nullptr && PyTuple_GET_SIZE(f_code->co_varnames) != 0) { PyObject *self_caller = dict_getitem( locals, PyTuple_GET_ITEM(f_code->co_varnames, 0) ); From 2688297721540ac2d24913bd8f4045feb49a17d7 Mon Sep 17 00:00:00 2001 From: Aaron Gokaslan Date: Wed, 10 Nov 2021 13:03:46 -0500 Subject: [PATCH 08/21] For testing --- include/pybind11/pybind11.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 5002422f33..347749353e 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -2342,8 +2342,8 @@ inline function get_type_override(const void *this_ptr, const type_info *this_ty PyCodeObject *f_code = PyFrame_GetCode(frame); // f_code is guaranteed to not be NULL if ((std::string) str(f_code->co_name) == name && f_code->co_argcount > 0) { - PyObject* locals = PyEval_GetLocals(); - if (locals != nullptr && f_code->co_varnames != nullptr && PyTuple_GET_SIZE(f_code->co_varnames) != 0) { + PyObject* locals = PyFrame_FastToLocals(frame); //PyEval_GetLocals(); + if (true) { PyObject *self_caller = dict_getitem( locals, PyTuple_GET_ITEM(f_code->co_varnames, 0) ); From 305def1abaacb3115abf1b0c2d6cdba0f85e4997 Mon Sep 17 00:00:00 2001 From: Aaron Gokaslan Date: Wed, 10 Nov 2021 13:08:16 -0500 Subject: [PATCH 09/21] More testing --- include/pybind11/pybind11.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 347749353e..8f3d3286cc 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -2342,7 +2342,8 @@ inline function get_type_override(const void *this_ptr, const type_info *this_ty PyCodeObject *f_code = PyFrame_GetCode(frame); // f_code is guaranteed to not be NULL if ((std::string) str(f_code->co_name) == name && f_code->co_argcount > 0) { - PyObject* locals = PyFrame_FastToLocals(frame); //PyEval_GetLocals(); + PyFrame_FastToLocals(frame); //PyEval_GetLocals(); + PyObject* locals = frame->f_locals; if (true) { PyObject *self_caller = dict_getitem( locals, PyTuple_GET_ITEM(f_code->co_varnames, 0) From 533f0c214ba02f6ad9d230f2d4052f66d2b838b2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 10 Nov 2021 18:08:45 +0000 Subject: [PATCH 10/21] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- include/pybind11/pybind11.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 8f3d3286cc..dab7ad6883 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -2342,7 +2342,7 @@ inline function get_type_override(const void *this_ptr, const type_info *this_ty PyCodeObject *f_code = PyFrame_GetCode(frame); // f_code is guaranteed to not be NULL if ((std::string) str(f_code->co_name) == name && f_code->co_argcount > 0) { - PyFrame_FastToLocals(frame); //PyEval_GetLocals(); + PyFrame_FastToLocals(frame); //PyEval_GetLocals(); PyObject* locals = frame->f_locals; if (true) { PyObject *self_caller = dict_getitem( From 0f1c3e097702f78bdcffcc188db349ae9bd893ed Mon Sep 17 00:00:00 2001 From: Aaron Gokaslan Date: Wed, 10 Nov 2021 13:20:16 -0500 Subject: [PATCH 11/21] Try to backport --- include/pybind11/pybind11.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 8f3d3286cc..2998d7b202 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -2342,8 +2342,12 @@ inline function get_type_override(const void *this_ptr, const type_info *this_ty PyCodeObject *f_code = PyFrame_GetCode(frame); // f_code is guaranteed to not be NULL if ((std::string) str(f_code->co_name) == name && f_code->co_argcount > 0) { - PyFrame_FastToLocals(frame); //PyEval_GetLocals(); + PyFrame_FastToLocals(frame); //PyEval_GetLocals(); +#if PY_VERSION_HEX >= 0x03110000 + PyObject* locals = frame->f_frame->f_locals; +#else PyObject* locals = frame->f_locals; +#endif if (true) { PyObject *self_caller = dict_getitem( locals, PyTuple_GET_ITEM(f_code->co_varnames, 0) From 52a2b24c6fe8709b392c026aa1f91525310edbad Mon Sep 17 00:00:00 2001 From: Aaron Gokaslan Date: Wed, 10 Nov 2021 13:33:12 -0500 Subject: [PATCH 12/21] Try to simplify fix --- include/pybind11/pybind11.h | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 2998d7b202..748e308ac3 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -2340,15 +2340,10 @@ inline function get_type_override(const void *this_ptr, const type_info *this_ty PyFrameObject *frame = PyThreadState_GetFrame(PyThreadState_Get()); if (frame != nullptr) { PyCodeObject *f_code = PyFrame_GetCode(frame); + PyObject* locals = PyEval_GetLocals(); // f_code is guaranteed to not be NULL if ((std::string) str(f_code->co_name) == name && f_code->co_argcount > 0) { - PyFrame_FastToLocals(frame); //PyEval_GetLocals(); -#if PY_VERSION_HEX >= 0x03110000 - PyObject* locals = frame->f_frame->f_locals; -#else - PyObject* locals = frame->f_locals; -#endif - if (true) { + if (locals != nullptr && PyTuple_GET_SIZE(f_code->co_varnames) != 0) { PyObject *self_caller = dict_getitem( locals, PyTuple_GET_ITEM(f_code->co_varnames, 0) ); From bfba3da369fd6471058b7fa98fcf934ac749df5f Mon Sep 17 00:00:00 2001 From: Aaron Gokaslan Date: Wed, 10 Nov 2021 13:48:39 -0500 Subject: [PATCH 13/21] Nail down the fix --- include/pybind11/pybind11.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 748e308ac3..8dedba37ca 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -2343,7 +2343,7 @@ inline function get_type_override(const void *this_ptr, const type_info *this_ty PyObject* locals = PyEval_GetLocals(); // f_code is guaranteed to not be NULL if ((std::string) str(f_code->co_name) == name && f_code->co_argcount > 0) { - if (locals != nullptr && PyTuple_GET_SIZE(f_code->co_varnames) != 0) { + if (locals != nullptr && f_code->co_varnames != nullptr) { PyObject *self_caller = dict_getitem( locals, PyTuple_GET_ITEM(f_code->co_varnames, 0) ); From 19cceb0d2aa92a9750440fcb0f90b9155548d28b Mon Sep 17 00:00:00 2001 From: Aaron Gokaslan Date: Thu, 11 Nov 2021 11:29:51 -0500 Subject: [PATCH 14/21] Try pypy workaround --- include/pybind11/pybind11.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 8dedba37ca..9228bd8d35 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -2334,18 +2334,18 @@ inline function get_type_override(const void *this_ptr, const type_info *this_ty /* Don't call dispatch code if invoked from overridden function. Unfortunately this doesn't work on PyPy. */ -#if !defined(PYPY_VERSION) +#if !defined(PYPY_VERSION) and PY_VERSION_HEX < 0x03110000 #if PY_VERSION_HEX >= 0x03090000 PyFrameObject *frame = PyThreadState_GetFrame(PyThreadState_Get()); if (frame != nullptr) { PyCodeObject *f_code = PyFrame_GetCode(frame); - PyObject* locals = PyEval_GetLocals(); // f_code is guaranteed to not be NULL if ((std::string) str(f_code->co_name) == name && f_code->co_argcount > 0) { + PyObject* locals = PyEval_GetLocals(); if (locals != nullptr && f_code->co_varnames != nullptr) { PyObject *self_caller = dict_getitem( - locals, PyTuple_GET_ITEM(f_code->co_varnames, 0) + locals, PyTuple_GET_ITEM(co_varnames, 0) ); if (self_caller == self.ptr()) { Py_DECREF(f_code); From 863035f6973d43a2b939b7501da69d35672b9ee1 Mon Sep 17 00:00:00 2001 From: Aaron Gokaslan Date: Thu, 11 Nov 2021 11:31:00 -0500 Subject: [PATCH 15/21] Typo --- include/pybind11/pybind11.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 9228bd8d35..b019a1910b 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -2334,7 +2334,7 @@ inline function get_type_override(const void *this_ptr, const type_info *this_ty /* Don't call dispatch code if invoked from overridden function. Unfortunately this doesn't work on PyPy. */ -#if !defined(PYPY_VERSION) and PY_VERSION_HEX < 0x03110000 +#if !defined(PYPY_VERSION) && PY_VERSION_HEX < 0x03110000 #if PY_VERSION_HEX >= 0x03090000 PyFrameObject *frame = PyThreadState_GetFrame(PyThreadState_Get()); From 76963536c46a7ca2101b3cfe155c8b614c5db841 Mon Sep 17 00:00:00 2001 From: Aaron Gokaslan Date: Thu, 11 Nov 2021 11:32:01 -0500 Subject: [PATCH 16/21] one last typo --- include/pybind11/pybind11.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index b019a1910b..79ffdab8a6 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -2345,7 +2345,7 @@ inline function get_type_override(const void *this_ptr, const type_info *this_ty PyObject* locals = PyEval_GetLocals(); if (locals != nullptr && f_code->co_varnames != nullptr) { PyObject *self_caller = dict_getitem( - locals, PyTuple_GET_ITEM(co_varnames, 0) + locals, PyTuple_GET_ITEM(f_code->co_varnames, 0) ); if (self_caller == self.ptr()) { Py_DECREF(f_code); From 6dd395db69922e14bf160b7c8c0180a7f0bcb5a9 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Thu, 11 Nov 2021 12:28:56 -0800 Subject: [PATCH 17/21] Replacing 0x03110000 with 0x030B0000 --- include/pybind11/pybind11.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 79ffdab8a6..ef2f042a5d 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -2334,7 +2334,7 @@ inline function get_type_override(const void *this_ptr, const type_info *this_ty /* Don't call dispatch code if invoked from overridden function. Unfortunately this doesn't work on PyPy. */ -#if !defined(PYPY_VERSION) && PY_VERSION_HEX < 0x03110000 +#if !defined(PYPY_VERSION) && PY_VERSION_HEX < 0x030B0000 #if PY_VERSION_HEX >= 0x03090000 PyFrameObject *frame = PyThreadState_GetFrame(PyThreadState_Get()); From 04b6107aeddb7cdc0d2ac0e788fc24702dfbd7be Mon Sep 17 00:00:00 2001 From: Aaron Gokaslan Date: Tue, 16 Nov 2021 11:04:00 -0500 Subject: [PATCH 18/21] Add TODO. Drop PyPy --- .github/workflows/ci.yml | 4 ++-- include/pybind11/pybind11.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 84832e0dc0..bc4c1ca6eb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,8 +31,8 @@ jobs: - '3.9' - '3.10' # - '3.11-dev' - - 'pypy-3.7-v7.3.7' - - 'pypy-3.8-v7.3.7' + - 'pypy-3.7-v7.3.5' + #- 'pypy-3.8-v7.3.7' # 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 diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 2661d961be..a6b6411c14 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -2366,7 +2366,8 @@ inline function get_type_override(const void *this_ptr, const type_info *this_ty /* Don't call dispatch code if invoked from overridden function. Unfortunately this doesn't work on PyPy. */ #if !defined(PYPY_VERSION) && PY_VERSION_HEX < 0x030B0000 - + // TODO: Remove PyPy workaround for Python 3.11. + // Current API fails on 3.11 since covarnames can be null. #if PY_VERSION_HEX >= 0x03090000 PyFrameObject *frame = PyThreadState_GetFrame(PyThreadState_Get()); if (frame != nullptr) { From e07514aa59d78952feb723b874709f823f66a984 Mon Sep 17 00:00:00 2001 From: Aaron Gokaslan Date: Tue, 16 Nov 2021 11:06:43 -0500 Subject: [PATCH 19/21] Fix typo --- .github/workflows/upstream.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/upstream.yml b/.github/workflows/upstream.yml index f5c0d6794b..654947425f 100644 --- a/.github/workflows/upstream.yml +++ b/.github/workflows/upstream.yml @@ -66,7 +66,7 @@ jobs: run: git clean -fdx # Second build - C++17 mode and in a build directory - - name: Configure C+=17 + - name: Configure C++17 run: > cmake -S . -B build2 -DPYBIND11_WERROR=ON From 60cee13c19de811c951a232433dd82dfce7738e6 Mon Sep 17 00:00:00 2001 From: Aaron Gokaslan Date: Tue, 16 Nov 2021 11:41:29 -0500 Subject: [PATCH 20/21] Revert catch upgrade --- tests/test_embed/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_embed/CMakeLists.txt b/tests/test_embed/CMakeLists.txt index 64cf8b20c8..edb8961a7d 100644 --- a/tests/test_embed/CMakeLists.txt +++ b/tests/test_embed/CMakeLists.txt @@ -7,7 +7,7 @@ if("${PYTHON_MODULE_EXTENSION}" MATCHES "pypy" OR "${Python_INTERPRETER_ID}" STR return() endif() -find_package(Catch 2.13.7) +find_package(Catch 2.13.2) if(CATCH_FOUND) message(STATUS "Building interpreter tests using Catch v${CATCH_VERSION}") From 0618bd5d937e9d011cc454139c8a8ff560b0815d Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Tue, 16 Nov 2021 14:47:29 -0500 Subject: [PATCH 21/21] fix: minor cleanup, try pypy again --- .github/workflows/ci.yml | 5 ++--- include/pybind11/pybind11.h | 2 +- tests/test_buffers.py | 6 ++++-- tests/test_builtin_casters.py | 3 +++ tests/test_exceptions.py | 5 +++-- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bc4c1ca6eb..dcc61ecd74 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,9 +30,8 @@ jobs: - '3.6' - '3.9' - '3.10' - # - '3.11-dev' - - 'pypy-3.7-v7.3.5' - #- 'pypy-3.8-v7.3.7' + - 'pypy-3.7-v7.3.7' + - 'pypy-3.8-v7.3.7' # 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 diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index a6b6411c14..cfe03f6dbd 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -2367,7 +2367,7 @@ inline function get_type_override(const void *this_ptr, const type_info *this_ty Unfortunately this doesn't work on PyPy. */ #if !defined(PYPY_VERSION) && PY_VERSION_HEX < 0x030B0000 // TODO: Remove PyPy workaround for Python 3.11. - // Current API fails on 3.11 since covarnames can be null. + // Current API fails on 3.11 since co_varnames can be null. #if PY_VERSION_HEX >= 0x03090000 PyFrameObject *frame = PyThreadState_GetFrame(PyThreadState_Get()); if (frame != nullptr) { diff --git a/tests/test_buffers.py b/tests/test_buffers.py index 62c772d0d3..0877dc0e41 100644 --- a/tests/test_buffers.py +++ b/tests/test_buffers.py @@ -36,6 +36,10 @@ def test_from_python(): # https://foss.heptapod.net/pypy/pypy/-/issues/2444 +# TODO: fix on recent PyPy +@pytest.mark.xfail( + env.PYPY, reason="PyPy 7.3.7 doesn't clear this anymore", stict=False +) def test_to_python(): mat = m.Matrix(5, 4) assert memoryview(mat).shape == (5, 4) @@ -62,8 +66,6 @@ def test_to_python(): assert cstats.alive() == 1 del mat2 # holds a mat reference pytest.gc_collect() - pytest.gc_collect() # Needed for PyPy - pytest.gc_collect() # Needed for PyPy assert cstats.alive() == 0 assert cstats.values() == ["5x4 matrix"] assert cstats.copy_constructions == 0 diff --git a/tests/test_builtin_casters.py b/tests/test_builtin_casters.py index db5ab48dac..9c5e17a68e 100644 --- a/tests/test_builtin_casters.py +++ b/tests/test_builtin_casters.py @@ -299,6 +299,7 @@ def cant_convert(v): assert noconvert(7) == 7 cant_convert(3.14159) # TODO: Avoid DeprecationWarning in `PyLong_AsLong` (and similar) + # TODO: PyPy 3.8 does not behave like CPython 3.8 here yet (7.3.7) if (3, 8) <= env.PY < (3, 10) and env.CPYTHON: with env.deprecated_call(): assert convert(Int()) == 42 @@ -334,6 +335,8 @@ def require_implicit(v): # The implicit conversion from np.float32 is undesirable but currently accepted. # TODO: Avoid DeprecationWarning in `PyLong_AsLong` (and similar) + # TODO: PyPy 3.8 does not behave like CPython 3.8 here yet (7.3.7) + # https://github.com/pybind/pybind11/issues/3408 if (3, 8) <= env.PY < (3, 10) and env.CPYTHON: with env.deprecated_call(): assert convert(np.float32(3.14159)) == 3 diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py index 29d69a1474..56201a81c5 100644 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -3,7 +3,7 @@ import pytest -import env # noqa: F401 +import env import pybind11_cross_module_tests as cm from pybind11_tests import exceptions as m @@ -97,6 +97,8 @@ def ignore_pytest_unraisable_warning(f): return f +# TODO: find out why this fails on PyPy, https://foss.heptapod.net/pypy/pypy/-/issues/3583 +@pytest.mark.xfail(env.PYPY, reason="Failure on PyPy 3.8 (7.3.7)", strict=False) @ignore_pytest_unraisable_warning def test_python_alreadyset_in_destructor(monkeypatch, capsys): hooked = False @@ -109,7 +111,6 @@ def test_python_alreadyset_in_destructor(monkeypatch, capsys): def hook(unraisable_hook_args): exc_type, exc_value, exc_tb, err_msg, obj = unraisable_hook_args - print(locals()) if obj == "already_set demo": triggered[0] = True default_hook(unraisable_hook_args)