From 9ef65cee0e780e6443fa0813122712c9ae4bdcc7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Feb 2023 00:16:52 -0500 Subject: [PATCH 1/7] chore(deps): bump ilammy/msvc-dev-cmd from 1.12.0 to 1.12.1 (#4493) Bumps [ilammy/msvc-dev-cmd](https://github.com/ilammy/msvc-dev-cmd) from 1.12.0 to 1.12.1. - [Release notes](https://github.com/ilammy/msvc-dev-cmd/releases) - [Commits](https://github.com/ilammy/msvc-dev-cmd/compare/v1.12.0...v1.12.1) --- updated-dependencies: - dependency-name: ilammy/msvc-dev-cmd dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7c5fcb43a..8befccdbc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -766,7 +766,7 @@ jobs: uses: jwlawson/actions-setup-cmake@v1.13 - name: Prepare MSVC - uses: ilammy/msvc-dev-cmd@v1.12.0 + uses: ilammy/msvc-dev-cmd@v1.12.1 with: arch: x86 @@ -819,7 +819,7 @@ jobs: uses: jwlawson/actions-setup-cmake@v1.13 - name: Prepare MSVC - uses: ilammy/msvc-dev-cmd@v1.12.0 + uses: ilammy/msvc-dev-cmd@v1.12.1 with: arch: x86 From b2c1978caaa6627095e3326f7ecba84b43037869 Mon Sep 17 00:00:00 2001 From: Aaron Gokaslan Date: Mon, 6 Feb 2023 11:36:05 -0500 Subject: [PATCH 2/7] bugfix: Keep registered types until after Py_Finalize(). Fix #4459 (#4486) * Keep registered types until after Py_Finalize(). Fix #4459 * Address reviewer comments --- include/pybind11/embed.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/include/pybind11/embed.h b/include/pybind11/embed.h index 5a175b134..8450d5358 100644 --- a/include/pybind11/embed.h +++ b/include/pybind11/embed.h @@ -254,13 +254,16 @@ inline void finalize_interpreter() { if (builtins.contains(id) && isinstance(builtins[id])) { internals_ptr_ptr = capsule(builtins[id]); } - // Local internals contains data managed by the current interpreter, so we must clear them to - // avoid undefined behaviors when initializing another interpreter - detail::get_local_internals().registered_types_cpp.clear(); - detail::get_local_internals().registered_exception_translators.clear(); Py_Finalize(); + // Local internals contains data managed by the current interpreter, so we must clear them to + // avoid undefined behaviors when initializing another interpreter + // Must be cleared only after Py_Finalize() so atexit and other hooks can still use + // registered_types + detail::get_local_internals().registered_types_cpp.clear(); + detail::get_local_internals().registered_exception_translators.clear(); + if (internals_ptr_ptr) { delete *internals_ptr_ptr; *internals_ptr_ptr = nullptr; From 8a90b36772f36da577c485bd450130c8318c8111 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 7 Feb 2023 01:16:25 -0500 Subject: [PATCH 3/7] chore(deps): update pre-commit hooks (#4495) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/PyCQA/pylint: v2.16.0 → v2.16.1](https://github.com/PyCQA/pylint/compare/v2.16.0...v2.16.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 363ac71c6..27474f2f7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -116,7 +116,7 @@ repos: # PyLint has native support - not always usable, but works for us - repo: https://github.com/PyCQA/pylint - rev: "v2.16.0" + rev: "v2.16.1" hooks: - id: pylint files: ^pybind11 From f8713ec43e6833033b43126c8b55de97242ab4dd Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 7 Feb 2023 16:55:00 -0800 Subject: [PATCH 4/7] Revert "bugfix: Keep registered types until after Py_Finalize(). Fix #4459 (#4486)" (#4501) This reverts commit b2c1978caaa6627095e3326f7ecba84b43037869. See #4500 for background. --- include/pybind11/embed.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/include/pybind11/embed.h b/include/pybind11/embed.h index 8450d5358..5a175b134 100644 --- a/include/pybind11/embed.h +++ b/include/pybind11/embed.h @@ -254,16 +254,13 @@ inline void finalize_interpreter() { if (builtins.contains(id) && isinstance(builtins[id])) { internals_ptr_ptr = capsule(builtins[id]); } - - Py_Finalize(); - // Local internals contains data managed by the current interpreter, so we must clear them to // avoid undefined behaviors when initializing another interpreter - // Must be cleared only after Py_Finalize() so atexit and other hooks can still use - // registered_types detail::get_local_internals().registered_types_cpp.clear(); detail::get_local_internals().registered_exception_translators.clear(); + Py_Finalize(); + if (internals_ptr_ptr) { delete *internals_ptr_ptr; *internals_ptr_ptr = nullptr; From b8f28551cc3a98ea9fbfc15c05b513c8f2d23e84 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 7 Feb 2023 20:19:33 -0800 Subject: [PATCH 5/7] Go back to CMake 3.25.2 (#4496) --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8befccdbc..5d93d42b1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -83,6 +83,9 @@ jobs: - name: Update CMake uses: jwlawson/actions-setup-cmake@v1.13 + # TEMPORARILY pin version because 3.26.0-rc1 is failing under macOS: + with: + cmake-version: '3.25.2' - name: Cache wheels if: runner.os == 'macOS' @@ -1071,6 +1074,9 @@ jobs: - name: Update CMake uses: jwlawson/actions-setup-cmake@v1.13 + # TEMPORARILY pin version because 3.26.0-rc1 is failing under macOS: + with: + cmake-version: '3.25.2' - name: Run pip installs run: | From 531144dddc8abf05612523a83ff575f6834fd611 Mon Sep 17 00:00:00 2001 From: Mike Essenmacher <112431871+mikeessen@users.noreply.github.com> Date: Thu, 9 Feb 2023 13:11:01 -0500 Subject: [PATCH 6/7] Replace "whitelist" with "allowlist" (#4506) --- tests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9beb268ed..b1cb222b4 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -169,7 +169,7 @@ if(PYBIND11_TEST_OVERRIDE) # This allows the override to be done with extensions, preserving backwards compatibility. foreach(test_name ${TEST_FILES_NO_EXT}) if(NOT ${test_name} IN_LIST TEST_OVERRIDE_NO_EXT - )# If not in the whitelist, add to be filtered out. + )# If not in the allowlist, add to be filtered out. list(APPEND PYBIND11_TEST_FILTER ${test_name}) endif() endforeach() From 8dcced29ae4c7654c25bc50742a72556ee3ae36c Mon Sep 17 00:00:00 2001 From: Dustin Spicuzza Date: Fri, 10 Feb 2023 00:21:17 -0500 Subject: [PATCH 7/7] Always display python type information in cast errors (#4463) * Always display python type information in cast errors * Address comments * Update comment --- include/pybind11/cast.h | 33 ++++++++++++++++++-------------- include/pybind11/detail/common.h | 5 +++-- tests/test_callbacks.py | 14 ++++++++++++-- tests/test_exceptions.cpp | 5 +++++ tests/test_exceptions.py | 9 +++++++++ tests/test_pytypes.py | 2 +- 6 files changed, 49 insertions(+), 19 deletions(-) diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 3a4046027..9b013bc39 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -1017,11 +1017,14 @@ type_caster &load_type(type_caster &conv, const handle &ha "Internal error: type_caster should only be used for C++ types"); if (!conv.load(handle, true)) { #if !defined(PYBIND11_DETAILED_ERROR_MESSAGES) - throw cast_error("Unable to cast Python instance to C++ type (#define " - "PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for details)"); + throw cast_error( + "Unable to cast Python instance of type " + + str(type::handle_of(handle)).cast() + + " to C++ type '?' (#define " + "PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for details)"); #else throw cast_error("Unable to cast Python instance of type " - + (std::string) str(type::handle_of(handle)) + " to C++ type '" + + str(type::handle_of(handle)).cast() + " to C++ type '" + type_id() + "'"); #endif } @@ -1085,12 +1088,13 @@ detail::enable_if_t::value, T> move(object &&obj) { if (obj.ref_count() > 1) { #if !defined(PYBIND11_DETAILED_ERROR_MESSAGES) throw cast_error( - "Unable to cast Python instance to C++ rvalue: instance has multiple references" - " (#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for details)"); + "Unable to cast Python " + str(type::handle_of(obj)).cast() + + " instance to C++ rvalue: instance has multiple references" + " (#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for details)"); #else - throw cast_error("Unable to move from Python " + (std::string) str(type::handle_of(obj)) - + " instance to C++ " + type_id() - + " instance: instance has multiple references"); + throw cast_error("Unable to move from Python " + + str(type::handle_of(obj)).cast() + " instance to C++ " + + type_id() + " instance: instance has multiple references"); #endif } @@ -1195,9 +1199,10 @@ PYBIND11_NAMESPACE_END(detail) // The overloads could coexist, i.e. the #if is not strictly speaking needed, // but it is an easy minor optimization. #if !defined(PYBIND11_DETAILED_ERROR_MESSAGES) -inline cast_error cast_error_unable_to_convert_call_arg() { - return cast_error("Unable to convert call argument to Python object (#define " - "PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for details)"); +inline cast_error cast_error_unable_to_convert_call_arg(const std::string &name) { + return cast_error("Unable to convert call argument '" + name + + "' to Python object (#define " + "PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for details)"); } #else inline cast_error cast_error_unable_to_convert_call_arg(const std::string &name, @@ -1220,7 +1225,7 @@ tuple make_tuple(Args &&...args_) { for (size_t i = 0; i < args.size(); i++) { if (!args[i]) { #if !defined(PYBIND11_DETAILED_ERROR_MESSAGES) - throw cast_error_unable_to_convert_call_arg(); + throw cast_error_unable_to_convert_call_arg(std::to_string(i)); #else std::array argtypes{{type_id()...}}; throw cast_error_unable_to_convert_call_arg(std::to_string(i), argtypes[i]); @@ -1510,7 +1515,7 @@ private: detail::make_caster::cast(std::forward(x), policy, {})); if (!o) { #if !defined(PYBIND11_DETAILED_ERROR_MESSAGES) - throw cast_error_unable_to_convert_call_arg(); + throw cast_error_unable_to_convert_call_arg(std::to_string(args_list.size())); #else throw cast_error_unable_to_convert_call_arg(std::to_string(args_list.size()), type_id()); @@ -1542,7 +1547,7 @@ private: } if (!a.value) { #if !defined(PYBIND11_DETAILED_ERROR_MESSAGES) - throw cast_error_unable_to_convert_call_arg(); + throw cast_error_unable_to_convert_call_arg(a.name); #else throw cast_error_unable_to_convert_call_arg(a.name, a.type); #endif diff --git a/include/pybind11/detail/common.h b/include/pybind11/detail/common.h index 0fc81e053..1032293d2 100644 --- a/include/pybind11/detail/common.h +++ b/include/pybind11/detail/common.h @@ -1225,8 +1225,9 @@ constexpr #endif // Pybind offers detailed error messages by default for all builts that are debug (through the -// negation of ndebug). This can also be manually enabled by users, for any builds, through -// defining PYBIND11_DETAILED_ERROR_MESSAGES. +// negation of NDEBUG). This can also be manually enabled by users, for any builds, through +// defining PYBIND11_DETAILED_ERROR_MESSAGES. This information is primarily useful for those +// who are writing (as opposed to merely using) libraries that use pybind11. #if !defined(PYBIND11_DETAILED_ERROR_MESSAGES) && !defined(NDEBUG) # define PYBIND11_DETAILED_ERROR_MESSAGES #endif diff --git a/tests/test_callbacks.py b/tests/test_callbacks.py index 57b659988..4a652f53e 100644 --- a/tests/test_callbacks.py +++ b/tests/test_callbacks.py @@ -5,6 +5,7 @@ import pytest import env # noqa: F401 from pybind11_tests import callbacks as m +from pybind11_tests import detailed_error_messages_enabled def test_callbacks(): @@ -70,11 +71,20 @@ def test_keyword_args_and_generalized_unpacking(): with pytest.raises(RuntimeError) as excinfo: m.test_arg_conversion_error1(f) - assert "Unable to convert call argument" in str(excinfo.value) + assert str(excinfo.value) == "Unable to convert call argument " + ( + "'1' of type 'UnregisteredType' to Python object" + if detailed_error_messages_enabled + else "'1' to Python object (#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for details)" + ) with pytest.raises(RuntimeError) as excinfo: m.test_arg_conversion_error2(f) - assert "Unable to convert call argument" in str(excinfo.value) + assert str(excinfo.value) == "Unable to convert call argument " + ( + "'expected_name' of type 'UnregisteredType' to Python object" + if detailed_error_messages_enabled + else "'expected_name' to Python object " + "(#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for details)" + ) def test_lambda_closure_cleanup(): diff --git a/tests/test_exceptions.cpp b/tests/test_exceptions.cpp index f57e09506..854c7e6f7 100644 --- a/tests/test_exceptions.cpp +++ b/tests/test_exceptions.cpp @@ -339,4 +339,9 @@ TEST_SUBMODULE(exceptions, m) { } return py::str("UNEXPECTED"); }); + + m.def("test_fn_cast_int", [](const py::function &fn) { + // function returns None instead of int, should give a useful error message + fn().cast(); + }); } diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py index 0d2c80814..8bcefe3de 100644 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -381,3 +381,12 @@ def test_pypy_oserror_normalization(): # https://github.com/pybind/pybind11/issues/4075 what = m.test_pypy_oserror_normalization() assert "this_filename_must_not_exist" in what + + +def test_fn_cast_int_exception(): + with pytest.raises(RuntimeError) as excinfo: + m.test_fn_cast_int(lambda: None) + + assert str(excinfo.value).startswith( + "Unable to cast Python instance of type to C++ type" + ) diff --git a/tests/test_pytypes.py b/tests/test_pytypes.py index 8f9f2987e..a1a80a293 100644 --- a/tests/test_pytypes.py +++ b/tests/test_pytypes.py @@ -536,7 +536,7 @@ def test_print(capture): assert str(excinfo.value) == "Unable to convert call argument " + ( "'1' of type 'UnregisteredType' to Python object" if detailed_error_messages_enabled - else "to Python object (#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for details)" + else "'1' to Python object (#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for details)" )