4 from pybind11_tests
import factory_constructors
as m
5 from pybind11_tests.factory_constructors
import tag
6 from pybind11_tests
import ConstructorStats
10 """Tests py::init_factory() wrapper around various ways of returning the object""" 14 n_inst = ConstructorStats.detail_reg_inst()
16 x1 = m.TestFactory1(tag.unique_ptr, 3)
17 assert x1.value ==
"3" 18 y1 = m.TestFactory1(tag.pointer)
19 assert y1.value ==
"(empty)" 20 z1 = m.TestFactory1(
"hi!")
21 assert z1.value ==
"hi!" 23 assert ConstructorStats.detail_reg_inst() == n_inst + 3
25 x2 = m.TestFactory2(tag.move)
26 assert x2.value ==
"(empty2)" 27 y2 = m.TestFactory2(tag.pointer, 7)
28 assert y2.value ==
"7" 29 z2 = m.TestFactory2(tag.unique_ptr,
"hi again")
30 assert z2.value ==
"hi again" 32 assert ConstructorStats.detail_reg_inst() == n_inst + 6
34 x3 = m.TestFactory3(tag.shared_ptr)
35 assert x3.value ==
"(empty3)" 36 y3 = m.TestFactory3(tag.pointer, 42)
37 assert y3.value ==
"42" 38 z3 = m.TestFactory3(
"bye")
39 assert z3.value ==
"bye" 41 with pytest.raises(TypeError)
as excinfo:
42 m.TestFactory3(tag.null_ptr)
43 assert str(excinfo.value) ==
"pybind11::init(): factory function returned nullptr" 45 assert [i.alive()
for i
in cstats] == [3, 3, 3]
46 assert ConstructorStats.detail_reg_inst() == n_inst + 9
49 assert [i.alive()
for i
in cstats] == [2, 2, 1]
50 assert ConstructorStats.detail_reg_inst() == n_inst + 5
51 del x2, x3, y1, z1, z2
52 assert [i.alive()
for i
in cstats] == [0, 0, 0]
53 assert ConstructorStats.detail_reg_inst() == n_inst
55 assert [i.values()
for i
in cstats] == [
60 assert [i.default_constructions
for i
in cstats] == [1, 1, 1]
64 with pytest.raises(TypeError)
as excinfo:
65 m.TestFactory1(
"invalid",
"constructor",
"arguments")
66 assert msg(excinfo.value) ==
""" 67 __init__(): incompatible constructor arguments. The following argument types are supported: 68 1. m.factory_constructors.TestFactory1(arg0: m.factory_constructors.tag.unique_ptr_tag, arg1: int) 69 2. m.factory_constructors.TestFactory1(arg0: str) 70 3. m.factory_constructors.TestFactory1(arg0: m.factory_constructors.tag.pointer_tag) 71 4. m.factory_constructors.TestFactory1(arg0: handle, arg1: int, arg2: handle) 73 Invoked with: 'invalid', 'constructor', 'arguments' 76 assert msg(m.TestFactory1.__init__.__doc__) ==
""" 77 __init__(*args, **kwargs) 80 1. __init__(self: m.factory_constructors.TestFactory1, arg0: m.factory_constructors.tag.unique_ptr_tag, arg1: int) -> None 82 2. __init__(self: m.factory_constructors.TestFactory1, arg0: str) -> None 84 3. __init__(self: m.factory_constructors.TestFactory1, arg0: m.factory_constructors.tag.pointer_tag) -> None 86 4. __init__(self: m.factory_constructors.TestFactory1, arg0: handle, arg1: int, arg2: handle) -> None 91 """Tests py::init_factory() wrapper with various upcasting and downcasting returns""" 95 n_inst = ConstructorStats.detail_reg_inst()
98 a = m.TestFactory3(tag.pointer, tag.TF4, 4)
100 b = m.TestFactory3(tag.shared_ptr, tag.TF4, 5)
101 assert b.value ==
"5" 102 c = m.TestFactory3(tag.pointer, tag.TF5, 6)
103 assert c.value ==
"6" 104 d = m.TestFactory3(tag.shared_ptr, tag.TF5, 7)
105 assert d.value ==
"7" 107 assert ConstructorStats.detail_reg_inst() == n_inst + 4
110 e = m.TestFactory4(tag.pointer, tag.TF4, 8)
111 assert e.value ==
"8" 113 assert ConstructorStats.detail_reg_inst() == n_inst + 5
114 assert [i.alive()
for i
in cstats] == [5, 3, 2]
117 assert [i.alive()
for i
in cstats] == [4, 2, 2]
118 assert ConstructorStats.detail_reg_inst() == n_inst + 4
121 assert [i.alive()
for i
in cstats] == [1, 0, 1]
122 assert ConstructorStats.detail_reg_inst() == n_inst + 1
125 assert [i.alive()
for i
in cstats] == [0, 0, 0]
126 assert ConstructorStats.detail_reg_inst() == n_inst
128 assert [i.values()
for i
in cstats] == [
129 [
"4",
"5",
"6",
"7",
"8"],
136 """Tests py::init_factory() wrapper with value conversions and alias types""" 138 cstats = [m.TestFactory6.get_cstats(), m.TestFactory6.get_alias_cstats()]
140 n_inst = ConstructorStats.detail_reg_inst()
142 a = m.TestFactory6(tag.base, 1)
144 assert not a.has_alias()
145 b = m.TestFactory6(tag.alias,
"hi there")
148 c = m.TestFactory6(tag.alias, 3)
151 d = m.TestFactory6(tag.alias, tag.pointer, 4)
154 e = m.TestFactory6(tag.base, tag.pointer, 5)
156 assert not e.has_alias()
157 f = m.TestFactory6(tag.base, tag.alias, tag.pointer, 6)
161 assert ConstructorStats.detail_reg_inst() == n_inst + 6
162 assert [i.alive()
for i
in cstats] == [6, 4]
165 assert [i.alive()
for i
in cstats] == [3, 3]
166 assert ConstructorStats.detail_reg_inst() == n_inst + 3
168 assert [i.alive()
for i
in cstats] == [0, 0]
169 assert ConstructorStats.detail_reg_inst() == n_inst
171 class MyTest(m.TestFactory6):
172 def __init__(self, *args):
173 m.TestFactory6.__init__(self, *args)
176 return -5 + m.TestFactory6.get(self)
179 z = MyTest(tag.base, 123)
180 assert z.get() == 118
184 y = MyTest(tag.alias,
"why hello!")
189 x = MyTest(tag.base, tag.pointer, 47)
193 assert ConstructorStats.detail_reg_inst() == n_inst + 3
194 assert [i.alive()
for i
in cstats] == [3, 3]
196 assert [i.alive()
for i
in cstats] == [0, 0]
197 assert ConstructorStats.detail_reg_inst() == n_inst
199 assert [i.values()
for i
in cstats] == [
200 [
"1",
"8",
"3",
"4",
"5",
"6",
"123",
"10",
"47"],
201 [
"hi there",
"3",
"4",
"6",
"move",
"123",
"why hello!",
"move",
"47"]
206 """Tests init factory functions with dual main/alias factory functions""" 207 from pybind11_tests.factory_constructors
import TestFactory7
209 cstats = [TestFactory7.get_cstats(), TestFactory7.get_alias_cstats()]
211 n_inst = ConstructorStats.detail_reg_inst()
220 assert a2.get() == 102
221 assert not a1.has_alias()
222 assert a2.has_alias()
225 b2 = PythFactory7(tag.pointer, 4)
227 assert b2.get() == 104
228 assert not b1.has_alias()
229 assert b2.has_alias()
232 c2 = PythFactory7(tag.mixed, 6)
234 assert c2.get() == 106
235 assert not c1.has_alias()
236 assert c2.has_alias()
239 d2 = PythFactory7(tag.base, tag.pointer, 8)
241 assert d2.get() == 108
242 assert not d1.has_alias()
243 assert d2.has_alias()
247 e2 = PythFactory7(tag.alias, tag.pointer, 10)
249 assert e2.get() == 200
250 assert e1.has_alias()
251 assert e2.has_alias()
254 f2 = PythFactory7(tag.shared_ptr, tag.base, 12)
255 assert f1.get() == 11
256 assert f2.get() == 112
257 assert not f1.has_alias()
258 assert f2.has_alias()
261 assert g1.get() == 13
262 assert not g1.has_alias()
263 with pytest.raises(TypeError)
as excinfo:
264 PythFactory7(tag.shared_ptr, tag.invalid_base, 14)
265 assert (
str(excinfo.value) ==
266 "pybind11::init(): construction failed: returned holder-wrapped instance is not an " 269 assert [i.alive()
for i
in cstats] == [13, 7]
270 assert ConstructorStats.detail_reg_inst() == n_inst + 13
272 del a1, a2, b1, d1, e1, e2
273 assert [i.alive()
for i
in cstats] == [7, 4]
274 assert ConstructorStats.detail_reg_inst() == n_inst + 7
275 del b2, c1, c2, d2, f1, f2, g1
276 assert [i.alive()
for i
in cstats] == [0, 0]
277 assert ConstructorStats.detail_reg_inst() == n_inst
279 assert [i.values()
for i
in cstats] == [
280 [
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"100",
"11",
"12",
"13",
"14"],
281 [
"2",
"4",
"6",
"8",
"9",
"100",
"12"]
286 """Prior to 2.2, `py::init<...>` relied on the type supporting placement 287 new; this tests a class without placement new support.""" 289 a = m.NoPlacementNew(123)
291 found = re.search(
r'^operator new called, returning (\d+)\n$',
str(capture))
297 assert capture ==
"operator delete called on " + found.group(1)
300 b = m.NoPlacementNew()
302 found = re.search(
r'^operator new called, returning (\d+)\n$',
str(capture))
308 assert capture ==
"operator delete called on " + found.group(1)
312 class MITest(m.TestFactory1, m.TestFactory2):
314 m.TestFactory1.__init__(self, tag.unique_ptr, 33)
315 m.TestFactory2.__init__(self, tag.move)
318 assert m.TestFactory1.value.fget(a) ==
"33" 319 assert m.TestFactory2.value.fget(a) ==
"(empty2)" 323 a = m.NoisyAlloc(*args)
330 return re.sub(
r'\s+#.*',
'', s)
334 """When the constructor is overloaded, previous overloads can require a preallocated value. 335 This test makes sure that such preallocated values only happen when they might be necessary, 336 and that they are deallocated properly""" 342 assert msg(capture) ==
""" 353 noisy new # allocation required to attempt first overload 354 noisy delete # have to dealloc before considering factory init overload 355 noisy new # pointer factory calling "new", part 1: allocation 356 NoisyAlloc(double 1.5) # ... part two, invoking constructor 358 ~NoisyAlloc() # Destructor 359 noisy delete # operator delete 365 noisy new # pointer factory calling "new", allocation 366 NoisyAlloc(int 2) # constructor 368 ~NoisyAlloc() # Destructor 369 noisy delete # operator delete 375 NoisyAlloc(double 2.5) # construction (local func variable: operator_new not called) 376 noisy new # return-by-value "new" part 1: allocation 377 ~NoisyAlloc() # moved-away local func variable destruction 379 ~NoisyAlloc() # Destructor 380 noisy delete # operator delete 386 noisy new # preallocation needed before invoking placement-new overload 387 noisy placement new # Placement new 388 NoisyAlloc(double 3.5) # construction 390 ~NoisyAlloc() # Destructor 391 noisy delete # operator delete 397 noisy new # preallocation needed before invoking placement-new overload 398 noisy delete # deallocation of preallocated storage 399 noisy new # Factory pointer allocation 400 NoisyAlloc(int 4) # factory pointer construction 402 ~NoisyAlloc() # Destructor 403 noisy delete # operator delete 409 noisy new # preallocation needed before invoking first placement new 410 noisy delete # delete before considering new-style constructor 411 noisy new # preallocation for second placement new 412 noisy placement new # Placement new in the second placement new overload 413 NoisyAlloc(int 5) # construction 415 ~NoisyAlloc() # Destructor 416 noisy delete # operator delete 420 @pytest.unsupported_on_py2
422 """Tests invocation of the pybind-registered base class with an invalid `self` argument. You 423 can only actually do this on Python 3: Python 2 raises an exception itself if you try.""" 424 class NotPybindDerived(object):
428 class BrokenTF1(m.TestFactory1):
429 def __init__(self, bad):
431 a = m.TestFactory2(tag.pointer, 1)
432 m.TestFactory1.__init__(a, tag.pointer)
434 a = NotPybindDerived()
435 m.TestFactory1.__init__(a, tag.pointer)
438 class BrokenTF6(m.TestFactory6):
439 def __init__(self, bad):
441 a = m.TestFactory2(tag.pointer, 1)
442 m.TestFactory6.__init__(a, tag.base, 1)
444 a = m.TestFactory2(tag.pointer, 1)
445 m.TestFactory6.__init__(a, tag.alias, 1)
447 m.TestFactory6.__init__(NotPybindDerived.__new__(NotPybindDerived), tag.base, 1)
449 m.TestFactory6.__init__(NotPybindDerived.__new__(NotPybindDerived), tag.alias, 1)
452 with pytest.raises(TypeError)
as excinfo:
454 assert str(excinfo.value) ==
"__init__(self, ...) called with invalid `self` argument" 456 for arg
in (1, 2, 3, 4):
457 with pytest.raises(TypeError)
as excinfo:
459 assert str(excinfo.value) ==
"__init__(self, ...) called with invalid `self` argument" static ConstructorStats & get(std::type_index type)
def create_and_destroy(args)
def test_init_factory_signature(msg)
def test_init_factory_casting()
def test_reallocations(capture, msg)
def test_multiple_inheritance()
def test_init_factory_basic()
def test_no_placement_new(capture)
def test_init_factory_alias()
def test_init_factory_dual()
void print(Args &&...args)