From 173204639e5c555dadbf5465e8d8b9b0d6b736ae Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 10 Aug 2020 17:49:14 -0700 Subject: [PATCH] Adding tests specifically to exercise pybind11::str::raw_str. (#2366) These tests will also alert us to any behavior changes across Python and PyPy versions. Hardening tests in preparation for changing `pybind11::str` to only hold `PyUnicodeObject` (NOT also `bytes`). Note that this test exposes that `pybind11::str` can also hold `bytes`. --- tests/test_pytypes.cpp | 2 ++ tests/test_pytypes.py | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/tests/test_pytypes.cpp b/tests/test_pytypes.cpp index 9f7bc37dc..9dae6e7d6 100644 --- a/tests/test_pytypes.cpp +++ b/tests/test_pytypes.cpp @@ -237,6 +237,8 @@ TEST_SUBMODULE(pytypes, m) { ); }); + m.def("convert_to_pybind11_str", [](py::object o) { return py::str(o); }); + m.def("get_implicit_casting", []() { py::dict d; d["char*_i1"] = "abc"; diff --git a/tests/test_pytypes.py b/tests/test_pytypes.py index 4cfc707a3..1c7b1dd1f 100644 --- a/tests/test_pytypes.py +++ b/tests/test_pytypes.py @@ -220,6 +220,38 @@ def test_constructors(): assert noconv2[k] is expected[k] +def test_pybind11_str_raw_str(): + # specifically to exercise pybind11::str::raw_str + cvt = m.convert_to_pybind11_str + assert cvt(u"Str") == u"Str" + assert cvt(b'Bytes') == u"Bytes" if str is bytes else "b'Bytes'" + assert cvt(None) == u"None" + assert cvt(False) == u"False" + assert cvt(True) == u"True" + assert cvt(42) == u"42" + assert cvt(2**65) == u"36893488147419103232" + assert cvt(-1.50) == u"-1.5" + assert cvt(()) == u"()" + assert cvt((18,)) == u"(18,)" + assert cvt([]) == u"[]" + assert cvt([28]) == u"[28]" + assert cvt({}) == u"{}" + assert cvt({3: 4}) == u"{3: 4}" + assert cvt(set()) == u"set([])" if str is bytes else "set()" + assert cvt({3, 3}) == u"set([3])" if str is bytes else "{3}" + + valid_orig = u"DZ" + valid_utf8 = valid_orig.encode("utf-8") + valid_cvt = cvt(valid_utf8) + assert type(valid_cvt) == bytes # Probably surprising. + assert valid_cvt == b'\xc7\xb1' + + malformed_utf8 = b'\x80' + malformed_cvt = cvt(malformed_utf8) + assert type(malformed_cvt) == bytes # Probably surprising. + assert malformed_cvt == b'\x80' + + def test_implicit_casting(): """Tests implicit casting when assigning or appending to dicts and lists.""" z = m.get_implicit_casting()