From d629d5e7cc31dc99bd44ead41a85a344461960c0 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 8 Sep 2020 08:53:17 -0700 Subject: [PATCH] Adds check if `str(handle)` correctly converted the object, and throw py::error_already_set if not. Similar to #2392, but does not depend on #2409. Splitting out this PR from #2409 to make that PR as simple as possible. Net effects of this PR: * Adds missing test coverage. * Changes TypeError to UnicodeDecodeError for Python 2. This PR has two commits. Please do not squash, to make the behavior change obvious in the commit history. --- include/pybind11/pytypes.h | 4 ++-- tests/test_pytypes.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/pybind11/pytypes.h b/include/pybind11/pytypes.h index bea34cd936..00c791aada 100644 --- a/include/pybind11/pytypes.h +++ b/include/pybind11/pytypes.h @@ -920,7 +920,7 @@ class str : public object { Return a string representation of the object. This is analogous to the ``str()`` function in Python. \endrst */ - explicit str(handle h) : object(raw_str(h.ptr()), stolen_t{}) { } + explicit str(handle h) : object(raw_str(h.ptr()), stolen_t{}) { if (!m_ptr) throw error_already_set(); } operator std::string() const { object temp = *this; @@ -945,8 +945,8 @@ class str : public object { /// Return string representation -- always returns a new reference, even if already a str static PyObject *raw_str(PyObject *op) { PyObject *str_value = PyObject_Str(op); - if (!str_value) throw error_already_set(); #if PY_MAJOR_VERSION < 3 + if (!str_value) throw error_already_set(); PyObject *unicode = PyUnicode_FromEncodedObject(str_value, "utf-8", nullptr); Py_XDECREF(str_value); str_value = unicode; #endif diff --git a/tests/test_pytypes.py b/tests/test_pytypes.py index 85739dc87f..33a03c66ca 100644 --- a/tests/test_pytypes.py +++ b/tests/test_pytypes.py @@ -114,7 +114,7 @@ def __repr__(self): malformed_utf8 = b"\x80" assert m.str_from_object(malformed_utf8) is malformed_utf8 # Probably surprising. if env.PY2: - with pytest.raises(TypeError): + with pytest.raises(UnicodeDecodeError): m.str_from_handle(malformed_utf8) else: assert m.str_from_handle(malformed_utf8) == "b'\\x80'"