Skip to content

Commit c577f60

Browse files
committed
adding @jagerman's isinstance<str> specialization for Python 3 only
1 parent 2d823e0 commit c577f60

File tree

3 files changed

+26
-1
lines changed

3 files changed

+26
-1
lines changed

include/pybind11/pytypes.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,10 @@ class str : public object {
943943
};
944944
/// @} pytypes
945945

946+
#if PY_MAJOR_VERSION >= 3
947+
template <> inline bool isinstance<str>(handle obj) { return PyUnicode_Check(obj.ptr()); }
948+
#endif
949+
946950
inline namespace literals {
947951
/** \rst
948952
String literal version of `str`

tests/test_pytypes.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,4 +316,7 @@ TEST_SUBMODULE(pytypes, m) {
316316

317317
m.def("isinstance_str", [](py::object o) { return py::isinstance<py::str>(o); });
318318
m.def("isinstance_bytes", [](py::object o) { return py::isinstance<py::bytes>(o); });
319+
320+
m.def("pass_to_std_string", [](std::string s) { return s.size(); });
321+
m.def("pass_to_py_str", [](py::str s) { return py::len(s); });
319322
}

tests/test_pytypes.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,5 +289,23 @@ def test_isinstance_string_types():
289289
else:
290290
assert not isinstance(actual_bytes, str)
291291
assert isinstance(actual_unicode, str)
292-
assert m.isinstance_str(actual_bytes) # REALLY BAD for Python 3?
292+
assert not m.isinstance_str(actual_bytes) # REALLY BAD for Python 3?
293293
assert m.isinstance_str(actual_unicode)
294+
295+
296+
def test_pass_str_or_bytes_to_std_string():
297+
actual_bytes = b"bytes"
298+
actual_unicode = u"str"
299+
assert m.pass_to_std_string(actual_unicode) == 3
300+
assert m.pass_to_std_string(actual_bytes) == 5
301+
assert m.pass_to_py_str(actual_unicode) == 3
302+
if str is bytes: # Python 2
303+
m.pass_to_py_str(actual_bytes) == 5
304+
else:
305+
with pytest.raises(TypeError) as excinfo:
306+
m.pass_to_py_str(actual_bytes)
307+
assert str(excinfo.value) == """\
308+
pass_to_py_str(): incompatible function arguments. The following argument types are supported:
309+
1. (arg0: str) -> int
310+
311+
Invoked with: b'bytes'"""

0 commit comments

Comments
 (0)