summaryrefslogtreecommitdiff
path: root/ext/pybind11/tests/test_python_types.py
diff options
context:
space:
mode:
Diffstat (limited to 'ext/pybind11/tests/test_python_types.py')
-rw-r--r--ext/pybind11/tests/test_python_types.py135
1 files changed, 134 insertions, 1 deletions
diff --git a/ext/pybind11/tests/test_python_types.py b/ext/pybind11/tests/test_python_types.py
index 9fe1ef71e..7956c7cc6 100644
--- a/ext/pybind11/tests/test_python_types.py
+++ b/ext/pybind11/tests/test_python_types.py
@@ -1,8 +1,15 @@
+# Python < 3 needs this: coding=utf-8
import pytest
from pybind11_tests import ExamplePythonTypes, ConstructorStats, has_optional, has_exp_optional
+def test_repr():
+ # In Python 3.3+, repr() accesses __qualname__
+ assert "pybind11_type" in repr(type(ExamplePythonTypes))
+ assert "ExamplePythonTypes" in repr(ExamplePythonTypes)
+
+
def test_static():
ExamplePythonTypes.value = 15
assert ExamplePythonTypes.value == 15
@@ -132,8 +139,12 @@ def test_instance(capture):
assert cstats.alive() == 0
-def test_docs(doc):
+# PyPy does not seem to propagate the tp_docs field at the moment
+def test_class_docs(doc):
assert doc(ExamplePythonTypes) == "Example 2 documentation"
+
+
+def test_method_docs(doc):
assert doc(ExamplePythonTypes.get_dict) == """
get_dict(self: m.ExamplePythonTypes) -> dict
@@ -400,3 +411,125 @@ def test_implicit_casting():
'int_i1': 42, 'int_i2': 42, 'int_e': 43, 'int_p': 44
}
assert z['l'] == [3, 6, 9, 12, 15]
+
+
+def test_unicode_conversion():
+ """Tests unicode conversion and error reporting."""
+ import pybind11_tests
+ from pybind11_tests import (good_utf8_string, bad_utf8_string,
+ good_utf16_string, bad_utf16_string,
+ good_utf32_string, # bad_utf32_string,
+ good_wchar_string, # bad_wchar_string,
+ u8_Z, u8_eacute, u16_ibang, u32_mathbfA, wchar_heart)
+
+ assert good_utf8_string() == u"Say utf8β€½ πŸŽ‚ 𝐀"
+ assert good_utf16_string() == u"bβ€½πŸŽ‚π€z"
+ assert good_utf32_string() == u"aπ€πŸŽ‚β€½z"
+ assert good_wchar_string() == u"aβΈ˜π€z"
+
+ with pytest.raises(UnicodeDecodeError):
+ bad_utf8_string()
+
+ with pytest.raises(UnicodeDecodeError):
+ bad_utf16_string()
+
+ # These are provided only if they actually fail (they don't when 32-bit and under Python 2.7)
+ if hasattr(pybind11_tests, "bad_utf32_string"):
+ with pytest.raises(UnicodeDecodeError):
+ pybind11_tests.bad_utf32_string()
+ if hasattr(pybind11_tests, "bad_wchar_string"):
+ with pytest.raises(UnicodeDecodeError):
+ pybind11_tests.bad_wchar_string()
+
+ assert u8_Z() == 'Z'
+ assert u8_eacute() == u'Γ©'
+ assert u16_ibang() == u'β€½'
+ assert u32_mathbfA() == u'𝐀'
+ assert wchar_heart() == u'β™₯'
+
+
+def test_single_char_arguments():
+ """Tests failures for passing invalid inputs to char-accepting functions"""
+ from pybind11_tests import ord_char, ord_char16, ord_char32, ord_wchar, wchar_size
+
+ def toobig_message(r):
+ return "Character code point not in range({0:#x})".format(r)
+ toolong_message = "Expected a character, but multi-character string found"
+
+ assert ord_char(u'a') == 0x61 # simple ASCII
+ assert ord_char(u'Γ©') == 0xE9 # requires 2 bytes in utf-8, but can be stuffed in a char
+ with pytest.raises(ValueError) as excinfo:
+ assert ord_char(u'Δ€') == 0x100 # requires 2 bytes, doesn't fit in a char
+ assert str(excinfo.value) == toobig_message(0x100)
+ with pytest.raises(ValueError) as excinfo:
+ assert ord_char(u'ab')
+ assert str(excinfo.value) == toolong_message
+
+ assert ord_char16(u'a') == 0x61
+ assert ord_char16(u'Γ©') == 0xE9
+ assert ord_char16(u'Δ€') == 0x100
+ assert ord_char16(u'β€½') == 0x203d
+ assert ord_char16(u'β™₯') == 0x2665
+ with pytest.raises(ValueError) as excinfo:
+ assert ord_char16(u'πŸŽ‚') == 0x1F382 # requires surrogate pair
+ assert str(excinfo.value) == toobig_message(0x10000)
+ with pytest.raises(ValueError) as excinfo:
+ assert ord_char16(u'aa')
+ assert str(excinfo.value) == toolong_message
+
+ assert ord_char32(u'a') == 0x61
+ assert ord_char32(u'Γ©') == 0xE9
+ assert ord_char32(u'Δ€') == 0x100
+ assert ord_char32(u'β€½') == 0x203d
+ assert ord_char32(u'β™₯') == 0x2665
+ assert ord_char32(u'πŸŽ‚') == 0x1F382
+ with pytest.raises(ValueError) as excinfo:
+ assert ord_char32(u'aa')
+ assert str(excinfo.value) == toolong_message
+
+ assert ord_wchar(u'a') == 0x61
+ assert ord_wchar(u'Γ©') == 0xE9
+ assert ord_wchar(u'Δ€') == 0x100
+ assert ord_wchar(u'β€½') == 0x203d
+ assert ord_wchar(u'β™₯') == 0x2665
+ if wchar_size == 2:
+ with pytest.raises(ValueError) as excinfo:
+ assert ord_wchar(u'πŸŽ‚') == 0x1F382 # requires surrogate pair
+ assert str(excinfo.value) == toobig_message(0x10000)
+ else:
+ assert ord_wchar(u'πŸŽ‚') == 0x1F382
+ with pytest.raises(ValueError) as excinfo:
+ assert ord_wchar(u'aa')
+ assert str(excinfo.value) == toolong_message
+
+
+def test_builtins_cast_return_none():
+ """Casters produced with PYBIND11_TYPE_CASTER() should convert nullptr to None"""
+ import pybind11_tests as m
+
+ assert m.return_none_string() is None
+ assert m.return_none_char() is None
+ assert m.return_none_bool() is None
+ assert m.return_none_int() is None
+ assert m.return_none_float() is None
+
+
+def test_capsule_with_destructor(capture):
+ import pybind11_tests as m
+ with capture:
+ a = m.return_capsule_with_destructor()
+ del a
+ pytest.gc_collect()
+ assert capture.unordered == """
+ creating capsule
+ destructing capsule
+ """
+
+ with capture:
+ a = m.return_capsule_with_destructor_2()
+ del a
+ pytest.gc_collect()
+ assert capture.unordered == """
+ creating capsule
+ destructing capsule: 1234
+ """