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
This commit is contained in:
Yannick Jadoul 2020-10-13 05:00:54 +02:00 committed by GitHub
parent 2f746eeeb4
commit 99773fc5f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 16 additions and 1 deletions

View File

@ -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);

View File

@ -407,4 +407,7 @@ TEST_SUBMODULE(pytypes, m) {
buf, static_cast<ssize_t>(strlen(buf)));
});
#endif
// test_builtin_functions
m.def("get_len", [](py::handle h) { return py::len(h); });
}

View File

@ -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