File indexing completed on 2025-01-18 10:17:52
0001 import pytest
0002
0003 import env
0004 from pybind11_tests import ConstructorStats
0005 from pybind11_tests import call_policies as m
0006
0007
0008 @pytest.mark.xfail("env.PYPY", reason="sometimes comes out 1 off on PyPy", strict=False)
0009 def test_keep_alive_argument(capture):
0010 n_inst = ConstructorStats.detail_reg_inst()
0011 with capture:
0012 p = m.Parent()
0013 assert capture == "Allocating parent."
0014 with capture:
0015 p.addChild(m.Child())
0016 assert ConstructorStats.detail_reg_inst() == n_inst + 1
0017 assert (
0018 capture
0019 == """
0020 Allocating child.
0021 Releasing child.
0022 """
0023 )
0024 with capture:
0025 del p
0026 assert ConstructorStats.detail_reg_inst() == n_inst
0027 assert capture == "Releasing parent."
0028
0029 with capture:
0030 p = m.Parent()
0031 assert capture == "Allocating parent."
0032 with capture:
0033 p.addChildKeepAlive(m.Child())
0034 assert ConstructorStats.detail_reg_inst() == n_inst + 2
0035 assert capture == "Allocating child."
0036 with capture:
0037 del p
0038 assert ConstructorStats.detail_reg_inst() == n_inst
0039 assert (
0040 capture
0041 == """
0042 Releasing parent.
0043 Releasing child.
0044 """
0045 )
0046
0047 p = m.Parent()
0048 c = m.Child()
0049 assert ConstructorStats.detail_reg_inst() == n_inst + 2
0050 m.free_function(p, c)
0051 del c
0052 assert ConstructorStats.detail_reg_inst() == n_inst + 2
0053 del p
0054 assert ConstructorStats.detail_reg_inst() == n_inst
0055
0056 with pytest.raises(RuntimeError) as excinfo:
0057 m.invalid_arg_index()
0058 assert str(excinfo.value) == "Could not activate keep_alive!"
0059
0060
0061 def test_keep_alive_return_value(capture):
0062 n_inst = ConstructorStats.detail_reg_inst()
0063 with capture:
0064 p = m.Parent()
0065 assert capture == "Allocating parent."
0066 with capture:
0067 p.returnChild()
0068 assert ConstructorStats.detail_reg_inst() == n_inst + 1
0069 assert (
0070 capture
0071 == """
0072 Allocating child.
0073 Releasing child.
0074 """
0075 )
0076 with capture:
0077 del p
0078 assert ConstructorStats.detail_reg_inst() == n_inst
0079 assert capture == "Releasing parent."
0080
0081 with capture:
0082 p = m.Parent()
0083 assert capture == "Allocating parent."
0084 with capture:
0085 p.returnChildKeepAlive()
0086 assert ConstructorStats.detail_reg_inst() == n_inst + 2
0087 assert capture == "Allocating child."
0088 with capture:
0089 del p
0090 assert ConstructorStats.detail_reg_inst() == n_inst
0091 assert (
0092 capture
0093 == """
0094 Releasing parent.
0095 Releasing child.
0096 """
0097 )
0098
0099 p = m.Parent()
0100 assert ConstructorStats.detail_reg_inst() == n_inst + 1
0101 with capture:
0102 m.Parent.staticFunction(p)
0103 assert ConstructorStats.detail_reg_inst() == n_inst + 2
0104 assert capture == "Allocating child."
0105 with capture:
0106 del p
0107 assert ConstructorStats.detail_reg_inst() == n_inst
0108 assert (
0109 capture
0110 == """
0111 Releasing parent.
0112 Releasing child.
0113 """
0114 )
0115
0116
0117
0118 @pytest.mark.xfail("env.PYPY", reason="_PyObject_GetDictPtr is unimplemented")
0119 def test_alive_gc(capture):
0120 n_inst = ConstructorStats.detail_reg_inst()
0121 p = m.ParentGC()
0122 p.addChildKeepAlive(m.Child())
0123 assert ConstructorStats.detail_reg_inst() == n_inst + 2
0124 lst = [p]
0125 lst.append(lst)
0126 with capture:
0127 del p, lst
0128 assert ConstructorStats.detail_reg_inst() == n_inst
0129 assert (
0130 capture
0131 == """
0132 Releasing parent.
0133 Releasing child.
0134 """
0135 )
0136
0137
0138 def test_alive_gc_derived(capture):
0139 class Derived(m.Parent):
0140 pass
0141
0142 n_inst = ConstructorStats.detail_reg_inst()
0143 p = Derived()
0144 p.addChildKeepAlive(m.Child())
0145 assert ConstructorStats.detail_reg_inst() == n_inst + 2
0146 lst = [p]
0147 lst.append(lst)
0148 with capture:
0149 del p, lst
0150 assert ConstructorStats.detail_reg_inst() == n_inst
0151 assert (
0152 capture
0153 == """
0154 Releasing parent.
0155 Releasing child.
0156 """
0157 )
0158
0159
0160 def test_alive_gc_multi_derived(capture):
0161 class Derived(m.Parent, m.Child):
0162 def __init__(self):
0163 m.Parent.__init__(self)
0164 m.Child.__init__(self)
0165
0166 n_inst = ConstructorStats.detail_reg_inst()
0167 p = Derived()
0168 p.addChildKeepAlive(m.Child())
0169
0170 assert ConstructorStats.detail_reg_inst() == n_inst + 3
0171 lst = [p]
0172 lst.append(lst)
0173 with capture:
0174 del p, lst
0175 assert ConstructorStats.detail_reg_inst() == n_inst
0176 assert (
0177 capture
0178 == """
0179 Releasing parent.
0180 Releasing child.
0181 Releasing child.
0182 """
0183 )
0184
0185
0186 def test_return_none(capture):
0187 n_inst = ConstructorStats.detail_reg_inst()
0188 with capture:
0189 p = m.Parent()
0190 assert capture == "Allocating parent."
0191 with capture:
0192 p.returnNullChildKeepAliveChild()
0193 assert ConstructorStats.detail_reg_inst() == n_inst + 1
0194 assert capture == ""
0195 with capture:
0196 del p
0197 assert ConstructorStats.detail_reg_inst() == n_inst
0198 assert capture == "Releasing parent."
0199
0200 with capture:
0201 p = m.Parent()
0202 assert capture == "Allocating parent."
0203 with capture:
0204 p.returnNullChildKeepAliveParent()
0205 assert ConstructorStats.detail_reg_inst() == n_inst + 1
0206 assert capture == ""
0207 with capture:
0208 del p
0209 assert ConstructorStats.detail_reg_inst() == n_inst
0210 assert capture == "Releasing parent."
0211
0212
0213 def test_keep_alive_constructor(capture):
0214 n_inst = ConstructorStats.detail_reg_inst()
0215
0216 with capture:
0217 p = m.Parent(m.Child())
0218 assert ConstructorStats.detail_reg_inst() == n_inst + 2
0219 assert (
0220 capture
0221 == """
0222 Allocating child.
0223 Allocating parent.
0224 """
0225 )
0226 with capture:
0227 del p
0228 assert ConstructorStats.detail_reg_inst() == n_inst
0229 assert (
0230 capture
0231 == """
0232 Releasing parent.
0233 Releasing child.
0234 """
0235 )
0236
0237
0238 def test_call_guard():
0239 assert m.unguarded_call() == "unguarded"
0240 assert m.guarded_call() == "guarded"
0241
0242 assert m.multiple_guards_correct_order() == "guarded & guarded"
0243 assert m.multiple_guards_wrong_order() == "unguarded & guarded"
0244
0245 if hasattr(m, "with_gil"):
0246 assert m.with_gil() == "GIL held"
0247 assert m.without_gil() == "GIL released"