5m = pytest.importorskip(
"pybind11_tests.virtual_functions")
6from pybind11_tests
import ConstructorStats
9def test_override(capture, msg):
10 class ExtendedExampleVirt(m.ExampleVirt):
11 def __init__(self, state):
12 super().__init__(state + 1)
13 self.data =
"Hello world"
16 print(f
"ExtendedExampleVirt::run({value}), calling parent..")
17 return super().run(value + 1)
20 print(
"ExtendedExampleVirt::run_bool()")
23 def get_string1(self):
26 def pure_virtual(self):
27 print(f
"ExtendedExampleVirt::pure_virtual(): {self.data}")
29 class ExtendedExampleVirt2(ExtendedExampleVirt):
30 def __init__(self, state):
31 super().__init__(state + 1)
33 def get_string2(self):
36 ex12 = m.ExampleVirt(10)
38 assert m.runExampleVirt(ex12, 20) == 30
42 Original implementation of ExampleVirt::run(state=10, value=20, str1=default1, str2=default2)
46 with pytest.raises(RuntimeError)
as excinfo:
47 m.runExampleVirtVirtual(ex12)
50 ==
'Tried to call pure virtual function "ExampleVirt::pure_virtual"'
53 ex12p = ExtendedExampleVirt(10)
55 assert m.runExampleVirt(ex12p, 20) == 32
59 ExtendedExampleVirt::run(20), calling parent..
60 Original implementation of ExampleVirt::run(state=11, value=21, str1=override1, str2=default2)
64 assert m.runExampleVirtBool(ex12p)
is False
65 assert capture ==
"ExtendedExampleVirt::run_bool()"
67 m.runExampleVirtVirtual(ex12p)
68 assert capture ==
"ExtendedExampleVirt::pure_virtual(): Hello world"
70 ex12p2 = ExtendedExampleVirt2(15)
72 assert m.runExampleVirt(ex12p2, 50) == 68
76 ExtendedExampleVirt::run(50), calling parent..
77 Original implementation of ExampleVirt::run(state=17, value=51, str1=override1, str2=override2)
82 assert cstats.alive() == 3
83 del ex12, ex12p, ex12p2
84 assert cstats.alive() == 0
85 assert cstats.values() == [
"10",
"11",
"17"]
86 assert cstats.copy_constructions == 0
87 assert cstats.move_constructions >= 0
90def test_alias_delay_initialization1(capture):
91 """`A` only initializes its trampoline class when we inherit from it
93 If we just create and use an A instance directly, the trampoline initialization
is
94 bypassed
and we only initialize an
A() instead (
for performance reasons).
102 print(
"In python f()")
110 assert capture ==
"A.f()"
129def test_alias_delay_initialization2(capture):
130 """`A2`, unlike the above, is configured to always initialize the alias
132 While the extra initialization and extra
class layer has small virtual dispatch
133 performance penalty, it also allows us to do more things
with the trampoline
134 class such as defining local variables and performing construction/destruction.
142 print(
"In python B2.f()")
187@pytest.mark.xfail("env.PYPY")
189 not hasattr(m,
"NCVirt"), reason=
"NCVirt does not work on Intel/PGI/NVCC compilers"
191def test_move_support():
192 class NCVirtExt(m.NCVirt):
193 def get_noncopyable(self, a, b):
195 nc = m.NonCopyable(a * a, b * b)
198 def get_movable(self, a, b):
200 self.movable = m.Movable(a, b)
203 class NCVirtExt2(m.NCVirt):
204 def get_noncopyable(self, a, b):
206 self.nc = m.NonCopyable(a, b)
209 def get_movable(self, a, b):
211 return m.Movable(a, b)
214 assert ncv1.print_nc(2, 3) ==
"36"
215 assert ncv1.print_movable(4, 5) ==
"9"
217 assert ncv2.print_movable(7, 7) ==
"14"
219 with pytest.raises(RuntimeError):
224 assert nc_stats.alive() == 1
225 assert mv_stats.alive() == 1
227 assert nc_stats.alive() == 0
228 assert mv_stats.alive() == 0
229 assert nc_stats.values() == [
"4",
"9",
"9",
"9"]
230 assert mv_stats.values() == [
"4",
"5",
"7",
"7"]
231 assert nc_stats.copy_constructions == 0
232 assert mv_stats.copy_constructions == 1
233 assert nc_stats.move_constructions >= 0
234 assert mv_stats.move_constructions >= 0
237def test_dispatch_issue(msg):
238 """#159: virtual function dispatch has problems with similar-named functions"""
240 class PyClass1(m.DispatchIssue):
244 class PyClass2(m.DispatchIssue):
246 with pytest.raises(RuntimeError)
as excinfo:
250 ==
'Tried to call pure virtual function "Base::dispatch"'
253 return m.dispatch_issue_go(PyClass1())
256 assert m.dispatch_issue_go(b) ==
"Yay.."
259def test_recursive_dispatch_issue(msg):
260 """#3357: Recursive dispatch fails to find python function override"""
263 def __init__(self, value):
267 class Adder(m.Adder):
268 def __call__(self, first, second, visitor):
272 (
lambda: visitor(Data(first.value + second.value)))()
274 class StoreResultVisitor:
278 def __call__(self, data):
279 self.result = data.value
281 store = StoreResultVisitor()
283 m.add2(Data(1), Data(2),
Adder(), store)
284 assert store.result == 3
288 m.add3(Data(1), Data(2), Data(3),
Adder(), store)
289 assert store.result == 6
292def test_override_ref():
293 """#392/397: overriding reference-returning functions"""
294 o = m.OverrideTest(
"asdf")
299 assert o.str_value() ==
"asdf"
301 assert o.A_value().value ==
"hi"
303 assert a.value ==
"hi"
305 assert a.value ==
"bye"
308def test_inherited_virtuals():
309 class AR(m.A_Repeat):
310 def unlucky_number(self):
314 def unlucky_number(self):
318 assert obj.say_something(3) ==
"hihihi"
319 assert obj.unlucky_number() == 99
320 assert obj.say_everything() ==
"hi 99"
323 assert obj.say_something(3) ==
"hihihi"
324 assert obj.unlucky_number() == 999
325 assert obj.say_everything() ==
"hi 999"
327 for obj
in [m.B_Repeat(), m.B_Tpl()]:
328 assert obj.say_something(3) ==
"B says hi 3 times"
329 assert obj.unlucky_number() == 13
330 assert obj.lucky_number() == 7.0
331 assert obj.say_everything() ==
"B says hi 1 times 13"
333 for obj
in [m.C_Repeat(), m.C_Tpl()]:
334 assert obj.say_something(3) ==
"B says hi 3 times"
335 assert obj.unlucky_number() == 4444
336 assert obj.lucky_number() == 888.0
337 assert obj.say_everything() ==
"B says hi 1 times 4444"
339 class CR(m.C_Repeat):
340 def lucky_number(self):
341 return m.C_Repeat.lucky_number(self) + 1.25
344 assert obj.say_something(3) ==
"B says hi 3 times"
345 assert obj.unlucky_number() == 4444
346 assert obj.lucky_number() == 889.25
347 assert obj.say_everything() ==
"B says hi 1 times 4444"
353 assert obj.say_something(3) ==
"B says hi 3 times"
354 assert obj.unlucky_number() == 4444
355 assert obj.lucky_number() == 888.0
356 assert obj.say_everything() ==
"B says hi 1 times 4444"
359 def lucky_number(self):
360 return CR.lucky_number(self) * 10
363 assert obj.say_something(3) ==
"B says hi 3 times"
364 assert obj.unlucky_number() == 4444
365 assert obj.lucky_number() == 8892.5
366 assert obj.say_everything() ==
"B says hi 1 times 4444"
369 def lucky_number(self):
370 return CT.lucky_number(self) * 1000
373 assert obj.say_something(3) ==
"B says hi 3 times"
374 assert obj.unlucky_number() == 4444
375 assert obj.lucky_number() == 888000.0
376 assert obj.say_everything() ==
"B says hi 1 times 4444"
378 class DR(m.D_Repeat):
379 def unlucky_number(self):
382 def lucky_number(self):
385 for obj
in [m.D_Repeat(), m.D_Tpl()]:
386 assert obj.say_something(3) ==
"B says hi 3 times"
387 assert obj.unlucky_number() == 4444
388 assert obj.lucky_number() == 888.0
389 assert obj.say_everything() ==
"B says hi 1 times 4444"
392 assert obj.say_something(3) ==
"B says hi 3 times"
393 assert obj.unlucky_number() == 123
394 assert obj.lucky_number() == 42.0
395 assert obj.say_everything() ==
"B says hi 1 times 123"
398 def say_something(self, times):
399 return "DT says:" + (
" quack" * times)
401 def unlucky_number(self):
404 def lucky_number(self):
408 assert obj.say_something(3) ==
"DT says: quack quack quack"
409 assert obj.unlucky_number() == 1234
410 assert obj.lucky_number() == -4.25
411 assert obj.say_everything() ==
"DT says: quack 1234"
414 def say_something(self, times):
415 return "DT2: " + (
"QUACK" * times)
417 def unlucky_number(self):
421 def say_something(self, times):
424 def unlucky_number(self):
427 def lucky_number(self):
431 assert obj.say_something(3) ==
"BTBTBT"
432 assert obj.unlucky_number() == -7
433 assert obj.lucky_number() == -1.375
434 assert obj.say_everything() ==
"BT -7"
437def test_issue_1454():
440 m.test_gil_from_thread()
443def test_python_override():
445 class Test(m.test_override_cache_helper):
452 class Test(m.test_override_cache_helper):
457 for _
in range(1500):
458 assert m.test_override_cache(func()) == 42
459 assert m.test_override_cache(func2()) == 0
static ConstructorStats & get(std::type_index type)
bool hasattr(handle obj, handle name)