Skip to content

Commit 77059f0

Browse files
committed
Make py::isinstance<py::str> less permissive
py::str's uses a permissive check function that allows both str (Py 3)/ unicode (Py 2), *and* bytes (Py 3)/str (Py 2) so that a `py::str` can be created from either, but this makes the default `isinstance` implementation overly permissive.
1 parent cbd16a8 commit 77059f0

File tree

3 files changed

+11
-0
lines changed

3 files changed

+11
-0
lines changed

include/pybind11/pytypes.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -895,6 +895,9 @@ class str : public object {
895895
};
896896
/// @} pytypes
897897

898+
// str::check_ is too permissive for `isinstance` (in particular it allows a `bytes` object)
899+
template <> inline bool isinstance<str>(handle obj) { return PyUnicode_Check(obj.ptr()); }
900+
898901
inline namespace literals {
899902
/** \rst
900903
String literal version of `str`

tests/test_pytypes.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,4 +269,7 @@ TEST_SUBMODULE(pytypes, m) {
269269
m.def("print_failure", []() { py::print(42, UnregisteredType()); });
270270

271271
m.def("hash_function", [](py::object obj) { return py::hash(obj); });
272+
273+
// test_str_isinstance
274+
m.def("is_str_instance", [](py::object o) { return py::isinstance<py::str>(o); });
272275
}

tests/test_pytypes.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,3 +238,8 @@ class Unhashable(object):
238238
assert m.hash_function(Hashable(42)) == 42
239239
with pytest.raises(TypeError):
240240
m.hash_function(Unhashable())
241+
242+
243+
def test_str_isinstance():
244+
assert m.is_str_instance(u"abc")
245+
assert not m.is_str_instance(b"abc")

0 commit comments

Comments
 (0)