test_class.py
Go to the documentation of this file.
1 import pytest
2 
3 import env # noqa: F401
4 from pybind11_tests import ConstructorStats, UserType
5 from pybind11_tests import class_ as m
6 
7 
8 def test_repr():
9  assert "pybind11_type" in repr(type(UserType))
10  assert "UserType" in repr(UserType)
11 
12 
13 def test_instance(msg):
14  with pytest.raises(TypeError) as excinfo:
15  m.NoConstructor()
16  assert msg(excinfo.value) == "m.class_.NoConstructor: No constructor defined!"
17 
18  instance = m.NoConstructor.new_instance()
19 
20  cstats = ConstructorStats.get(m.NoConstructor)
21  assert cstats.alive() == 1
22  del instance
23  assert cstats.alive() == 0
24 
25 
27  instance = m.NoConstructorNew() # .__new__(m.NoConstructor.__class__)
28  cstats = ConstructorStats.get(m.NoConstructorNew)
29  assert cstats.alive() == 1
30  del instance
31  assert cstats.alive() == 0
32 
33 
34 def test_type():
35  assert m.check_type(1) == m.DerivedClass1
36  with pytest.raises(RuntimeError) as execinfo:
37  m.check_type(0)
38 
39  assert "pybind11::detail::get_type_info: unable to find type info" in str(
40  execinfo.value
41  )
42  assert "Invalid" in str(execinfo.value)
43 
44  # Currently not supported
45  # See https://github.com/pybind/pybind11/issues/2486
46  # assert m.check_type(2) == int
47 
48 
50  assert m.get_type_of(1) == int
51  assert m.get_type_of(m.DerivedClass1()) == m.DerivedClass1
52  assert m.get_type_of(int) == type
53 
54 
56  assert m.get_type_classic(1) == int
57  assert m.get_type_classic(m.DerivedClass1()) == m.DerivedClass1
58  assert m.get_type_classic(int) == type
59 
60 
62  # If the above test deleted the class, this will segfault
63  assert m.get_type_of(m.DerivedClass1()) == m.DerivedClass1
64 
65 
67  assert m.as_type(int) == int
68 
69  with pytest.raises(TypeError):
70  assert m.as_type(1) == int
71 
72  with pytest.raises(TypeError):
73  assert m.as_type(m.DerivedClass1()) == m.DerivedClass1
74 
75 
76 def test_docstrings(doc):
77  assert doc(UserType) == "A `py::class_` type for testing"
78  assert UserType.__name__ == "UserType"
79  assert UserType.__module__ == "pybind11_tests"
80  assert UserType.get_value.__name__ == "get_value"
81  assert UserType.get_value.__module__ == "pybind11_tests"
82 
83  assert (
84  doc(UserType.get_value)
85  == """
86  get_value(self: m.UserType) -> int
87 
88  Get value using a method
89  """
90  )
91  assert doc(UserType.value) == "Get/set value using a property"
92 
93  assert (
94  doc(m.NoConstructor.new_instance)
95  == """
96  new_instance() -> m.class_.NoConstructor
97 
98  Return an instance
99  """
100  )
101 
102 
103 def test_qualname(doc):
104  """Tests that a properly qualified name is set in __qualname__ and that
105  generated docstrings properly use it and the module name"""
106  assert m.NestBase.__qualname__ == "NestBase"
107  assert m.NestBase.Nested.__qualname__ == "NestBase.Nested"
108 
109  assert (
110  doc(m.NestBase.__init__)
111  == """
112  __init__(self: m.class_.NestBase) -> None
113  """
114  )
115  assert (
116  doc(m.NestBase.g)
117  == """
118  g(self: m.class_.NestBase, arg0: m.class_.NestBase.Nested) -> None
119  """
120  )
121  assert (
122  doc(m.NestBase.Nested.__init__)
123  == """
124  __init__(self: m.class_.NestBase.Nested) -> None
125  """
126  )
127  assert (
128  doc(m.NestBase.Nested.fn)
129  == """
130  fn(self: m.class_.NestBase.Nested, arg0: int, arg1: m.class_.NestBase, arg2: m.class_.NestBase.Nested) -> None
131  """
132  )
133  assert (
134  doc(m.NestBase.Nested.fa)
135  == """
136  fa(self: m.class_.NestBase.Nested, a: int, b: m.class_.NestBase, c: m.class_.NestBase.Nested) -> None
137  """
138  )
139  assert m.NestBase.__module__ == "pybind11_tests.class_"
140  assert m.NestBase.Nested.__module__ == "pybind11_tests.class_"
141 
142 
144  roger = m.Rabbit("Rabbit")
145  assert roger.name() + " is a " + roger.species() == "Rabbit is a parrot"
146  assert m.pet_name_species(roger) == "Rabbit is a parrot"
147 
148  polly = m.Pet("Polly", "parrot")
149  assert polly.name() + " is a " + polly.species() == "Polly is a parrot"
150  assert m.pet_name_species(polly) == "Polly is a parrot"
151 
152  molly = m.Dog("Molly")
153  assert molly.name() + " is a " + molly.species() == "Molly is a dog"
154  assert m.pet_name_species(molly) == "Molly is a dog"
155 
156  fred = m.Hamster("Fred")
157  assert fred.name() + " is a " + fred.species() == "Fred is a rodent"
158 
159  assert m.dog_bark(molly) == "Woof!"
160 
161  with pytest.raises(TypeError) as excinfo:
162  m.dog_bark(polly)
163  assert (
164  msg(excinfo.value)
165  == """
166  dog_bark(): incompatible function arguments. The following argument types are supported:
167  1. (arg0: m.class_.Dog) -> str
168 
169  Invoked with: <m.class_.Pet object at 0>
170  """
171  )
172 
173  with pytest.raises(TypeError) as excinfo:
174  m.Chimera("lion", "goat")
175  assert "No constructor defined!" in str(excinfo.value)
176 
177 
179 
180  # Single base
181  class Python(m.Pet):
182  def __init__(self):
183  pass
184 
185  with pytest.raises(TypeError) as exc_info:
186  Python()
187  expected = "m.class_.Pet.__init__() must be called when overriding __init__"
188  assert msg(exc_info.value) == expected
189 
190  # Multiple bases
191  class RabbitHamster(m.Rabbit, m.Hamster):
192  def __init__(self):
193  m.Rabbit.__init__(self, "RabbitHamster")
194 
195  with pytest.raises(TypeError) as exc_info:
196  RabbitHamster()
197  expected = "m.class_.Hamster.__init__() must be called when overriding __init__"
198  assert msg(exc_info.value) == expected
199 
200 
202  assert type(m.return_class_1()).__name__ == "DerivedClass1"
203  assert type(m.return_class_2()).__name__ == "DerivedClass2"
204  assert type(m.return_none()).__name__ == "NoneType"
205  # Repeat these a few times in a random order to ensure no invalid caching is applied
206  assert type(m.return_class_n(1)).__name__ == "DerivedClass1"
207  assert type(m.return_class_n(2)).__name__ == "DerivedClass2"
208  assert type(m.return_class_n(0)).__name__ == "BaseClass"
209  assert type(m.return_class_n(2)).__name__ == "DerivedClass2"
210  assert type(m.return_class_n(2)).__name__ == "DerivedClass2"
211  assert type(m.return_class_n(0)).__name__ == "BaseClass"
212  assert type(m.return_class_n(1)).__name__ == "DerivedClass1"
213 
214 
216  objects = [tuple(), dict(), m.Pet("Polly", "parrot")] + [m.Dog("Molly")] * 4
217  expected = (True, True, True, True, True, False, False)
218  assert m.check_instances(objects) == expected
219 
220 
222  import re
223 
224  with pytest.raises(RuntimeError) as excinfo:
225  m.mismatched_holder_1()
226  assert re.match(
227  'generic_type: type ".*MismatchDerived1" does not have a non-default '
228  'holder type while its base ".*MismatchBase1" does',
229  str(excinfo.value),
230  )
231 
232  with pytest.raises(RuntimeError) as excinfo:
233  m.mismatched_holder_2()
234  assert re.match(
235  'generic_type: type ".*MismatchDerived2" has a non-default holder type '
236  'while its base ".*MismatchBase2" does not',
237  str(excinfo.value),
238  )
239 
240 
242  """#511: problem with inheritance + overwritten def_static"""
243  b = m.MyBase.make()
244  d1 = m.MyDerived.make2()
245  d2 = m.MyDerived.make()
246 
247  assert isinstance(b, m.MyBase)
248  assert isinstance(d1, m.MyDerived)
249  assert isinstance(d2, m.MyDerived)
250 
251 
253  """Ensure the lifetime of temporary objects created for implicit conversions"""
254  assert m.implicitly_convert_argument(UserType(5)) == 5
255  assert m.implicitly_convert_variable(UserType(5)) == 5
256 
257  assert "outside a bound function" in m.implicitly_convert_variable_fail(UserType(5))
258 
259 
261  """Tests that class-specific operator new/delete functions are invoked"""
262 
263  class SubAliased(m.AliasedHasOpNewDelSize):
264  pass
265 
266  with capture:
267  a = m.HasOpNewDel()
268  b = m.HasOpNewDelSize()
269  d = m.HasOpNewDelBoth()
270  assert (
271  capture
272  == """
273  A new 8
274  B new 4
275  D new 32
276  """
277  )
278  sz_alias = str(m.AliasedHasOpNewDelSize.size_alias)
279  sz_noalias = str(m.AliasedHasOpNewDelSize.size_noalias)
280  with capture:
281  c = m.AliasedHasOpNewDelSize()
282  c2 = SubAliased()
283  assert capture == ("C new " + sz_noalias + "\n" + "C new " + sz_alias + "\n")
284 
285  with capture:
286  del a
287  pytest.gc_collect()
288  del b
289  pytest.gc_collect()
290  del d
291  pytest.gc_collect()
292  assert (
293  capture
294  == """
295  A delete
296  B delete 4
297  D delete
298  """
299  )
300 
301  with capture:
302  del c
303  pytest.gc_collect()
304  del c2
305  pytest.gc_collect()
306  assert capture == ("C delete " + sz_noalias + "\n" + "C delete " + sz_alias + "\n")
307 
308 
310  """Expose protected member functions to Python using a helper class"""
311  a = m.ProtectedA()
312  assert a.foo() == 42
313 
314  b = m.ProtectedB()
315  assert b.foo() == 42
316 
317  class C(m.ProtectedB):
318  def __init__(self):
319  m.ProtectedB.__init__(self)
320 
321  def foo(self):
322  return 0
323 
324  c = C()
325  assert c.foo() == 0
326 
327 
329  """Tests that simple POD classes can be constructed using C++11 brace initialization"""
330  a = m.BraceInitialization(123, "test")
331  assert a.field1 == 123
332  assert a.field2 == "test"
333 
334  # Tests that a non-simple class doesn't get brace initialization (if the
335  # class defines an initializer_list constructor, in particular, it would
336  # win over the expected constructor).
337  b = m.NoBraceInitialization([123, 456])
338  assert b.vec == [123, 456]
339 
340 
341 @pytest.mark.xfail("env.PYPY")
343  """Instances must correctly increase/decrease the reference count of their types (#1029)"""
344  from sys import getrefcount
345 
346  class PyDog(m.Dog):
347  pass
348 
349  for cls in m.Dog, PyDog:
350  refcount_1 = getrefcount(cls)
351  molly = [cls("Molly") for _ in range(10)]
352  refcount_2 = getrefcount(cls)
353 
354  del molly
355  pytest.gc_collect()
356  refcount_3 = getrefcount(cls)
357 
358  assert refcount_1 == refcount_3
359  assert refcount_2 > refcount_1
360 
361 
363  # ensure that there is no runaway reentrant implicit conversion (#1035)
364  with pytest.raises(TypeError) as excinfo:
365  m.BogusImplicitConversion(0)
366  assert (
367  msg(excinfo.value)
368  == """
369  __init__(): incompatible constructor arguments. The following argument types are supported:
370  1. m.class_.BogusImplicitConversion(arg0: m.class_.BogusImplicitConversion)
371 
372  Invoked with: 0
373  """
374  )
375 
376 
378  with pytest.raises(TypeError) as exc_info:
379  m.test_error_after_conversions("hello")
380  assert str(exc_info.value).startswith(
381  "Unable to convert function return value to a Python type!"
382  )
383 
384 
386  if hasattr(m, "Aligned"):
387  p = m.Aligned().ptr()
388  assert p % 1024 == 0
389 
390 
391 # https://foss.heptapod.net/pypy/pypy/-/issues/2742
392 @pytest.mark.xfail("env.PYPY")
394  with pytest.raises(TypeError) as exc_info:
395 
396  class PyFinalChild(m.IsFinal):
397  pass
398 
399  assert str(exc_info.value).endswith("is not an acceptable base type")
400 
401 
402 # https://foss.heptapod.net/pypy/pypy/-/issues/2742
403 @pytest.mark.xfail("env.PYPY")
405  with pytest.raises(TypeError) as exc_info:
406 
407  class PyNonFinalFinalChild(m.IsNonFinalFinal):
408  pass
409 
410  assert str(exc_info.value).endswith("is not an acceptable base type")
411 
412 
413 # https://github.com/pybind/pybind11/issues/1878
415  with pytest.raises(RuntimeError):
416  m.PyPrintDestructor().throw_something()
417 
418 
419 # https://github.com/pybind/pybind11/issues/1568
421  n = 100
422  instances = [m.SamePointer() for _ in range(n)]
423  for i in range(n):
424  # We need to reuse the same allocated memory for with a different type,
425  # to ensure the bug in `deregister_instance_impl` is detected. Otherwise
426  # `Py_TYPE(self) == Py_TYPE(it->second)` will still succeed, even though
427  # the `instance` is already deleted.
428  instances[i] = m.Empty()
429  # No assert: if this does not trigger the error
430  # pybind11_fail("pybind11_object_dealloc(): Tried to deallocate unregistered instance!");
431  # and just completes without crashing, we're good.
432 
433 
434 # https://github.com/pybind/pybind11/issues/1624
436  assert issubclass(m.DerivedWithNested, m.BaseWithNested)
437  assert m.BaseWithNested.Nested != m.DerivedWithNested.Nested
438  assert m.BaseWithNested.Nested.get_name() == "BaseWithNested::Nested"
439  assert m.DerivedWithNested.Nested.get_name() == "DerivedWithNested::Nested"
440 
441 
443  import types
444 
445  module_scope = types.ModuleType("module_scope")
446  with pytest.raises(RuntimeError) as exc_info:
447  m.register_duplicate_class_name(module_scope)
448  expected = (
449  'generic_type: cannot initialize type "Duplicate": '
450  "an object with that name is already defined"
451  )
452  assert str(exc_info.value) == expected
453  with pytest.raises(RuntimeError) as exc_info:
454  m.register_duplicate_class_type(module_scope)
455  expected = 'generic_type: type "YetAnotherDuplicate" is already registered!'
456  assert str(exc_info.value) == expected
457 
458  class ClassScope:
459  pass
460 
461  with pytest.raises(RuntimeError) as exc_info:
462  m.register_duplicate_nested_class_name(ClassScope)
463  expected = (
464  'generic_type: cannot initialize type "DuplicateNested": '
465  "an object with that name is already defined"
466  )
467  assert str(exc_info.value) == expected
468  with pytest.raises(RuntimeError) as exc_info:
469  m.register_duplicate_nested_class_type(ClassScope)
470  expected = 'generic_type: type "YetAnotherDuplicateNested" is already registered!'
471  assert str(exc_info.value) == expected
def test_brace_initialization()
Definition: test_class.py:328
def test_type_of_py()
Definition: test_class.py:49
bool hasattr(handle obj, handle name)
Definition: pytypes.h:728
def test_inheritance(msg)
Definition: test_class.py:143
def test_repr()
Definition: test_class.py:8
Annotation for documentation.
Definition: attr.h:42
def test_qualname(doc)
Definition: test_class.py:103
bool isinstance(handle obj)
Definition: pytypes.h:700
def test_automatic_upcasting()
Definition: test_class.py:201
def test_multiple_instances_with_same_pointer(capture)
Definition: test_class.py:420
def test_type_of_py_nodelete()
Definition: test_class.py:61
def test_final()
Definition: test_class.py:393
def test_type_of_classic()
Definition: test_class.py:55
void foo(CV_QUALIFIER Matrix3d &m)
def test_operator_new_delete(capture)
Definition: test_class.py:260
def test_register_duplicate_class()
Definition: test_class.py:442
static ConstructorStats & get(std::type_index type)
Definition: pytypes.h:1403
def test_reentrant_implicit_conversion_failure(msg)
Definition: test_class.py:362
def test_exception_rvalue_abort()
Definition: test_class.py:414
def test_type()
Definition: test_class.py:34
def test_non_final_final()
Definition: test_class.py:404
def test_isinstance()
Definition: test_class.py:215
def test_docstrings(doc)
Definition: test_class.py:76
Matrix< Scalar, Dynamic, Dynamic > C
Definition: bench_gemm.cpp:50
def test_inheritance_init(msg)
Definition: test_class.py:178
def test_aligned()
Definition: test_class.py:385
def test_instance_new(msg)
Definition: test_class.py:26
def test_mismatched_holder()
Definition: test_class.py:221
Double_ range(const Point2_ &p, const Point2_ &q)
def test_class_refcount()
Definition: test_class.py:342
def test_base_and_derived_nested_scope()
Definition: test_class.py:435
def test_bind_protected_functions()
Definition: test_class.py:309
Definition: pytypes.h:1924
str repr(handle h)
Definition: pytypes.h:2265
def test_implicit_conversion_life_support()
Definition: test_class.py:252
def test_override_static()
Definition: test_class.py:241
def test_as_type_py()
Definition: test_class.py:66
Definition: pytypes.h:1370
def test_error_after_conversions()
Definition: test_class.py:377
def test_instance(msg)
Definition: test_class.py:13


gtsam
Author(s):
autogenerated on Tue Jul 4 2023 02:37:45