test_pytypes.py revision 14299
114299Sbbruce@ucdavis.edufrom __future__ import division 212391Sjason@lowepower.comimport pytest 312391Sjason@lowepower.comimport sys 412391Sjason@lowepower.com 512391Sjason@lowepower.comfrom pybind11_tests import pytypes as m 612391Sjason@lowepower.comfrom pybind11_tests import debug_enabled 712391Sjason@lowepower.com 812391Sjason@lowepower.com 912391Sjason@lowepower.comdef test_list(capture, doc): 1012391Sjason@lowepower.com with capture: 1114299Sbbruce@ucdavis.edu lst = m.get_list() 1214299Sbbruce@ucdavis.edu assert lst == ["inserted-0", "overwritten", "inserted-2"] 1312391Sjason@lowepower.com 1414299Sbbruce@ucdavis.edu lst.append("value2") 1514299Sbbruce@ucdavis.edu m.print_list(lst) 1612391Sjason@lowepower.com assert capture.unordered == """ 1712391Sjason@lowepower.com Entry at position 0: value 1814299Sbbruce@ucdavis.edu list item 0: inserted-0 1914299Sbbruce@ucdavis.edu list item 1: overwritten 2014299Sbbruce@ucdavis.edu list item 2: inserted-2 2114299Sbbruce@ucdavis.edu list item 3: value2 2212391Sjason@lowepower.com """ 2312391Sjason@lowepower.com 2412391Sjason@lowepower.com assert doc(m.get_list) == "get_list() -> list" 2512391Sjason@lowepower.com assert doc(m.print_list) == "print_list(arg0: list) -> None" 2612391Sjason@lowepower.com 2712391Sjason@lowepower.com 2812391Sjason@lowepower.comdef test_set(capture, doc): 2912391Sjason@lowepower.com s = m.get_set() 3012391Sjason@lowepower.com assert s == {"key1", "key2", "key3"} 3112391Sjason@lowepower.com 3212391Sjason@lowepower.com with capture: 3312391Sjason@lowepower.com s.add("key4") 3412391Sjason@lowepower.com m.print_set(s) 3512391Sjason@lowepower.com assert capture.unordered == """ 3612391Sjason@lowepower.com key: key1 3712391Sjason@lowepower.com key: key2 3812391Sjason@lowepower.com key: key3 3912391Sjason@lowepower.com key: key4 4012391Sjason@lowepower.com """ 4112391Sjason@lowepower.com 4214299Sbbruce@ucdavis.edu assert not m.set_contains(set([]), 42) 4314299Sbbruce@ucdavis.edu assert m.set_contains({42}, 42) 4414299Sbbruce@ucdavis.edu assert m.set_contains({"foo"}, "foo") 4514299Sbbruce@ucdavis.edu 4612391Sjason@lowepower.com assert doc(m.get_list) == "get_list() -> list" 4712391Sjason@lowepower.com assert doc(m.print_list) == "print_list(arg0: list) -> None" 4812391Sjason@lowepower.com 4912391Sjason@lowepower.com 5012391Sjason@lowepower.comdef test_dict(capture, doc): 5112391Sjason@lowepower.com d = m.get_dict() 5212391Sjason@lowepower.com assert d == {"key": "value"} 5312391Sjason@lowepower.com 5412391Sjason@lowepower.com with capture: 5512391Sjason@lowepower.com d["key2"] = "value2" 5612391Sjason@lowepower.com m.print_dict(d) 5712391Sjason@lowepower.com assert capture.unordered == """ 5812391Sjason@lowepower.com key: key, value=value 5912391Sjason@lowepower.com key: key2, value=value2 6012391Sjason@lowepower.com """ 6112391Sjason@lowepower.com 6214299Sbbruce@ucdavis.edu assert not m.dict_contains({}, 42) 6314299Sbbruce@ucdavis.edu assert m.dict_contains({42: None}, 42) 6414299Sbbruce@ucdavis.edu assert m.dict_contains({"foo": None}, "foo") 6514299Sbbruce@ucdavis.edu 6612391Sjason@lowepower.com assert doc(m.get_dict) == "get_dict() -> dict" 6712391Sjason@lowepower.com assert doc(m.print_dict) == "print_dict(arg0: dict) -> None" 6812391Sjason@lowepower.com 6912391Sjason@lowepower.com assert m.dict_keyword_constructor() == {"x": 1, "y": 2, "z": 3} 7012391Sjason@lowepower.com 7112391Sjason@lowepower.com 7212391Sjason@lowepower.comdef test_str(doc): 7312391Sjason@lowepower.com assert m.str_from_string().encode().decode() == "baz" 7412391Sjason@lowepower.com assert m.str_from_bytes().encode().decode() == "boo" 7512391Sjason@lowepower.com 7612391Sjason@lowepower.com assert doc(m.str_from_bytes) == "str_from_bytes() -> str" 7712391Sjason@lowepower.com 7812391Sjason@lowepower.com class A(object): 7912391Sjason@lowepower.com def __str__(self): 8012391Sjason@lowepower.com return "this is a str" 8112391Sjason@lowepower.com 8212391Sjason@lowepower.com def __repr__(self): 8312391Sjason@lowepower.com return "this is a repr" 8412391Sjason@lowepower.com 8512391Sjason@lowepower.com assert m.str_from_object(A()) == "this is a str" 8612391Sjason@lowepower.com assert m.repr_from_object(A()) == "this is a repr" 8712391Sjason@lowepower.com 8812391Sjason@lowepower.com s1, s2 = m.str_format() 8912391Sjason@lowepower.com assert s1 == "1 + 2 = 3" 9012391Sjason@lowepower.com assert s1 == s2 9112391Sjason@lowepower.com 9212391Sjason@lowepower.com 9312391Sjason@lowepower.comdef test_bytes(doc): 9412391Sjason@lowepower.com assert m.bytes_from_string().decode() == "foo" 9512391Sjason@lowepower.com assert m.bytes_from_str().decode() == "bar" 9612391Sjason@lowepower.com 9712391Sjason@lowepower.com assert doc(m.bytes_from_str) == "bytes_from_str() -> {}".format( 9812391Sjason@lowepower.com "bytes" if sys.version_info[0] == 3 else "str" 9912391Sjason@lowepower.com ) 10012391Sjason@lowepower.com 10112391Sjason@lowepower.com 10212391Sjason@lowepower.comdef test_capsule(capture): 10312391Sjason@lowepower.com pytest.gc_collect() 10412391Sjason@lowepower.com with capture: 10512391Sjason@lowepower.com a = m.return_capsule_with_destructor() 10612391Sjason@lowepower.com del a 10712391Sjason@lowepower.com pytest.gc_collect() 10812391Sjason@lowepower.com assert capture.unordered == """ 10912391Sjason@lowepower.com creating capsule 11012391Sjason@lowepower.com destructing capsule 11112391Sjason@lowepower.com """ 11212391Sjason@lowepower.com 11312391Sjason@lowepower.com with capture: 11412391Sjason@lowepower.com a = m.return_capsule_with_destructor_2() 11512391Sjason@lowepower.com del a 11612391Sjason@lowepower.com pytest.gc_collect() 11712391Sjason@lowepower.com assert capture.unordered == """ 11812391Sjason@lowepower.com creating capsule 11912391Sjason@lowepower.com destructing capsule: 1234 12012391Sjason@lowepower.com """ 12112391Sjason@lowepower.com 12212391Sjason@lowepower.com with capture: 12312391Sjason@lowepower.com a = m.return_capsule_with_name_and_destructor() 12412391Sjason@lowepower.com del a 12512391Sjason@lowepower.com pytest.gc_collect() 12612391Sjason@lowepower.com assert capture.unordered == """ 12712391Sjason@lowepower.com created capsule (1234, 'pointer type description') 12812391Sjason@lowepower.com destructing capsule (1234, 'pointer type description') 12912391Sjason@lowepower.com """ 13012391Sjason@lowepower.com 13112391Sjason@lowepower.com 13212391Sjason@lowepower.comdef test_accessors(): 13312391Sjason@lowepower.com class SubTestObject: 13412391Sjason@lowepower.com attr_obj = 1 13512391Sjason@lowepower.com attr_char = 2 13612391Sjason@lowepower.com 13712391Sjason@lowepower.com class TestObject: 13812391Sjason@lowepower.com basic_attr = 1 13912391Sjason@lowepower.com begin_end = [1, 2, 3] 14012391Sjason@lowepower.com d = {"operator[object]": 1, "operator[char *]": 2} 14112391Sjason@lowepower.com sub = SubTestObject() 14212391Sjason@lowepower.com 14312391Sjason@lowepower.com def func(self, x, *args): 14412391Sjason@lowepower.com return self.basic_attr + x + sum(args) 14512391Sjason@lowepower.com 14612391Sjason@lowepower.com d = m.accessor_api(TestObject()) 14712391Sjason@lowepower.com assert d["basic_attr"] == 1 14812391Sjason@lowepower.com assert d["begin_end"] == [1, 2, 3] 14912391Sjason@lowepower.com assert d["operator[object]"] == 1 15012391Sjason@lowepower.com assert d["operator[char *]"] == 2 15112391Sjason@lowepower.com assert d["attr(object)"] == 1 15212391Sjason@lowepower.com assert d["attr(char *)"] == 2 15312391Sjason@lowepower.com assert d["missing_attr_ptr"] == "raised" 15412391Sjason@lowepower.com assert d["missing_attr_chain"] == "raised" 15512391Sjason@lowepower.com assert d["is_none"] is False 15612391Sjason@lowepower.com assert d["operator()"] == 2 15712391Sjason@lowepower.com assert d["operator*"] == 7 15812391Sjason@lowepower.com assert d["implicit_list"] == [1, 2, 3] 15912391Sjason@lowepower.com assert all(x in TestObject.__dict__ for x in d["implicit_dict"]) 16012391Sjason@lowepower.com 16112391Sjason@lowepower.com assert m.tuple_accessor(tuple()) == (0, 1, 2) 16212391Sjason@lowepower.com 16312391Sjason@lowepower.com d = m.accessor_assignment() 16412391Sjason@lowepower.com assert d["get"] == 0 16512391Sjason@lowepower.com assert d["deferred_get"] == 0 16612391Sjason@lowepower.com assert d["set"] == 1 16712391Sjason@lowepower.com assert d["deferred_set"] == 1 16812391Sjason@lowepower.com assert d["var"] == 99 16912391Sjason@lowepower.com 17012391Sjason@lowepower.com 17112391Sjason@lowepower.comdef test_constructors(): 17212391Sjason@lowepower.com """C++ default and converting constructors are equivalent to type calls in Python""" 17312391Sjason@lowepower.com types = [str, bool, int, float, tuple, list, dict, set] 17412391Sjason@lowepower.com expected = {t.__name__: t() for t in types} 17512391Sjason@lowepower.com assert m.default_constructors() == expected 17612391Sjason@lowepower.com 17712391Sjason@lowepower.com data = { 17812391Sjason@lowepower.com str: 42, 17912391Sjason@lowepower.com bool: "Not empty", 18012391Sjason@lowepower.com int: "42", 18112391Sjason@lowepower.com float: "+1e3", 18212391Sjason@lowepower.com tuple: range(3), 18312391Sjason@lowepower.com list: range(3), 18412391Sjason@lowepower.com dict: [("two", 2), ("one", 1), ("three", 3)], 18512391Sjason@lowepower.com set: [4, 4, 5, 6, 6, 6], 18612391Sjason@lowepower.com memoryview: b'abc' 18712391Sjason@lowepower.com } 18812391Sjason@lowepower.com inputs = {k.__name__: v for k, v in data.items()} 18912391Sjason@lowepower.com expected = {k.__name__: k(v) for k, v in data.items()} 19012391Sjason@lowepower.com 19112391Sjason@lowepower.com assert m.converting_constructors(inputs) == expected 19212391Sjason@lowepower.com assert m.cast_functions(inputs) == expected 19312391Sjason@lowepower.com 19412391Sjason@lowepower.com # Converting constructors and cast functions should just reference rather 19512391Sjason@lowepower.com # than copy when no conversion is needed: 19612391Sjason@lowepower.com noconv1 = m.converting_constructors(expected) 19712391Sjason@lowepower.com for k in noconv1: 19812391Sjason@lowepower.com assert noconv1[k] is expected[k] 19912391Sjason@lowepower.com 20012391Sjason@lowepower.com noconv2 = m.cast_functions(expected) 20112391Sjason@lowepower.com for k in noconv2: 20212391Sjason@lowepower.com assert noconv2[k] is expected[k] 20312391Sjason@lowepower.com 20412391Sjason@lowepower.com 20512391Sjason@lowepower.comdef test_implicit_casting(): 20612391Sjason@lowepower.com """Tests implicit casting when assigning or appending to dicts and lists.""" 20712391Sjason@lowepower.com z = m.get_implicit_casting() 20812391Sjason@lowepower.com assert z['d'] == { 20912391Sjason@lowepower.com 'char*_i1': 'abc', 'char*_i2': 'abc', 'char*_e': 'abc', 'char*_p': 'abc', 21012391Sjason@lowepower.com 'str_i1': 'str', 'str_i2': 'str1', 'str_e': 'str2', 'str_p': 'str3', 21112391Sjason@lowepower.com 'int_i1': 42, 'int_i2': 42, 'int_e': 43, 'int_p': 44 21212391Sjason@lowepower.com } 21312391Sjason@lowepower.com assert z['l'] == [3, 6, 9, 12, 15] 21412391Sjason@lowepower.com 21512391Sjason@lowepower.com 21612391Sjason@lowepower.comdef test_print(capture): 21712391Sjason@lowepower.com with capture: 21812391Sjason@lowepower.com m.print_function() 21912391Sjason@lowepower.com assert capture == """ 22012391Sjason@lowepower.com Hello, World! 22112391Sjason@lowepower.com 1 2.0 three True -- multiple args 22212391Sjason@lowepower.com *args-and-a-custom-separator 22312391Sjason@lowepower.com no new line here -- next print 22412391Sjason@lowepower.com flush 22512391Sjason@lowepower.com py::print + str.format = this 22612391Sjason@lowepower.com """ 22712391Sjason@lowepower.com assert capture.stderr == "this goes to stderr" 22812391Sjason@lowepower.com 22912391Sjason@lowepower.com with pytest.raises(RuntimeError) as excinfo: 23012391Sjason@lowepower.com m.print_failure() 23112391Sjason@lowepower.com assert str(excinfo.value) == "make_tuple(): unable to convert " + ( 23212391Sjason@lowepower.com "argument of type 'UnregisteredType' to Python object" 23312391Sjason@lowepower.com if debug_enabled else 23412391Sjason@lowepower.com "arguments to Python object (compile in debug mode for details)" 23512391Sjason@lowepower.com ) 23612391Sjason@lowepower.com 23712391Sjason@lowepower.com 23812391Sjason@lowepower.comdef test_hash(): 23912391Sjason@lowepower.com class Hashable(object): 24012391Sjason@lowepower.com def __init__(self, value): 24112391Sjason@lowepower.com self.value = value 24212391Sjason@lowepower.com 24312391Sjason@lowepower.com def __hash__(self): 24412391Sjason@lowepower.com return self.value 24512391Sjason@lowepower.com 24612391Sjason@lowepower.com class Unhashable(object): 24712391Sjason@lowepower.com __hash__ = None 24812391Sjason@lowepower.com 24912391Sjason@lowepower.com assert m.hash_function(Hashable(42)) == 42 25012391Sjason@lowepower.com with pytest.raises(TypeError): 25112391Sjason@lowepower.com m.hash_function(Unhashable()) 25214299Sbbruce@ucdavis.edu 25314299Sbbruce@ucdavis.edu 25414299Sbbruce@ucdavis.edudef test_number_protocol(): 25514299Sbbruce@ucdavis.edu for a, b in [(1, 1), (3, 5)]: 25614299Sbbruce@ucdavis.edu li = [a == b, a != b, a < b, a <= b, a > b, a >= b, a + b, 25714299Sbbruce@ucdavis.edu a - b, a * b, a / b, a | b, a & b, a ^ b, a >> b, a << b] 25814299Sbbruce@ucdavis.edu assert m.test_number_protocol(a, b) == li 25914299Sbbruce@ucdavis.edu 26014299Sbbruce@ucdavis.edu 26114299Sbbruce@ucdavis.edudef test_list_slicing(): 26214299Sbbruce@ucdavis.edu li = list(range(100)) 26314299Sbbruce@ucdavis.edu assert li[::2] == m.test_list_slicing(li) 264