@@ -104,11 +104,28 @@ def __repr__(self):
104104
105105 assert m .str_from_object (A ()) == "this is a str"
106106 assert m .repr_from_object (A ()) == "this is a repr"
107+ assert m .str_from_handle (A ()) == "this is a str"
107108
108109 s1 , s2 = m .str_format ()
109110 assert s1 == "1 + 2 = 3"
110111 assert s1 == s2
111112
113+ malformed_utf8 = b"\x80 "
114+ if env .PY2 :
115+ if hasattr (m , "has_str_non_permissive" ):
116+ with pytest .raises (UnicodeDecodeError ):
117+ m .str_from_object (malformed_utf8 )
118+ else :
119+ m .str_from_object (malformed_utf8 ) is malformed_utf8
120+ with pytest .raises (UnicodeDecodeError ):
121+ m .str_from_handle (malformed_utf8 )
122+ else :
123+ if hasattr (m , "has_str_non_permissive" ):
124+ assert m .str_from_object (malformed_utf8 ) == "b'\\ x80'"
125+ else :
126+ assert m .str_from_object (malformed_utf8 ) is malformed_utf8
127+ assert m .str_from_handle (malformed_utf8 ) == "b'\\ x80'"
128+
112129
113130def test_bytes (doc ):
114131 assert m .bytes_from_string ().decode () == "foo"
@@ -190,11 +207,17 @@ def func(self, x, *args):
190207
191208def test_constructors ():
192209 """C++ default and converting constructors are equivalent to type calls in Python"""
193- types = [str , bool , int , float , tuple , list , dict , set ]
210+ types = [bytes , str , bool , int , float , tuple , list , dict , set ]
194211 expected = {t .__name__ : t () for t in types }
212+ if env .PY2 :
213+ # Note that bytes.__name__ == 'str' in Python 2.
214+ # pybind11::str is unicode even under Python 2.
215+ expected ["bytes" ] = bytes ()
216+ expected ["str" ] = u"" # flake8 complains about unicode().
195217 assert m .default_constructors () == expected
196218
197219 data = {
220+ bytes : b'41' , # Currently no supported or working conversions.
198221 str : 42 ,
199222 bool : "Not empty" ,
200223 int : "42" ,
@@ -207,6 +230,11 @@ def test_constructors():
207230 }
208231 inputs = {k .__name__ : v for k , v in data .items ()}
209232 expected = {k .__name__ : k (v ) for k , v in data .items ()}
233+ if env .PY2 : # Similar to the above. See comments above.
234+ inputs ["bytes" ] = b'41'
235+ inputs ["str" ] = 42
236+ expected ["bytes" ] = b'41'
237+ expected ["str" ] = u"42"
210238
211239 assert m .converting_constructors (inputs ) == expected
212240 assert m .cast_functions (inputs ) == expected
@@ -245,13 +273,26 @@ def test_pybind11_str_raw_str():
245273 valid_orig = u"DZ"
246274 valid_utf8 = valid_orig .encode ("utf-8" )
247275 valid_cvt = cvt (valid_utf8 )
248- assert type (valid_cvt ) == bytes # Probably surprising.
249- assert valid_cvt == b'\xc7 \xb1 '
276+ if hasattr (m , "has_str_non_permissive" ):
277+ assert type (valid_cvt ) is unicode if env .PY2 else str # noqa: F821
278+ if env .PY2 :
279+ assert valid_cvt == valid_orig
280+ else :
281+ assert valid_cvt == u"b'\\ xc7\\ xb1'"
282+ else :
283+ assert valid_cvt is valid_utf8
250284
251285 malformed_utf8 = b'\x80 '
252- malformed_cvt = cvt (malformed_utf8 )
253- assert type (malformed_cvt ) == bytes # Probably surprising.
254- assert malformed_cvt == b'\x80 '
286+ if hasattr (m , "has_str_non_permissive" ):
287+ if env .PY2 :
288+ with pytest .raises (UnicodeDecodeError ):
289+ cvt (malformed_utf8 )
290+ else :
291+ malformed_cvt = cvt (malformed_utf8 )
292+ assert type (malformed_cvt ) is unicode if env .PY2 else str # noqa: F821
293+ assert malformed_cvt == u"b'\\ x80'"
294+ else :
295+ assert cvt (malformed_utf8 ) is malformed_utf8
255296
256297
257298def test_implicit_casting ():
@@ -379,3 +420,41 @@ def test_memoryview_from_memory():
379420 assert isinstance (view , memoryview )
380421 assert view .format == 'B'
381422 assert bytes (view ) == b'\xff \xe1 \xab \x37 '
423+
424+
425+ def test_isinstance_string_types ():
426+ assert m .isinstance_pybind11_bytes (b"" )
427+ assert not m .isinstance_pybind11_bytes (u"" )
428+
429+ assert m .isinstance_pybind11_str (u"" )
430+ if hasattr (m , "has_str_non_permissive" ):
431+ assert not m .isinstance_pybind11_str (b"" )
432+ else :
433+ assert m .isinstance_pybind11_str (b"" )
434+
435+
436+ def test_pass_bytes_or_unicode_to_string_types ():
437+ assert m .pass_to_pybind11_bytes (b"Bytes" ) == 5
438+ with pytest .raises (TypeError ):
439+ m .pass_to_pybind11_bytes (u"Str" )
440+
441+ if hasattr (m , "has_str_caster_no_implicit_decode" ):
442+ with pytest .raises (TypeError ):
443+ m .pass_to_pybind11_str (b"Bytes" )
444+ else :
445+ assert m .pass_to_pybind11_str (b"Bytes" ) == 5
446+ assert m .pass_to_pybind11_str (u"Str" ) == 3
447+
448+ assert m .pass_to_std_string (b"Bytes" ) == 5
449+ assert m .pass_to_std_string (u"Str" ) == 3
450+
451+ malformed_utf8 = b"\x80 "
452+ if hasattr (m , "has_str_non_permissive" ):
453+ if hasattr (m , "has_str_caster_no_implicit_decode" ):
454+ with pytest .raises (TypeError ):
455+ m .pass_to_pybind11_str (malformed_utf8 )
456+ else :
457+ with pytest .raises (UnicodeDecodeError ):
458+ m .pass_to_pybind11_str (malformed_utf8 )
459+ else :
460+ assert m .pass_to_pybind11_str (malformed_utf8 ) == 1
0 commit comments