1 from __future__
import annotations
5 from threading
import Thread
10 from pybind11_tests
import callbacks
as m
11 from pybind11_tests
import detailed_error_messages_enabled
15 from functools
import partial
20 def func2(a, b, c, d):
21 return "func2", a, b, c, d
26 assert m.test_callback1(func1) ==
"func1"
27 assert m.test_callback2(func2) == (
"func2",
"Hello",
"x",
True, 5)
28 assert m.test_callback1(partial(func2, 1, 2, 3, 4)) == (
"func2", 1, 2, 3, 4)
29 assert m.test_callback1(partial(func3,
"partial")) ==
"func3(partial)"
30 assert m.test_callback3(
lambda i: i + 1) ==
"func(43) = 44"
32 f = m.test_callback4()
34 f = m.test_callback5()
35 assert f(number=43) == 44
41 def double(self, val):
45 assert m.test_callback3(z.double) ==
"func(43) = 86"
47 z = m.CppBoundMethodTest()
48 assert m.test_callback3(z.triple) ==
"func(43) = 129"
52 def f(*args, **kwargs):
55 assert m.test_tuple_unpacking(f) == ((
"positional", 1, 2, 3, 4, 5, 6), {})
56 assert m.test_dict_unpacking(f) == (
58 {
"key":
"value",
"a": 1,
"b": 2},
60 assert m.test_keyword_args(f) == ((), {
"x": 10,
"y": 20})
61 assert m.test_unpacking_and_keywords1(f) == ((1, 2), {
"c": 3,
"d": 4})
62 assert m.test_unpacking_and_keywords2(f) == (
63 (
"positional", 1, 2, 3, 4, 5),
64 {
"key":
"value",
"a": 1,
"b": 2,
"c": 3,
"d": 4,
"e": 5},
67 with pytest.raises(TypeError)
as excinfo:
68 m.test_unpacking_error1(f)
69 assert "Got multiple values for keyword argument" in str(excinfo.value)
71 with pytest.raises(TypeError)
as excinfo:
72 m.test_unpacking_error2(f)
73 assert "Got multiple values for keyword argument" in str(excinfo.value)
75 with pytest.raises(RuntimeError)
as excinfo:
76 m.test_arg_conversion_error1(f)
77 assert str(excinfo.value) ==
"Unable to convert call argument " + (
78 "'1' of type 'UnregisteredType' to Python object"
79 if detailed_error_messages_enabled
80 else "'1' to Python object (#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for details)"
83 with pytest.raises(RuntimeError)
as excinfo:
84 m.test_arg_conversion_error2(f)
85 assert str(excinfo.value) ==
"Unable to convert call argument " + (
86 "'expected_name' of type 'UnregisteredType' to Python object"
87 if detailed_error_messages_enabled
88 else "'expected_name' to Python object "
89 "(#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for details)"
94 m.test_lambda_closure_cleanup()
95 cstats = m.payload_cstats()
96 assert cstats.alive() == 0
97 assert cstats.copy_constructions == 1
98 assert cstats.move_constructions >= 1
102 alive_counts = m.test_cpp_callable_cleanup()
103 assert alive_counts == [0, 1, 2, 1, 2, 1, 0]
107 """Test if passing a function pointer from C++ -> Python -> C++ yields the original pointer"""
110 m.test_dummy_function(m.dummy_function) ==
"matches dummy_function: eval(1) = 2"
113 m.test_dummy_function(m.roundtrip(m.dummy_function))
114 ==
"matches dummy_function: eval(1) = 2"
117 m.test_dummy_function(m.dummy_function_overloaded)
118 ==
"matches dummy_function: eval(1) = 2"
120 assert m.roundtrip(
None, expect_none=
True)
is None
122 m.test_dummy_function(
lambda x: x + 2)
123 ==
"can't convert to function pointer: eval(1) = 3"
126 with pytest.raises(TypeError)
as excinfo:
127 m.test_dummy_function(m.dummy_function2)
128 assert "incompatible function arguments" in str(excinfo.value)
130 with pytest.raises(TypeError)
as excinfo:
131 m.test_dummy_function(
lambda x, y: x + y)
133 s
in str(excinfo.value)
134 for s
in (
"missing 1 required positional argument",
"takes exactly 2 arguments")
139 assert doc(m.test_callback3) ==
"test_callback3(arg0: Callable[[int], int]) -> str"
140 assert doc(m.test_callback4) ==
"test_callback4() -> Callable[[int], int]"
144 assert m.callback_with_movable(
lambda _:
None)
is True
149 reason=
"PyPy segfaults on here. See discussion on #1413.",
152 """Test if python builtins like sum() can be used as callbacks"""
153 assert m.test_sum_builtin(sum, [1, 2, 3]) == 6
154 assert m.test_sum_builtin(sum, []) == 0
157 @pytest.mark.skipif(sys.platform.startswith(
"emscripten"), reason=
"Requires threads")
169 return lambda j: res.append(s.value + j)
173 m.test_async_callback(gen_f(), work)
175 from time
import sleep
178 assert sum(res) == sum(x + 3
for x
in work)
181 @pytest.mark.skipif(sys.platform.startswith(
"emscripten"), reason=
"Requires threads")
183 t = Thread(target=test_async_callbacks)
193 one_million = 1000000
197 for rep
in range(repeats):
199 m.callback_num_times(
lambda:
None, num_millions * one_million)
200 td = time.time() - t0
201 rate = num_millions / td
if td
else 0
206 f
"callback_num_times: {num_millions:d} million / {td:.3f} seconds = {rate:.3f} million / second"
209 print(
"Min Mean Max")
210 print(f
"{min(rates):6.3f} {sum(rates) / len(rates):6.3f} {max(rates):6.3f}")
214 assert m.custom_function(4) == 36
215 assert m.roundtrip(m.custom_function)(4) == 36
219 m.custom_function2
is None, reason=
"Current PYBIND11_INTERNALS_VERSION too low"
222 assert m.custom_function2(3) == 27
223 assert m.roundtrip(m.custom_function2)(3) == 27
228 m.test_tuple_unpacking.__doc__.strip()
229 ==
"test_tuple_unpacking(arg0: Callable) -> object"