test_callbacks.py revision 11986
1import pytest 2 3 4def test_callbacks(): 5 from functools import partial 6 from pybind11_tests import (test_callback1, test_callback2, test_callback3, 7 test_callback4, test_callback5) 8 9 def func1(): 10 return "func1" 11 12 def func2(a, b, c, d): 13 return "func2", a, b, c, d 14 15 def func3(a): 16 return "func3({})".format(a) 17 18 assert test_callback1(func1) == "func1" 19 assert test_callback2(func2) == ("func2", "Hello", "x", True, 5) 20 assert test_callback1(partial(func2, 1, 2, 3, 4)) == ("func2", 1, 2, 3, 4) 21 assert test_callback1(partial(func3, "partial")) == "func3(partial)" 22 assert test_callback3(lambda i: i + 1) == "func(43) = 44" 23 24 f = test_callback4() 25 assert f(43) == 44 26 f = test_callback5() 27 assert f(number=43) == 44 28 29 30def test_keyword_args_and_generalized_unpacking(): 31 from pybind11_tests import (test_tuple_unpacking, test_dict_unpacking, test_keyword_args, 32 test_unpacking_and_keywords1, test_unpacking_and_keywords2, 33 test_unpacking_error1, test_unpacking_error2, 34 test_arg_conversion_error1, test_arg_conversion_error2) 35 36 def f(*args, **kwargs): 37 return args, kwargs 38 39 assert test_tuple_unpacking(f) == (("positional", 1, 2, 3, 4, 5, 6), {}) 40 assert test_dict_unpacking(f) == (("positional", 1), {"key": "value", "a": 1, "b": 2}) 41 assert test_keyword_args(f) == ((), {"x": 10, "y": 20}) 42 assert test_unpacking_and_keywords1(f) == ((1, 2), {"c": 3, "d": 4}) 43 assert test_unpacking_and_keywords2(f) == ( 44 ("positional", 1, 2, 3, 4, 5), 45 {"key": "value", "a": 1, "b": 2, "c": 3, "d": 4, "e": 5} 46 ) 47 48 with pytest.raises(TypeError) as excinfo: 49 test_unpacking_error1(f) 50 assert "Got multiple values for keyword argument" in str(excinfo.value) 51 52 with pytest.raises(TypeError) as excinfo: 53 test_unpacking_error2(f) 54 assert "Got multiple values for keyword argument" in str(excinfo.value) 55 56 with pytest.raises(RuntimeError) as excinfo: 57 test_arg_conversion_error1(f) 58 assert "Unable to convert call argument" in str(excinfo.value) 59 60 with pytest.raises(RuntimeError) as excinfo: 61 test_arg_conversion_error2(f) 62 assert "Unable to convert call argument" in str(excinfo.value) 63 64 65def test_lambda_closure_cleanup(): 66 from pybind11_tests import test_cleanup, payload_cstats 67 68 test_cleanup() 69 cstats = payload_cstats() 70 assert cstats.alive() == 0 71 assert cstats.copy_constructions == 1 72 assert cstats.move_constructions >= 1 73 74 75def test_cpp_function_roundtrip(): 76 """Test if passing a function pointer from C++ -> Python -> C++ yields the original pointer""" 77 from pybind11_tests import dummy_function, dummy_function2, test_dummy_function, roundtrip 78 79 assert test_dummy_function(dummy_function) == "matches dummy_function: eval(1) = 2" 80 assert test_dummy_function(roundtrip(dummy_function)) == "matches dummy_function: eval(1) = 2" 81 assert roundtrip(None, expect_none=True) is None 82 assert test_dummy_function(lambda x: x + 2) == "can't convert to function pointer: eval(1) = 3" 83 84 with pytest.raises(TypeError) as excinfo: 85 test_dummy_function(dummy_function2) 86 assert "incompatible function arguments" in str(excinfo.value) 87 88 with pytest.raises(TypeError) as excinfo: 89 test_dummy_function(lambda x, y: x + y) 90 assert any(s in str(excinfo.value) for s in ("missing 1 required positional argument", 91 "takes exactly 2 arguments")) 92 93 94def test_function_signatures(doc): 95 from pybind11_tests import test_callback3, test_callback4 96 97 assert doc(test_callback3) == "test_callback3(arg0: Callable[[int], int]) -> str" 98 assert doc(test_callback4) == "test_callback4() -> Callable[[int], int]" 99