blob: b6d9e84cab53067611b66199c54d7f29375201c5 [file] [log] [blame]
Jason Rhinelanderec62d972016-09-09 02:42:51 -04001import pytest
2import gc
3
4def test_alias_delay_initialization(capture, msg):
5
6 # A only initializes its trampoline class when we inherit from it; if we
7 # just create and use an A instance directly, the trampoline initialization
8 # is bypassed and we only initialize an A() instead (for performance
9 # reasons)
10 from pybind11_tests import A, call_f
11
12 class B(A):
13 def __init__(self):
14 super(B, self).__init__()
15
16 def f(self):
17 print("In python f()")
18
19 # C++ version
20 with capture:
21 a = A()
22 call_f(a)
23 del a
24 gc.collect()
25 assert capture == "A.f()"
26
27 # Python version
28 with capture:
29 b = B()
30 call_f(b)
31 del b
32 gc.collect()
33 assert capture == """
34 PyA.PyA()
35 PyA.f()
36 In python f()
37 PyA.~PyA()
38 """
39
40def test_alias_delay_initialization(capture, msg):
41 from pybind11_tests import A2, call_f
42
43 # A2, unlike the above, is configured to always initialize the alias; while
44 # the extra initialization and extra class layer has small virtual dispatch
45 # performance penalty, it also allows us to do more things with the
46 # trampoline class such as defining local variables and performing
47 # construction/destruction.
48
49 class B2(A2):
50 def __init__(self):
51 super(B2, self).__init__()
52
53 def f(self):
54 print("In python B2.f()")
55
56 # No python subclass version
57 with capture:
58 a2 = A2()
59 call_f(a2)
60 del a2
61 gc.collect()
62 assert capture == """
63 PyA2.PyA2()
64 PyA2.f()
65 A2.f()
66 PyA2.~PyA2()
67 """
68
69 # Python subclass version
70 with capture:
71 b2 = B2()
72 call_f(b2)
73 del b2
74 gc.collect()
75 assert capture == """
76 PyA2.PyA2()
77 PyA2.f()
78 In python B2.f()
79 PyA2.~PyA2()
80 """