mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-25 14:45:12 +00:00
Add check if str(handle)
correctly converted the object, and throw py::error_already_set if not (bis) (#2477)
* Add check if `str(handle)` correctly converted the object, and throw py::error_already_set if not * Fix tests on Python 3 * Apply @rwgk's fixes to cherry-picked commits from #2392
This commit is contained in:
parent
b47efd35fb
commit
fe9ee86ba8
@ -920,7 +920,7 @@ public:
|
||||
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 @@ private:
|
||||
/// 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
|
||||
|
@ -80,6 +80,7 @@ TEST_SUBMODULE(pytypes, m) {
|
||||
m.def("str_from_bytes", []() { return py::str(py::bytes("boo", 3)); });
|
||||
m.def("str_from_object", [](const py::object& obj) { return py::str(obj); });
|
||||
m.def("repr_from_object", [](const py::object& obj) { return py::repr(obj); });
|
||||
m.def("str_from_handle", [](py::handle h) { return py::str(h); });
|
||||
|
||||
m.def("str_format", []() {
|
||||
auto s1 = "{} + {} = {}"_s.format(1, 2, 3);
|
||||
|
@ -104,11 +104,23 @@ def test_str(doc):
|
||||
|
||||
assert m.str_from_object(A()) == "this is a str"
|
||||
assert m.repr_from_object(A()) == "this is a repr"
|
||||
assert m.str_from_handle(A()) == "this is a str"
|
||||
|
||||
s1, s2 = m.str_format()
|
||||
assert s1 == "1 + 2 = 3"
|
||||
assert s1 == s2
|
||||
|
||||
malformed_utf8 = b"\x80"
|
||||
assert m.str_from_object(malformed_utf8) is malformed_utf8 # To be fixed; see #2380
|
||||
if env.PY2:
|
||||
# with pytest.raises(UnicodeDecodeError):
|
||||
# m.str_from_object(malformed_utf8)
|
||||
with pytest.raises(UnicodeDecodeError):
|
||||
m.str_from_handle(malformed_utf8)
|
||||
else:
|
||||
# assert m.str_from_object(malformed_utf8) == "b'\\x80'"
|
||||
assert m.str_from_handle(malformed_utf8) == "b'\\x80'"
|
||||
|
||||
|
||||
def test_bytes(doc):
|
||||
assert m.bytes_from_string().decode() == "foo"
|
||||
|
Loading…
Reference in New Issue
Block a user