Scarab  2.8.1
Project 8 C++ Utility Library
test_class.py
Go to the documentation of this file.
1 import pytest
2 
3 from pybind11_tests import class_ as m
4 from pybind11_tests import UserType, ConstructorStats
5 
6 
7 def test_repr():
8  # In Python 3.3+, repr() accesses __qualname__
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 
26 def test_docstrings(doc):
27  assert doc(UserType) == "A `py::class_` type for testing"
28  assert UserType.__name__ == "UserType"
29  assert UserType.__module__ == "pybind11_tests"
30  assert UserType.get_value.__name__ == "get_value"
31  assert UserType.get_value.__module__ == "pybind11_tests"
32 
33  assert doc(UserType.get_value) == """
34  get_value(self: m.UserType) -> int
35 
36  Get value using a method
37  """
38  assert doc(UserType.value) == "Get/set value using a property"
39 
40  assert doc(m.NoConstructor.new_instance) == """
41  new_instance() -> m.class_.NoConstructor
42 
43  Return an instance
44  """
45 
46 
47 def test_qualname(doc):
48  """Tests that a properly qualified name is set in __qualname__ (even in pre-3.3, where we
49  backport the attribute) and that generated docstrings properly use it and the module name"""
50  assert m.NestBase.__qualname__ == "NestBase"
51  assert m.NestBase.Nested.__qualname__ == "NestBase.Nested"
52 
53  assert doc(m.NestBase.__init__) == """
54  __init__(self: m.class_.NestBase) -> None
55  """
56  assert doc(m.NestBase.g) == """
57  g(self: m.class_.NestBase, arg0: m.class_.NestBase.Nested) -> None
58  """
59  assert doc(m.NestBase.Nested.__init__) == """
60  __init__(self: m.class_.NestBase.Nested) -> None
61  """
62  assert doc(m.NestBase.Nested.fn) == """
63  fn(self: m.class_.NestBase.Nested, arg0: int, arg1: m.class_.NestBase, arg2: m.class_.NestBase.Nested) -> None
64  """ # noqa: E501 line too long
65  assert doc(m.NestBase.Nested.fa) == """
66  fa(self: m.class_.NestBase.Nested, a: int, b: m.class_.NestBase, c: m.class_.NestBase.Nested) -> None
67  """ # noqa: E501 line too long
68  assert m.NestBase.__module__ == "pybind11_tests.class_"
69  assert m.NestBase.Nested.__module__ == "pybind11_tests.class_"
70 
71 
73  roger = m.Rabbit('Rabbit')
74  assert roger.name() + " is a " + roger.species() == "Rabbit is a parrot"
75  assert m.pet_name_species(roger) == "Rabbit is a parrot"
76 
77  polly = m.Pet('Polly', 'parrot')
78  assert polly.name() + " is a " + polly.species() == "Polly is a parrot"
79  assert m.pet_name_species(polly) == "Polly is a parrot"
80 
81  molly = m.Dog('Molly')
82  assert molly.name() + " is a " + molly.species() == "Molly is a dog"
83  assert m.pet_name_species(molly) == "Molly is a dog"
84 
85  fred = m.Hamster('Fred')
86  assert fred.name() + " is a " + fred.species() == "Fred is a rodent"
87 
88  assert m.dog_bark(molly) == "Woof!"
89 
90  with pytest.raises(TypeError) as excinfo:
91  m.dog_bark(polly)
92  assert msg(excinfo.value) == """
93  dog_bark(): incompatible function arguments. The following argument types are supported:
94  1. (arg0: m.class_.Dog) -> str
95 
96  Invoked with: <m.class_.Pet object at 0>
97  """
98 
99  with pytest.raises(TypeError) as excinfo:
100  m.Chimera("lion", "goat")
101  assert "No constructor defined!" in str(excinfo.value)
102 
103 
105  assert type(m.return_class_1()).__name__ == "DerivedClass1"
106  assert type(m.return_class_2()).__name__ == "DerivedClass2"
107  assert type(m.return_none()).__name__ == "NoneType"
108  # Repeat these a few times in a random order to ensure no invalid caching is applied
109  assert type(m.return_class_n(1)).__name__ == "DerivedClass1"
110  assert type(m.return_class_n(2)).__name__ == "DerivedClass2"
111  assert type(m.return_class_n(0)).__name__ == "BaseClass"
112  assert type(m.return_class_n(2)).__name__ == "DerivedClass2"
113  assert type(m.return_class_n(2)).__name__ == "DerivedClass2"
114  assert type(m.return_class_n(0)).__name__ == "BaseClass"
115  assert type(m.return_class_n(1)).__name__ == "DerivedClass1"
116 
117 
119  objects = [tuple(), dict(), m.Pet("Polly", "parrot")] + [m.Dog("Molly")] * 4
120  expected = (True, True, True, True, True, False, False)
121  assert m.check_instances(objects) == expected
122 
123 
125  import re
126 
127  with pytest.raises(RuntimeError) as excinfo:
128  m.mismatched_holder_1()
129  assert re.match('generic_type: type ".*MismatchDerived1" does not have a non-default '
130  'holder type while its base ".*MismatchBase1" does', str(excinfo.value))
131 
132  with pytest.raises(RuntimeError) as excinfo:
133  m.mismatched_holder_2()
134  assert re.match('generic_type: type ".*MismatchDerived2" has a non-default holder type '
135  'while its base ".*MismatchBase2" does not', str(excinfo.value))
136 
137 
139  """#511: problem with inheritance + overwritten def_static"""
140  b = m.MyBase.make()
141  d1 = m.MyDerived.make2()
142  d2 = m.MyDerived.make()
143 
144  assert isinstance(b, m.MyBase)
145  assert isinstance(d1, m.MyDerived)
146  assert isinstance(d2, m.MyDerived)
147 
148 
150  """Ensure the lifetime of temporary objects created for implicit conversions"""
151  assert m.implicitly_convert_argument(UserType(5)) == 5
152  assert m.implicitly_convert_variable(UserType(5)) == 5
153 
154  assert "outside a bound function" in m.implicitly_convert_variable_fail(UserType(5))
155 
156 
158  """Tests that class-specific operator new/delete functions are invoked"""
159 
160  class SubAliased(m.AliasedHasOpNewDelSize):
161  pass
162 
163  with capture:
164  a = m.HasOpNewDel()
165  b = m.HasOpNewDelSize()
166  d = m.HasOpNewDelBoth()
167  assert capture == """
168  A new 8
169  B new 4
170  D new 32
171  """
172  sz_alias = str(m.AliasedHasOpNewDelSize.size_alias)
173  sz_noalias = str(m.AliasedHasOpNewDelSize.size_noalias)
174  with capture:
175  c = m.AliasedHasOpNewDelSize()
176  c2 = SubAliased()
177  assert capture == (
178  "C new " + sz_noalias + "\n" +
179  "C new " + sz_alias + "\n"
180  )
181 
182  with capture:
183  del a
184  pytest.gc_collect()
185  del b
186  pytest.gc_collect()
187  del d
188  pytest.gc_collect()
189  assert capture == """
190  A delete
191  B delete 4
192  D delete
193  """
194 
195  with capture:
196  del c
197  pytest.gc_collect()
198  del c2
199  pytest.gc_collect()
200  assert capture == (
201  "C delete " + sz_noalias + "\n" +
202  "C delete " + sz_alias + "\n"
203  )
204 
205 
207  """Expose protected member functions to Python using a helper class"""
208  a = m.ProtectedA()
209  assert a.foo() == 42
210 
211  b = m.ProtectedB()
212  assert b.foo() == 42
213 
214  class C(m.ProtectedB):
215  def __init__(self):
216  m.ProtectedB.__init__(self)
217 
218  def foo(self):
219  return 0
220 
221  c = C()
222  assert c.foo() == 0
223 
224 
226  """ Tests that simple POD classes can be constructed using C++11 brace initialization """
227  a = m.BraceInitialization(123, "test")
228  assert a.field1 == 123
229  assert a.field2 == "test"
230 
231  # Tests that a non-simple class doesn't get brace initialization (if the
232  # class defines an initializer_list constructor, in particular, it would
233  # win over the expected constructor).
234  b = m.NoBraceInitialization([123, 456])
235  assert b.vec == [123, 456]
236 
237 
238 @pytest.unsupported_on_pypy
240  """Instances must correctly increase/decrease the reference count of their types (#1029)"""
241  from sys import getrefcount
242 
243  class PyDog(m.Dog):
244  pass
245 
246  for cls in m.Dog, PyDog:
247  refcount_1 = getrefcount(cls)
248  molly = [cls("Molly") for _ in range(10)]
249  refcount_2 = getrefcount(cls)
250 
251  del molly
252  pytest.gc_collect()
253  refcount_3 = getrefcount(cls)
254 
255  assert refcount_1 == refcount_3
256  assert refcount_2 > refcount_1
257 
258 
260  # ensure that there is no runaway reentrant implicit conversion (#1035)
261  with pytest.raises(TypeError) as excinfo:
262  m.BogusImplicitConversion(0)
263  assert msg(excinfo.value) == '''
264  __init__(): incompatible constructor arguments. The following argument types are supported:
265  1. m.class_.BogusImplicitConversion(arg0: m.class_.BogusImplicitConversion)
266 
267  Invoked with: 0
268  '''
269 
270 
272  with pytest.raises(TypeError) as exc_info:
273  m.test_error_after_conversions("hello")
274  assert str(exc_info.value).startswith(
275  "Unable to convert function return value to a Python type!")
276 
277 
279  if hasattr(m, "Aligned"):
280  p = m.Aligned().ptr()
281  assert p % 1024 == 0
def test_brace_initialization()
Definition: test_class.py:225
static ConstructorStats & get(std::type_index type)
def test_inheritance(msg)
Definition: test_class.py:72
def test_repr()
Definition: test_class.py:7
def test_qualname(doc)
Definition: test_class.py:47
def msg()
Definition: conftest.py:165
def test_automatic_upcasting()
Definition: test_class.py:104
def test_operator_new_delete(capture)
Definition: test_class.py:157
return isinstance(obj, type)
def test_reentrant_implicit_conversion_failure(msg)
Definition: test_class.py:259
def test_isinstance()
Definition: test_class.py:118
def test_docstrings(doc)
Definition: test_class.py:26
str repr(handle h)
Definition: pytypes.h:1383
def test_aligned()
Definition: test_class.py:278
def doc()
Definition: conftest.py:152
def test_mismatched_holder()
Definition: test_class.py:124
const detail::type_info * type
Definition: cast.h:453
return os str()
def test_class_refcount()
Definition: test_class.py:239
def test_bind_protected_functions()
Definition: test_class.py:206
def test_implicit_conversion_life_support()
Definition: test_class.py:149
def test_override_static()
Definition: test_class.py:138
auto range
Definition: cast.h:455
bool hasattr(handle obj, handle name)
Definition: pytypes.h:387
def test_error_after_conversions()
Definition: test_class.py:271
def test_instance(msg)
Definition: test_class.py:13