6 m = pytest.importorskip(
"pybind11_tests.virtual_functions")
7 from pybind11_tests
import ConstructorStats
11 class ExtendedExampleVirt(m.ExampleVirt):
12 def __init__(self, state):
13 super(ExtendedExampleVirt, self).__init__(state + 1)
14 self.data =
"Hello world"
17 print(
"ExtendedExampleVirt::run(%i), calling parent.." % value)
18 return super(ExtendedExampleVirt, self).run(value + 1)
21 print(
"ExtendedExampleVirt::run_bool()")
24 def get_string1(self):
27 def pure_virtual(self):
28 print(
"ExtendedExampleVirt::pure_virtual(): %s" % self.data)
30 class ExtendedExampleVirt2(ExtendedExampleVirt):
31 def __init__(self, state):
32 super(ExtendedExampleVirt2, self).__init__(state + 1)
34 def get_string2(self):
37 ex12 = m.ExampleVirt(10)
39 assert m.runExampleVirt(ex12, 20) == 30
43 Original implementation of ExampleVirt::run(state=10, value=20, str1=default1, str2=default2)
47 with pytest.raises(RuntimeError)
as excinfo:
48 m.runExampleVirtVirtual(ex12)
51 ==
'Tried to call pure virtual function "ExampleVirt::pure_virtual"'
54 ex12p = ExtendedExampleVirt(10)
56 assert m.runExampleVirt(ex12p, 20) == 32
60 ExtendedExampleVirt::run(20), calling parent..
61 Original implementation of ExampleVirt::run(state=11, value=21, str1=override1, str2=default2)
65 assert m.runExampleVirtBool(ex12p)
is False
66 assert capture ==
"ExtendedExampleVirt::run_bool()"
68 m.runExampleVirtVirtual(ex12p)
69 assert capture ==
"ExtendedExampleVirt::pure_virtual(): Hello world"
71 ex12p2 = ExtendedExampleVirt2(15)
73 assert m.runExampleVirt(ex12p2, 50) == 68
77 ExtendedExampleVirt::run(50), calling parent..
78 Original implementation of ExampleVirt::run(state=17, value=51, str1=override1, str2=override2)
83 assert cstats.alive() == 3
84 del ex12, ex12p, ex12p2
85 assert cstats.alive() == 0
86 assert cstats.values() == [
"10",
"11",
"17"]
87 assert cstats.copy_constructions == 0
88 assert cstats.move_constructions >= 0
92 """`A` only initializes its trampoline class when we inherit from it
94 If we just create and use an A instance directly, the trampoline initialization is
95 bypassed and we only initialize an A() instead (for performance reasons).
100 super(B, self).__init__()
103 print(
"In python f()")
111 assert capture ==
"A.f()"
131 """`A2`, unlike the above, is configured to always initialize the alias
133 While the extra initialization and extra class layer has small virtual dispatch
134 performance penalty, it also allows us to do more things with the trampoline
135 class such as defining local variables and performing construction/destruction.
140 super(B2, self).__init__()
143 print(
"In python B2.f()")
188 @pytest.mark.xfail(
"env.PYPY")
190 not hasattr(m,
"NCVirt"), reason=
"NCVirt does not work on Intel/PGI/NVCC compilers"
193 class NCVirtExt(m.NCVirt):
194 def get_noncopyable(self, a, b):
196 nc = m.NonCopyable(a * a, b * b)
199 def get_movable(self, a, b):
201 self.movable = m.Movable(a, b)
204 class NCVirtExt2(m.NCVirt):
205 def get_noncopyable(self, a, b):
207 self.nc = m.NonCopyable(a, b)
210 def get_movable(self, a, b):
212 return m.Movable(a, b)
215 assert ncv1.print_nc(2, 3) ==
"36"
216 assert ncv1.print_movable(4, 5) ==
"9"
218 assert ncv2.print_movable(7, 7) ==
"14"
220 with pytest.raises(RuntimeError):
225 assert nc_stats.alive() == 1
226 assert mv_stats.alive() == 1
228 assert nc_stats.alive() == 0
229 assert mv_stats.alive() == 0
230 assert nc_stats.values() == [
"4",
"9",
"9",
"9"]
231 assert mv_stats.values() == [
"4",
"5",
"7",
"7"]
232 assert nc_stats.copy_constructions == 0
233 assert mv_stats.copy_constructions == 1
234 assert nc_stats.move_constructions >= 0
235 assert mv_stats.move_constructions >= 0
239 """#159: virtual function dispatch has problems with similar-named functions"""
241 class PyClass1(m.DispatchIssue):
245 class PyClass2(m.DispatchIssue):
247 with pytest.raises(RuntimeError)
as excinfo:
248 super(PyClass2, self).dispatch()
251 ==
'Tried to call pure virtual function "Base::dispatch"'
254 return m.dispatch_issue_go(PyClass1())
257 assert m.dispatch_issue_go(b) ==
"Yay.."
261 """#392/397: overriding reference-returning functions"""
262 o = m.OverrideTest(
"asdf")
267 assert o.str_value() ==
"asdf"
269 assert o.A_value().value ==
"hi"
271 assert a.value ==
"hi"
273 assert a.value ==
"bye"
277 class AR(m.A_Repeat):
278 def unlucky_number(self):
282 def unlucky_number(self):
286 assert obj.say_something(3) ==
"hihihi"
287 assert obj.unlucky_number() == 99
288 assert obj.say_everything() ==
"hi 99"
291 assert obj.say_something(3) ==
"hihihi"
292 assert obj.unlucky_number() == 999
293 assert obj.say_everything() ==
"hi 999"
295 for obj
in [m.B_Repeat(), m.B_Tpl()]:
296 assert obj.say_something(3) ==
"B says hi 3 times"
297 assert obj.unlucky_number() == 13
298 assert obj.lucky_number() == 7.0
299 assert obj.say_everything() ==
"B says hi 1 times 13"
301 for obj
in [m.C_Repeat(), m.C_Tpl()]:
302 assert obj.say_something(3) ==
"B says hi 3 times"
303 assert obj.unlucky_number() == 4444
304 assert obj.lucky_number() == 888.0
305 assert obj.say_everything() ==
"B says hi 1 times 4444"
307 class CR(m.C_Repeat):
308 def lucky_number(self):
309 return m.C_Repeat.lucky_number(self) + 1.25
312 assert obj.say_something(3) ==
"B says hi 3 times"
313 assert obj.unlucky_number() == 4444
314 assert obj.lucky_number() == 889.25
315 assert obj.say_everything() ==
"B says hi 1 times 4444"
321 assert obj.say_something(3) ==
"B says hi 3 times"
322 assert obj.unlucky_number() == 4444
323 assert obj.lucky_number() == 888.0
324 assert obj.say_everything() ==
"B says hi 1 times 4444"
327 def lucky_number(self):
328 return CR.lucky_number(self) * 10
331 assert obj.say_something(3) ==
"B says hi 3 times"
332 assert obj.unlucky_number() == 4444
333 assert obj.lucky_number() == 8892.5
334 assert obj.say_everything() ==
"B says hi 1 times 4444"
337 def lucky_number(self):
338 return CT.lucky_number(self) * 1000
341 assert obj.say_something(3) ==
"B says hi 3 times"
342 assert obj.unlucky_number() == 4444
343 assert obj.lucky_number() == 888000.0
344 assert obj.say_everything() ==
"B says hi 1 times 4444"
346 class DR(m.D_Repeat):
347 def unlucky_number(self):
350 def lucky_number(self):
353 for obj
in [m.D_Repeat(), m.D_Tpl()]:
354 assert obj.say_something(3) ==
"B says hi 3 times"
355 assert obj.unlucky_number() == 4444
356 assert obj.lucky_number() == 888.0
357 assert obj.say_everything() ==
"B says hi 1 times 4444"
360 assert obj.say_something(3) ==
"B says hi 3 times"
361 assert obj.unlucky_number() == 123
362 assert obj.lucky_number() == 42.0
363 assert obj.say_everything() ==
"B says hi 1 times 123"
366 def say_something(self, times):
367 return "DT says:" + (
" quack" * times)
369 def unlucky_number(self):
372 def lucky_number(self):
376 assert obj.say_something(3) ==
"DT says: quack quack quack"
377 assert obj.unlucky_number() == 1234
378 assert obj.lucky_number() == -4.25
379 assert obj.say_everything() ==
"DT says: quack 1234"
382 def say_something(self, times):
383 return "DT2: " + (
"QUACK" * times)
385 def unlucky_number(self):
389 def say_something(self, times):
392 def unlucky_number(self):
395 def lucky_number(self):
399 assert obj.say_something(3) ==
"BTBTBT"
400 assert obj.unlucky_number() == -7
401 assert obj.lucky_number() == -1.375
402 assert obj.say_everything() ==
"BT -7"
408 m.test_gil_from_thread()