test_pytypes.py revision 12391:ceeca8b41e4b
1import pytest 2import sys 3 4from pybind11_tests import pytypes as m 5from pybind11_tests import debug_enabled 6 7 8def test_list(capture, doc): 9 with capture: 10 l = m.get_list() 11 assert l == ["overwritten"] 12 13 l.append("value2") 14 m.print_list(l) 15 assert capture.unordered == """ 16 Entry at position 0: value 17 list item 0: overwritten 18 list item 1: value2 19 """ 20 21 assert doc(m.get_list) == "get_list() -> list" 22 assert doc(m.print_list) == "print_list(arg0: list) -> None" 23 24 25def test_set(capture, doc): 26 s = m.get_set() 27 assert s == {"key1", "key2", "key3"} 28 29 with capture: 30 s.add("key4") 31 m.print_set(s) 32 assert capture.unordered == """ 33 key: key1 34 key: key2 35 key: key3 36 key: key4 37 """ 38 39 assert doc(m.get_list) == "get_list() -> list" 40 assert doc(m.print_list) == "print_list(arg0: list) -> None" 41 42 43def test_dict(capture, doc): 44 d = m.get_dict() 45 assert d == {"key": "value"} 46 47 with capture: 48 d["key2"] = "value2" 49 m.print_dict(d) 50 assert capture.unordered == """ 51 key: key, value=value 52 key: key2, value=value2 53 """ 54 55 assert doc(m.get_dict) == "get_dict() -> dict" 56 assert doc(m.print_dict) == "print_dict(arg0: dict) -> None" 57 58 assert m.dict_keyword_constructor() == {"x": 1, "y": 2, "z": 3} 59 60 61def test_str(doc): 62 assert m.str_from_string().encode().decode() == "baz" 63 assert m.str_from_bytes().encode().decode() == "boo" 64 65 assert doc(m.str_from_bytes) == "str_from_bytes() -> str" 66 67 class A(object): 68 def __str__(self): 69 return "this is a str" 70 71 def __repr__(self): 72 return "this is a repr" 73 74 assert m.str_from_object(A()) == "this is a str" 75 assert m.repr_from_object(A()) == "this is a repr" 76 77 s1, s2 = m.str_format() 78 assert s1 == "1 + 2 = 3" 79 assert s1 == s2 80 81 82def test_bytes(doc): 83 assert m.bytes_from_string().decode() == "foo" 84 assert m.bytes_from_str().decode() == "bar" 85 86 assert doc(m.bytes_from_str) == "bytes_from_str() -> {}".format( 87 "bytes" if sys.version_info[0] == 3 else "str" 88 ) 89 90 91def test_capsule(capture): 92 pytest.gc_collect() 93 with capture: 94 a = m.return_capsule_with_destructor() 95 del a 96 pytest.gc_collect() 97 assert capture.unordered == """ 98 creating capsule 99 destructing capsule 100 """ 101 102 with capture: 103 a = m.return_capsule_with_destructor_2() 104 del a 105 pytest.gc_collect() 106 assert capture.unordered == """ 107 creating capsule 108 destructing capsule: 1234 109 """ 110 111 with capture: 112 a = m.return_capsule_with_name_and_destructor() 113 del a 114 pytest.gc_collect() 115 assert capture.unordered == """ 116 created capsule (1234, 'pointer type description') 117 destructing capsule (1234, 'pointer type description') 118 """ 119 120 121def test_accessors(): 122 class SubTestObject: 123 attr_obj = 1 124 attr_char = 2 125 126 class TestObject: 127 basic_attr = 1 128 begin_end = [1, 2, 3] 129 d = {"operator[object]": 1, "operator[char *]": 2} 130 sub = SubTestObject() 131 132 def func(self, x, *args): 133 return self.basic_attr + x + sum(args) 134 135 d = m.accessor_api(TestObject()) 136 assert d["basic_attr"] == 1 137 assert d["begin_end"] == [1, 2, 3] 138 assert d["operator[object]"] == 1 139 assert d["operator[char *]"] == 2 140 assert d["attr(object)"] == 1 141 assert d["attr(char *)"] == 2 142 assert d["missing_attr_ptr"] == "raised" 143 assert d["missing_attr_chain"] == "raised" 144 assert d["is_none"] is False 145 assert d["operator()"] == 2 146 assert d["operator*"] == 7 147 assert d["implicit_list"] == [1, 2, 3] 148 assert all(x in TestObject.__dict__ for x in d["implicit_dict"]) 149 150 assert m.tuple_accessor(tuple()) == (0, 1, 2) 151 152 d = m.accessor_assignment() 153 assert d["get"] == 0 154 assert d["deferred_get"] == 0 155 assert d["set"] == 1 156 assert d["deferred_set"] == 1 157 assert d["var"] == 99 158 159 160def test_constructors(): 161 """C++ default and converting constructors are equivalent to type calls in Python""" 162 types = [str, bool, int, float, tuple, list, dict, set] 163 expected = {t.__name__: t() for t in types} 164 assert m.default_constructors() == expected 165 166 data = { 167 str: 42, 168 bool: "Not empty", 169 int: "42", 170 float: "+1e3", 171 tuple: range(3), 172 list: range(3), 173 dict: [("two", 2), ("one", 1), ("three", 3)], 174 set: [4, 4, 5, 6, 6, 6], 175 memoryview: b'abc' 176 } 177 inputs = {k.__name__: v for k, v in data.items()} 178 expected = {k.__name__: k(v) for k, v in data.items()} 179 180 assert m.converting_constructors(inputs) == expected 181 assert m.cast_functions(inputs) == expected 182 183 # Converting constructors and cast functions should just reference rather 184 # than copy when no conversion is needed: 185 noconv1 = m.converting_constructors(expected) 186 for k in noconv1: 187 assert noconv1[k] is expected[k] 188 189 noconv2 = m.cast_functions(expected) 190 for k in noconv2: 191 assert noconv2[k] is expected[k] 192 193 194def test_implicit_casting(): 195 """Tests implicit casting when assigning or appending to dicts and lists.""" 196 z = m.get_implicit_casting() 197 assert z['d'] == { 198 'char*_i1': 'abc', 'char*_i2': 'abc', 'char*_e': 'abc', 'char*_p': 'abc', 199 'str_i1': 'str', 'str_i2': 'str1', 'str_e': 'str2', 'str_p': 'str3', 200 'int_i1': 42, 'int_i2': 42, 'int_e': 43, 'int_p': 44 201 } 202 assert z['l'] == [3, 6, 9, 12, 15] 203 204 205def test_print(capture): 206 with capture: 207 m.print_function() 208 assert capture == """ 209 Hello, World! 210 1 2.0 three True -- multiple args 211 *args-and-a-custom-separator 212 no new line here -- next print 213 flush 214 py::print + str.format = this 215 """ 216 assert capture.stderr == "this goes to stderr" 217 218 with pytest.raises(RuntimeError) as excinfo: 219 m.print_failure() 220 assert str(excinfo.value) == "make_tuple(): unable to convert " + ( 221 "argument of type 'UnregisteredType' to Python object" 222 if debug_enabled else 223 "arguments to Python object (compile in debug mode for details)" 224 ) 225 226 227def test_hash(): 228 class Hashable(object): 229 def __init__(self, value): 230 self.value = value 231 232 def __hash__(self): 233 return self.value 234 235 class Unhashable(object): 236 __hash__ = None 237 238 assert m.hash_function(Hashable(42)) == 42 239 with pytest.raises(TypeError): 240 m.hash_function(Unhashable()) 241