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