test_class.py
Go to the documentation of this file.
1 # -*- coding: utf-8 -*-
2 import pytest
3 
4 import env # noqa: F401
5 
6 from pybind11_tests import class_ as m
7 from pybind11_tests import UserType, ConstructorStats
8 
9 
10 def test_repr():
11  # In Python 3.3+, repr() accesses __qualname__
12  assert "pybind11_type" in repr(type(UserType))
13  assert "UserType" in repr(UserType)
14 
15 
16 def test_instance(msg):
17  with pytest.raises(TypeError) as excinfo:
18  m.NoConstructor()
19  assert msg(excinfo.value) == "m.class_.NoConstructor: No constructor defined!"
20 
21  instance = m.NoConstructor.new_instance()
22 
23  cstats = ConstructorStats.get(m.NoConstructor)
24  assert cstats.alive() == 1
25  del instance
26  assert cstats.alive() == 0
27 
28 
29 def test_type():
30  assert m.check_type(1) == m.DerivedClass1
31  with pytest.raises(RuntimeError) as execinfo:
32  m.check_type(0)
33 
34  assert 'pybind11::detail::get_type_info: unable to find type info' in str(execinfo.value)
35  assert 'Invalid' in str(execinfo.value)
36 
37  # Currently not supported
38  # See https://github.com/pybind/pybind11/issues/2486
39  # assert m.check_type(2) == int
40 
41 
43  assert m.get_type_of(1) == int
44  assert m.get_type_of(m.DerivedClass1()) == m.DerivedClass1
45  assert m.get_type_of(int) == type
46 
47 
49  # If the above test deleted the class, this will segfault
50  assert m.get_type_of(m.DerivedClass1()) == m.DerivedClass1
51 
52 
54  assert m.as_type(int) == int
55 
56  with pytest.raises(RuntimeError):
57  assert m.as_type(1) == int
58 
59  with pytest.raises(RuntimeError):
60  assert m.as_type(m.DerivedClass1()) == m.DerivedClass1
61 
62 
63 def test_docstrings(doc):
64  assert doc(UserType) == "A `py::class_` type for testing"
65  assert UserType.__name__ == "UserType"
66  assert UserType.__module__ == "pybind11_tests"
67  assert UserType.get_value.__name__ == "get_value"
68  assert UserType.get_value.__module__ == "pybind11_tests"
69 
70  assert doc(UserType.get_value) == """
71  get_value(self: m.UserType) -> int
72 
73  Get value using a method
74  """
75  assert doc(UserType.value) == "Get/set value using a property"
76 
77  assert doc(m.NoConstructor.new_instance) == """
78  new_instance() -> m.class_.NoConstructor
79 
80  Return an instance
81  """
82 
83 
84 def test_qualname(doc):
85  """Tests that a properly qualified name is set in __qualname__ (even in pre-3.3, where we
86  backport the attribute) and that generated docstrings properly use it and the module name"""
87  assert m.NestBase.__qualname__ == "NestBase"
88  assert m.NestBase.Nested.__qualname__ == "NestBase.Nested"
89 
90  assert doc(m.NestBase.__init__) == """
91  __init__(self: m.class_.NestBase) -> None
92  """
93  assert doc(m.NestBase.g) == """
94  g(self: m.class_.NestBase, arg0: m.class_.NestBase.Nested) -> None
95  """
96  assert doc(m.NestBase.Nested.__init__) == """
97  __init__(self: m.class_.NestBase.Nested) -> None
98  """
99  assert doc(m.NestBase.Nested.fn) == """
100  fn(self: m.class_.NestBase.Nested, arg0: int, arg1: m.class_.NestBase, arg2: m.class_.NestBase.Nested) -> None
101  """ # noqa: E501 line too long
102  assert doc(m.NestBase.Nested.fa) == """
103  fa(self: m.class_.NestBase.Nested, a: int, b: m.class_.NestBase, c: m.class_.NestBase.Nested) -> None
104  """ # noqa: E501 line too long
105  assert m.NestBase.__module__ == "pybind11_tests.class_"
106  assert m.NestBase.Nested.__module__ == "pybind11_tests.class_"
107 
108 
110  roger = m.Rabbit('Rabbit')
111  assert roger.name() + " is a " + roger.species() == "Rabbit is a parrot"
112  assert m.pet_name_species(roger) == "Rabbit is a parrot"
113 
114  polly = m.Pet('Polly', 'parrot')
115  assert polly.name() + " is a " + polly.species() == "Polly is a parrot"
116  assert m.pet_name_species(polly) == "Polly is a parrot"
117 
118  molly = m.Dog('Molly')
119  assert molly.name() + " is a " + molly.species() == "Molly is a dog"
120  assert m.pet_name_species(molly) == "Molly is a dog"
121 
122  fred = m.Hamster('Fred')
123  assert fred.name() + " is a " + fred.species() == "Fred is a rodent"
124 
125  assert m.dog_bark(molly) == "Woof!"
126 
127  with pytest.raises(TypeError) as excinfo:
128  m.dog_bark(polly)
129  assert msg(excinfo.value) == """
130  dog_bark(): incompatible function arguments. The following argument types are supported:
131  1. (arg0: m.class_.Dog) -> str
132 
133  Invoked with: <m.class_.Pet object at 0>
134  """
135 
136  with pytest.raises(TypeError) as excinfo:
137  m.Chimera("lion", "goat")
138  assert "No constructor defined!" in str(excinfo.value)
139 
140 
142 
143  # Single base
144  class Python(m.Pet):
145  def __init__(self):
146  pass
147  with pytest.raises(TypeError) as exc_info:
148  Python()
149  expected = ["m.class_.Pet.__init__() must be called when overriding __init__",
150  "Pet.__init__() must be called when overriding __init__"] # PyPy?
151  # TODO: fix PyPy error message wrt. tp_name/__qualname__?
152  assert msg(exc_info.value) in expected
153 
154  # Multiple bases
155  class RabbitHamster(m.Rabbit, m.Hamster):
156  def __init__(self):
157  m.Rabbit.__init__(self, "RabbitHamster")
158 
159  with pytest.raises(TypeError) as exc_info:
160  RabbitHamster()
161  expected = ["m.class_.Hamster.__init__() must be called when overriding __init__",
162  "Hamster.__init__() must be called when overriding __init__"] # PyPy
163  assert msg(exc_info.value) in expected
164 
165 
167  assert type(m.return_class_1()).__name__ == "DerivedClass1"
168  assert type(m.return_class_2()).__name__ == "DerivedClass2"
169  assert type(m.return_none()).__name__ == "NoneType"
170  # Repeat these a few times in a random order to ensure no invalid caching is applied
171  assert type(m.return_class_n(1)).__name__ == "DerivedClass1"
172  assert type(m.return_class_n(2)).__name__ == "DerivedClass2"
173  assert type(m.return_class_n(0)).__name__ == "BaseClass"
174  assert type(m.return_class_n(2)).__name__ == "DerivedClass2"
175  assert type(m.return_class_n(2)).__name__ == "DerivedClass2"
176  assert type(m.return_class_n(0)).__name__ == "BaseClass"
177  assert type(m.return_class_n(1)).__name__ == "DerivedClass1"
178 
179 
181  objects = [tuple(), dict(), m.Pet("Polly", "parrot")] + [m.Dog("Molly")] * 4
182  expected = (True, True, True, True, True, False, False)
183  assert m.check_instances(objects) == expected
184 
185 
187  import re
188 
189  with pytest.raises(RuntimeError) as excinfo:
190  m.mismatched_holder_1()
191  assert re.match('generic_type: type ".*MismatchDerived1" does not have a non-default '
192  'holder type while its base ".*MismatchBase1" does', str(excinfo.value))
193 
194  with pytest.raises(RuntimeError) as excinfo:
195  m.mismatched_holder_2()
196  assert re.match('generic_type: type ".*MismatchDerived2" has a non-default holder type '
197  'while its base ".*MismatchBase2" does not', str(excinfo.value))
198 
199 
201  """#511: problem with inheritance + overwritten def_static"""
202  b = m.MyBase.make()
203  d1 = m.MyDerived.make2()
204  d2 = m.MyDerived.make()
205 
206  assert isinstance(b, m.MyBase)
207  assert isinstance(d1, m.MyDerived)
208  assert isinstance(d2, m.MyDerived)
209 
210 
212  """Ensure the lifetime of temporary objects created for implicit conversions"""
213  assert m.implicitly_convert_argument(UserType(5)) == 5
214  assert m.implicitly_convert_variable(UserType(5)) == 5
215 
216  assert "outside a bound function" in m.implicitly_convert_variable_fail(UserType(5))
217 
218 
220  """Tests that class-specific operator new/delete functions are invoked"""
221 
222  class SubAliased(m.AliasedHasOpNewDelSize):
223  pass
224 
225  with capture:
226  a = m.HasOpNewDel()
227  b = m.HasOpNewDelSize()
228  d = m.HasOpNewDelBoth()
229  assert capture == """
230  A new 8
231  B new 4
232  D new 32
233  """
234  sz_alias = str(m.AliasedHasOpNewDelSize.size_alias)
235  sz_noalias = str(m.AliasedHasOpNewDelSize.size_noalias)
236  with capture:
237  c = m.AliasedHasOpNewDelSize()
238  c2 = SubAliased()
239  assert capture == (
240  "C new " + sz_noalias + "\n" +
241  "C new " + sz_alias + "\n"
242  )
243 
244  with capture:
245  del a
246  pytest.gc_collect()
247  del b
248  pytest.gc_collect()
249  del d
250  pytest.gc_collect()
251  assert capture == """
252  A delete
253  B delete 4
254  D delete
255  """
256 
257  with capture:
258  del c
259  pytest.gc_collect()
260  del c2
261  pytest.gc_collect()
262  assert capture == (
263  "C delete " + sz_noalias + "\n" +
264  "C delete " + sz_alias + "\n"
265  )
266 
267 
269  """Expose protected member functions to Python using a helper class"""
270  a = m.ProtectedA()
271  assert a.foo() == 42
272 
273  b = m.ProtectedB()
274  assert b.foo() == 42
275 
276  class C(m.ProtectedB):
277  def __init__(self):
278  m.ProtectedB.__init__(self)
279 
280  def foo(self):
281  return 0
282 
283  c = C()
284  assert c.foo() == 0
285 
286 
288  """ Tests that simple POD classes can be constructed using C++11 brace initialization """
289  a = m.BraceInitialization(123, "test")
290  assert a.field1 == 123
291  assert a.field2 == "test"
292 
293  # Tests that a non-simple class doesn't get brace initialization (if the
294  # class defines an initializer_list constructor, in particular, it would
295  # win over the expected constructor).
296  b = m.NoBraceInitialization([123, 456])
297  assert b.vec == [123, 456]
298 
299 
300 @pytest.mark.xfail("env.PYPY")
302  """Instances must correctly increase/decrease the reference count of their types (#1029)"""
303  from sys import getrefcount
304 
305  class PyDog(m.Dog):
306  pass
307 
308  for cls in m.Dog, PyDog:
309  refcount_1 = getrefcount(cls)
310  molly = [cls("Molly") for _ in range(10)]
311  refcount_2 = getrefcount(cls)
312 
313  del molly
314  pytest.gc_collect()
315  refcount_3 = getrefcount(cls)
316 
317  assert refcount_1 == refcount_3
318  assert refcount_2 > refcount_1
319 
320 
322  # ensure that there is no runaway reentrant implicit conversion (#1035)
323  with pytest.raises(TypeError) as excinfo:
324  m.BogusImplicitConversion(0)
325  assert msg(excinfo.value) == '''
326  __init__(): incompatible constructor arguments. The following argument types are supported:
327  1. m.class_.BogusImplicitConversion(arg0: m.class_.BogusImplicitConversion)
328 
329  Invoked with: 0
330  '''
331 
332 
334  with pytest.raises(TypeError) as exc_info:
335  m.test_error_after_conversions("hello")
336  assert str(exc_info.value).startswith(
337  "Unable to convert function return value to a Python type!")
338 
339 
341  if hasattr(m, "Aligned"):
342  p = m.Aligned().ptr()
343  assert p % 1024 == 0
344 
345 
346 # https://foss.heptapod.net/pypy/pypy/-/issues/2742
347 @pytest.mark.xfail("env.PYPY")
349  with pytest.raises(TypeError) as exc_info:
350  class PyFinalChild(m.IsFinal):
351  pass
352  assert str(exc_info.value).endswith("is not an acceptable base type")
353 
354 
355 # https://foss.heptapod.net/pypy/pypy/-/issues/2742
356 @pytest.mark.xfail("env.PYPY")
358  with pytest.raises(TypeError) as exc_info:
359  class PyNonFinalFinalChild(m.IsNonFinalFinal):
360  pass
361  assert str(exc_info.value).endswith("is not an acceptable base type")
362 
363 
364 # https://github.com/pybind/pybind11/issues/1878
366  with pytest.raises(RuntimeError):
367  m.PyPrintDestructor().throw_something()
def test_brace_initialization()
Definition: test_class.py:287
def test_type_of_py()
Definition: test_class.py:42
bool hasattr(handle obj, handle name)
Definition: pytypes.h:403
def test_inheritance(msg)
Definition: test_class.py:109
def test_repr()
Definition: test_class.py:10
Annotation for documentation.
Definition: attr.h:33
def test_qualname(doc)
Definition: test_class.py:84
bool isinstance(handle obj)
Definition: pytypes.h:384
def test_automatic_upcasting()
Definition: test_class.py:166
def test_type_of_py_nodelete()
Definition: test_class.py:48
def test_final()
Definition: test_class.py:348
void foo(CV_QUALIFIER Matrix3d &m)
def test_operator_new_delete(capture)
Definition: test_class.py:219
static ConstructorStats & get(std::type_index type)
Definition: pytypes.h:928
float * ptr
def test_reentrant_implicit_conversion_failure(msg)
Definition: test_class.py:321
def test_exception_rvalue_abort()
Definition: test_class.py:365
def test_type()
Definition: test_class.py:29
def test_non_final_final()
Definition: test_class.py:357
def test_isinstance()
Definition: test_class.py:180
def test_docstrings(doc)
Definition: test_class.py:63
def test_inheritance_init(msg)
Definition: test_class.py:141
def test_aligned()
Definition: test_class.py:340
def test_mismatched_holder()
Definition: test_class.py:186
def test_class_refcount()
Definition: test_class.py:301
def test_bind_protected_functions()
Definition: test_class.py:268
Definition: pytypes.h:1255
str repr(handle h)
Definition: pytypes.h:1536
def test_implicit_conversion_life_support()
Definition: test_class.py:211
def test_override_static()
Definition: test_class.py:200
def test_as_type_py()
Definition: test_class.py:53
Definition: pytypes.h:897
def test_error_after_conversions()
Definition: test_class.py:333
def test_instance(msg)
Definition: test_class.py:16


gtsam
Author(s):
autogenerated on Sat May 8 2021 02:46:03