2c2,3
< import pybind11_tests
---
>
> from pybind11_tests import virtual_functions as m
7,10c8
< from pybind11_tests import (ExampleVirt, runExampleVirt, runExampleVirtVirtual,
< runExampleVirtBool)
<
< class ExtendedExampleVirt(ExampleVirt):
---
> class ExtendedExampleVirt(m.ExampleVirt):
36c34
< ex12 = ExampleVirt(10)
---
> ex12 = m.ExampleVirt(10)
38c36
< assert runExampleVirt(ex12, 20) == 30
---
> assert m.runExampleVirt(ex12, 20) == 30
44c42
< runExampleVirtVirtual(ex12)
---
> m.runExampleVirtVirtual(ex12)
49c47
< assert runExampleVirt(ex12p, 20) == 32
---
> assert m.runExampleVirt(ex12p, 20) == 32
55c53
< assert runExampleVirtBool(ex12p) is False
---
> assert m.runExampleVirtBool(ex12p) is False
58c56
< runExampleVirtVirtual(ex12p)
---
> m.runExampleVirtVirtual(ex12p)
63c61
< assert runExampleVirt(ex12p2, 50) == 68
---
> assert m.runExampleVirt(ex12p2, 50) == 68
69c67
< cstats = ConstructorStats.get(ExampleVirt)
---
> cstats = ConstructorStats.get(m.ExampleVirt)
78,79c76,77
< def test_inheriting_repeat():
< from pybind11_tests import A_Repeat, B_Repeat, C_Repeat, D_Repeat, A_Tpl, B_Tpl, C_Tpl, D_Tpl
---
> def test_alias_delay_initialization1(capture):
> """`A` only initializes its trampoline class when we inherit from it
81c79,246
< class AR(A_Repeat):
---
> If we just create and use an A instance directly, the trampoline initialization is
> bypassed and we only initialize an A() instead (for performance reasons).
> """
> class B(m.A):
> def __init__(self):
> super(B, self).__init__()
>
> def f(self):
> print("In python f()")
>
> # C++ version
> with capture:
> a = m.A()
> m.call_f(a)
> del a
> pytest.gc_collect()
> assert capture == "A.f()"
>
> # Python version
> with capture:
> b = B()
> m.call_f(b)
> del b
> pytest.gc_collect()
> assert capture == """
> PyA.PyA()
> PyA.f()
> In python f()
> PyA.~PyA()
> """
>
>
> def test_alias_delay_initialization2(capture):
> """`A2`, unlike the above, is configured to always initialize the alias
>
> While the extra initialization and extra class layer has small virtual dispatch
> performance penalty, it also allows us to do more things with the trampoline
> class such as defining local variables and performing construction/destruction.
> """
> class B2(m.A2):
> def __init__(self):
> super(B2, self).__init__()
>
> def f(self):
> print("In python B2.f()")
>
> # No python subclass version
> with capture:
> a2 = m.A2()
> m.call_f(a2)
> del a2
> pytest.gc_collect()
> a3 = m.A2(1)
> m.call_f(a3)
> del a3
> pytest.gc_collect()
> assert capture == """
> PyA2.PyA2()
> PyA2.f()
> A2.f()
> PyA2.~PyA2()
> PyA2.PyA2()
> PyA2.f()
> A2.f()
> PyA2.~PyA2()
> """
>
> # Python subclass version
> with capture:
> b2 = B2()
> m.call_f(b2)
> del b2
> pytest.gc_collect()
> assert capture == """
> PyA2.PyA2()
> PyA2.f()
> In python B2.f()
> PyA2.~PyA2()
> """
>
>
> # PyPy: Reference count > 1 causes call with noncopyable instance
> # to fail in ncv1.print_nc()
> @pytest.unsupported_on_pypy
> @pytest.mark.skipif(not hasattr(m, "NCVirt"), reason="NCVirt test broken on ICPC")
> def test_move_support():
> class NCVirtExt(m.NCVirt):
> def get_noncopyable(self, a, b):
> # Constructs and returns a new instance:
> nc = m.NonCopyable(a * a, b * b)
> return nc
>
> def get_movable(self, a, b):
> # Return a referenced copy
> self.movable = m.Movable(a, b)
> return self.movable
>
> class NCVirtExt2(m.NCVirt):
> def get_noncopyable(self, a, b):
> # Keep a reference: this is going to throw an exception
> self.nc = m.NonCopyable(a, b)
> return self.nc
>
> def get_movable(self, a, b):
> # Return a new instance without storing it
> return m.Movable(a, b)
>
> ncv1 = NCVirtExt()
> assert ncv1.print_nc(2, 3) == "36"
> assert ncv1.print_movable(4, 5) == "9"
> ncv2 = NCVirtExt2()
> assert ncv2.print_movable(7, 7) == "14"
> # Don't check the exception message here because it differs under debug/non-debug mode
> with pytest.raises(RuntimeError):
> ncv2.print_nc(9, 9)
>
> nc_stats = ConstructorStats.get(m.NonCopyable)
> mv_stats = ConstructorStats.get(m.Movable)
> assert nc_stats.alive() == 1
> assert mv_stats.alive() == 1
> del ncv1, ncv2
> assert nc_stats.alive() == 0
> assert mv_stats.alive() == 0
> assert nc_stats.values() == ['4', '9', '9', '9']
> assert mv_stats.values() == ['4', '5', '7', '7']
> assert nc_stats.copy_constructions == 0
> assert mv_stats.copy_constructions == 1
> assert nc_stats.move_constructions >= 0
> assert mv_stats.move_constructions >= 0
>
>
> def test_dispatch_issue(msg):
> """#159: virtual function dispatch has problems with similar-named functions"""
> class PyClass1(m.DispatchIssue):
> def dispatch(self):
> return "Yay.."
>
> class PyClass2(m.DispatchIssue):
> def dispatch(self):
> with pytest.raises(RuntimeError) as excinfo:
> super(PyClass2, self).dispatch()
> assert msg(excinfo.value) == 'Tried to call pure virtual function "Base::dispatch"'
>
> p = PyClass1()
> return m.dispatch_issue_go(p)
>
> b = PyClass2()
> assert m.dispatch_issue_go(b) == "Yay.."
>
>
> def test_override_ref():
> """#392/397: overridding reference-returning functions"""
> o = m.OverrideTest("asdf")
>
> # Not allowed (see associated .cpp comment)
> # i = o.str_ref()
> # assert o.str_ref() == "asdf"
> assert o.str_value() == "asdf"
>
> assert o.A_value().value == "hi"
> a = o.A_ref()
> assert a.value == "hi"
> a.value = "bye"
> assert a.value == "bye"
>
>
> def test_inherited_virtuals():
> class AR(m.A_Repeat):
85c250
< class AT(A_Tpl):
---
> class AT(m.A_Tpl):
99c264
< for obj in [B_Repeat(), B_Tpl()]:
---
> for obj in [m.B_Repeat(), m.B_Tpl()]:
105c270
< for obj in [C_Repeat(), C_Tpl()]:
---
> for obj in [m.C_Repeat(), m.C_Tpl()]:
111c276
< class CR(C_Repeat):
---
> class CR(m.C_Repeat):
113c278
< return C_Repeat.lucky_number(self) + 1.25
---
> return m.C_Repeat.lucky_number(self) + 1.25
121c286
< class CT(C_Tpl):
---
> class CT(m.C_Tpl):
150c315
< class DR(D_Repeat):
---
> class DR(m.D_Repeat):
157c322
< for obj in [D_Repeat(), D_Tpl()]:
---
> for obj in [m.D_Repeat(), m.D_Tpl()]:
169c334
< class DT(D_Tpl):
---
> class DT(m.D_Tpl):
192c357
< class BT(B_Tpl):
---
> class BT(m.B_Tpl):
207,259d371
<
<
< # PyPy: Reference count > 1 causes call with noncopyable instance
< # to fail in ncv1.print_nc()
< @pytest.unsupported_on_pypy
< @pytest.mark.skipif(not hasattr(pybind11_tests, 'NCVirt'),
< reason="NCVirt test broken on ICPC")
< def test_move_support():
< from pybind11_tests import NCVirt, NonCopyable, Movable
<
< class NCVirtExt(NCVirt):
< def get_noncopyable(self, a, b):
< # Constructs and returns a new instance:
< nc = NonCopyable(a * a, b * b)
< return nc
<
< def get_movable(self, a, b):
< # Return a referenced copy
< self.movable = Movable(a, b)
< return self.movable
<
< class NCVirtExt2(NCVirt):
< def get_noncopyable(self, a, b):
< # Keep a reference: this is going to throw an exception
< self.nc = NonCopyable(a, b)
< return self.nc
<
< def get_movable(self, a, b):
< # Return a new instance without storing it
< return Movable(a, b)
<
< ncv1 = NCVirtExt()
< assert ncv1.print_nc(2, 3) == "36"
< assert ncv1.print_movable(4, 5) == "9"
< ncv2 = NCVirtExt2()
< assert ncv2.print_movable(7, 7) == "14"
< # Don't check the exception message here because it differs under debug/non-debug mode
< with pytest.raises(RuntimeError):
< ncv2.print_nc(9, 9)
<
< nc_stats = ConstructorStats.get(NonCopyable)
< mv_stats = ConstructorStats.get(Movable)
< assert nc_stats.alive() == 1
< assert mv_stats.alive() == 1
< del ncv1, ncv2
< assert nc_stats.alive() == 0
< assert mv_stats.alive() == 0
< assert nc_stats.values() == ['4', '9', '9', '9']
< assert mv_stats.values() == ['4', '5', '7', '7']
< assert nc_stats.copy_constructions == 0
< assert mv_stats.copy_constructions == 1
< assert nc_stats.move_constructions >= 0
< assert mv_stats.move_constructions >= 0