From 99773fc5f6b148900a8b5e61a4a683a17052261d Mon Sep 17 00:00:00 2001 From: Yannick Jadoul Date: Tue, 13 Oct 2020 05:00:54 +0200 Subject: [PATCH] fix: throw error_already_set in py::len on failing PyObject_Length (#2575) * Throw error_already_set in py::len on failing PyObject_Length * Fix tests to mach error message on PyPy --- include/pybind11/pytypes.h | 6 +++++- tests/test_pytypes.cpp | 3 +++ tests/test_pytypes.py | 8 ++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/include/pybind11/pytypes.h b/include/pybind11/pytypes.h index 30d7f9ae..1010ad71 100644 --- a/include/pybind11/pytypes.h +++ b/include/pybind11/pytypes.h @@ -1530,13 +1530,17 @@ inline memoryview memoryview::from_buffer( /// \addtogroup python_builtins /// @{ + +/// Get the length of a Python object. inline size_t len(handle h) { ssize_t result = PyObject_Length(h.ptr()); if (result < 0) - pybind11_fail("Unable to compute length of object"); + throw error_already_set(); return (size_t) result; } +/// Get the length hint of a Python object. +/// Returns 0 when this cannot be determined. inline size_t len_hint(handle h) { #if PY_VERSION_HEX >= 0x03040000 ssize_t result = PyObject_LengthHint(h.ptr(), 0); diff --git a/tests/test_pytypes.cpp b/tests/test_pytypes.cpp index 45fd8718..ceaac365 100644 --- a/tests/test_pytypes.cpp +++ b/tests/test_pytypes.cpp @@ -407,4 +407,7 @@ TEST_SUBMODULE(pytypes, m) { buf, static_cast(strlen(buf))); }); #endif + + // test_builtin_functions + m.def("get_len", [](py::handle h) { return py::len(h); }); } diff --git a/tests/test_pytypes.py b/tests/test_pytypes.py index ab51b551..403c4da4 100644 --- a/tests/test_pytypes.py +++ b/tests/test_pytypes.py @@ -424,3 +424,11 @@ def test_memoryview_from_memory(): assert isinstance(view, memoryview) assert view.format == 'B' assert bytes(view) == b'\xff\xe1\xab\x37' + + +def test_builtin_functions(): + assert m.get_len([i for i in range(42)]) == 42 + with pytest.raises(TypeError) as exc_info: + m.get_len(i for i in range(42)) + assert str(exc_info.value) in ["object of type 'generator' has no len()", + "'generator' has no length"] # PyPy