You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

459 lines
16 KiB

8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
  1. import pytest
  2. from pybind11_tests import ExampleMandA, ConstructorStats
  3. def test_methods_and_attributes():
  4. instance1 = ExampleMandA()
  5. instance2 = ExampleMandA(32)
  6. instance1.add1(instance2)
  7. instance1.add2(instance2)
  8. instance1.add3(instance2)
  9. instance1.add4(instance2)
  10. instance1.add5(instance2)
  11. instance1.add6(32)
  12. instance1.add7(32)
  13. instance1.add8(32)
  14. instance1.add9(32)
  15. instance1.add10(32)
  16. assert str(instance1) == "ExampleMandA[value=320]"
  17. assert str(instance2) == "ExampleMandA[value=32]"
  18. assert str(instance1.self1()) == "ExampleMandA[value=320]"
  19. assert str(instance1.self2()) == "ExampleMandA[value=320]"
  20. assert str(instance1.self3()) == "ExampleMandA[value=320]"
  21. assert str(instance1.self4()) == "ExampleMandA[value=320]"
  22. assert str(instance1.self5()) == "ExampleMandA[value=320]"
  23. assert instance1.internal1() == 320
  24. assert instance1.internal2() == 320
  25. assert instance1.internal3() == 320
  26. assert instance1.internal4() == 320
  27. assert instance1.internal5() == 320
  28. assert instance1.overloaded(1, 1.0) == "(int, float)"
  29. assert instance1.overloaded(2.0, 2) == "(float, int)"
  30. assert instance1.overloaded(3, 3) == "(int, int)"
  31. assert instance1.overloaded(4., 4.) == "(float, float)"
  32. assert instance1.overloaded_const(5, 5.0) == "(int, float) const"
  33. assert instance1.overloaded_const(6.0, 6) == "(float, int) const"
  34. assert instance1.overloaded_const(7, 7) == "(int, int) const"
  35. assert instance1.overloaded_const(8., 8.) == "(float, float) const"
  36. assert instance1.overloaded_float(1, 1) == "(float, float)"
  37. assert instance1.overloaded_float(1, 1.) == "(float, float)"
  38. assert instance1.overloaded_float(1., 1) == "(float, float)"
  39. assert instance1.overloaded_float(1., 1.) == "(float, float)"
  40. assert instance1.value == 320
  41. instance1.value = 100
  42. assert str(instance1) == "ExampleMandA[value=100]"
  43. cstats = ConstructorStats.get(ExampleMandA)
  44. assert cstats.alive() == 2
  45. del instance1, instance2
  46. assert cstats.alive() == 0
  47. assert cstats.values() == ["32"]
  48. assert cstats.default_constructions == 1
  49. assert cstats.copy_constructions == 3
  50. assert cstats.move_constructions >= 1
  51. assert cstats.copy_assignments == 0
  52. assert cstats.move_assignments == 0
  53. def test_properties():
  54. from pybind11_tests import TestProperties
  55. instance = TestProperties()
  56. assert instance.def_readonly == 1
  57. with pytest.raises(AttributeError):
  58. instance.def_readonly = 2
  59. instance.def_readwrite = 2
  60. assert instance.def_readwrite == 2
  61. assert instance.def_property_readonly == 2
  62. with pytest.raises(AttributeError):
  63. instance.def_property_readonly = 3
  64. instance.def_property = 3
  65. assert instance.def_property == 3
  66. def test_copy_method():
  67. """Issue #443: calling copied methods fails in Python 3"""
  68. from pybind11_tests import ExampleMandA
  69. ExampleMandA.add2c = ExampleMandA.add2
  70. ExampleMandA.add2d = ExampleMandA.add2b
  71. a = ExampleMandA(123)
  72. assert a.value == 123
  73. a.add2(ExampleMandA(-100))
  74. assert a.value == 23
  75. a.add2b(ExampleMandA(20))
  76. assert a.value == 43
  77. a.add2c(ExampleMandA(6))
  78. assert a.value == 49
  79. a.add2d(ExampleMandA(-7))
  80. assert a.value == 42
  81. def test_static_properties():
  82. from pybind11_tests import TestProperties as Type
  83. assert Type.def_readonly_static == 1
  84. with pytest.raises(AttributeError) as excinfo:
  85. Type.def_readonly_static = 2
  86. assert "can't set attribute" in str(excinfo)
  87. Type.def_readwrite_static = 2
  88. assert Type.def_readwrite_static == 2
  89. assert Type.def_property_readonly_static == 2
  90. with pytest.raises(AttributeError) as excinfo:
  91. Type.def_property_readonly_static = 3
  92. assert "can't set attribute" in str(excinfo)
  93. Type.def_property_static = 3
  94. assert Type.def_property_static == 3
  95. # Static property read and write via instance
  96. instance = Type()
  97. Type.def_readwrite_static = 0
  98. assert Type.def_readwrite_static == 0
  99. assert instance.def_readwrite_static == 0
  100. instance.def_readwrite_static = 2
  101. assert Type.def_readwrite_static == 2
  102. assert instance.def_readwrite_static == 2
  103. # It should be possible to override properties in derived classes
  104. from pybind11_tests import TestPropertiesOverride as TypeOverride
  105. assert TypeOverride().def_readonly == 99
  106. assert TypeOverride.def_readonly_static == 99
  107. def test_static_cls():
  108. """Static property getter and setters expect the type object as the their only argument"""
  109. from pybind11_tests import TestProperties as Type
  110. instance = Type()
  111. assert Type.static_cls is Type
  112. assert instance.static_cls is Type
  113. def check_self(self):
  114. assert self is Type
  115. Type.static_cls = check_self
  116. instance.static_cls = check_self
  117. def test_metaclass_override():
  118. """Overriding pybind11's default metaclass changes the behavior of `static_property`"""
  119. from pybind11_tests import MetaclassOverride
  120. assert type(ExampleMandA).__name__ == "pybind11_type"
  121. assert type(MetaclassOverride).__name__ == "type"
  122. assert MetaclassOverride.readonly == 1
  123. assert type(MetaclassOverride.__dict__["readonly"]).__name__ == "pybind11_static_property"
  124. # Regular `type` replaces the property instead of calling `__set__()`
  125. MetaclassOverride.readonly = 2
  126. assert MetaclassOverride.readonly == 2
  127. assert isinstance(MetaclassOverride.__dict__["readonly"], int)
  128. def test_no_mixed_overloads():
  129. from pybind11_tests import debug_enabled
  130. with pytest.raises(RuntimeError) as excinfo:
  131. ExampleMandA.add_mixed_overloads1()
  132. assert (str(excinfo.value) ==
  133. "overloading a method with both static and instance methods is not supported; " +
  134. ("compile in debug mode for more details" if not debug_enabled else
  135. "error while attempting to bind static method ExampleMandA.overload_mixed1"
  136. "() -> str")
  137. )
  138. with pytest.raises(RuntimeError) as excinfo:
  139. ExampleMandA.add_mixed_overloads2()
  140. assert (str(excinfo.value) ==
  141. "overloading a method with both static and instance methods is not supported; " +
  142. ("compile in debug mode for more details" if not debug_enabled else
  143. "error while attempting to bind instance method ExampleMandA.overload_mixed2"
  144. "(self: pybind11_tests.ExampleMandA, arg0: int, arg1: int) -> str")
  145. )
  146. @pytest.mark.parametrize("access", ["ro", "rw", "static_ro", "static_rw"])
  147. def test_property_return_value_policies(access):
  148. from pybind11_tests import TestPropRVP
  149. if not access.startswith("static"):
  150. obj = TestPropRVP()
  151. else:
  152. obj = TestPropRVP
  153. ref = getattr(obj, access + "_ref")
  154. assert ref.value == 1
  155. ref.value = 2
  156. assert getattr(obj, access + "_ref").value == 2
  157. ref.value = 1 # restore original value for static properties
  158. copy = getattr(obj, access + "_copy")
  159. assert copy.value == 1
  160. copy.value = 2
  161. assert getattr(obj, access + "_copy").value == 1
  162. copy = getattr(obj, access + "_func")
  163. assert copy.value == 1
  164. copy.value = 2
  165. assert getattr(obj, access + "_func").value == 1
  166. def test_property_rvalue_policy():
  167. """When returning an rvalue, the return value policy is automatically changed from
  168. `reference(_internal)` to `move`. The following would not work otherwise.
  169. """
  170. from pybind11_tests import TestPropRVP
  171. instance = TestPropRVP()
  172. o = instance.rvalue
  173. assert o.value == 1
  174. def test_property_rvalue_policy_static():
  175. """When returning an rvalue, the return value policy is automatically changed from
  176. `reference(_internal)` to `move`. The following would not work otherwise.
  177. """
  178. from pybind11_tests import TestPropRVP
  179. o = TestPropRVP.static_rvalue
  180. assert o.value == 1
  181. # https://bitbucket.org/pypy/pypy/issues/2447
  182. @pytest.unsupported_on_pypy
  183. def test_dynamic_attributes():
  184. from pybind11_tests import DynamicClass, CppDerivedDynamicClass
  185. instance = DynamicClass()
  186. assert not hasattr(instance, "foo")
  187. assert "foo" not in dir(instance)
  188. # Dynamically add attribute
  189. instance.foo = 42
  190. assert hasattr(instance, "foo")
  191. assert instance.foo == 42
  192. assert "foo" in dir(instance)
  193. # __dict__ should be accessible and replaceable
  194. assert "foo" in instance.__dict__
  195. instance.__dict__ = {"bar": True}
  196. assert not hasattr(instance, "foo")
  197. assert hasattr(instance, "bar")
  198. with pytest.raises(TypeError) as excinfo:
  199. instance.__dict__ = []
  200. assert str(excinfo.value) == "__dict__ must be set to a dictionary, not a 'list'"
  201. cstats = ConstructorStats.get(DynamicClass)
  202. assert cstats.alive() == 1
  203. del instance
  204. assert cstats.alive() == 0
  205. # Derived classes should work as well
  206. class PythonDerivedDynamicClass(DynamicClass):
  207. pass
  208. for cls in CppDerivedDynamicClass, PythonDerivedDynamicClass:
  209. derived = cls()
  210. derived.foobar = 100
  211. assert derived.foobar == 100
  212. assert cstats.alive() == 1
  213. del derived
  214. assert cstats.alive() == 0
  215. # https://bitbucket.org/pypy/pypy/issues/2447
  216. @pytest.unsupported_on_pypy
  217. def test_cyclic_gc():
  218. from pybind11_tests import DynamicClass
  219. # One object references itself
  220. instance = DynamicClass()
  221. instance.circular_reference = instance
  222. cstats = ConstructorStats.get(DynamicClass)
  223. assert cstats.alive() == 1
  224. del instance
  225. assert cstats.alive() == 0
  226. # Two object reference each other
  227. i1 = DynamicClass()
  228. i2 = DynamicClass()
  229. i1.cycle = i2
  230. i2.cycle = i1
  231. assert cstats.alive() == 2
  232. del i1, i2
  233. assert cstats.alive() == 0
  234. def test_noconvert_args(msg):
  235. import pybind11_tests as m
  236. a = m.ArgInspector()
  237. assert msg(a.f("hi")) == """
  238. loading ArgInspector1 argument WITH conversion allowed. Argument value = hi
  239. """
  240. assert msg(a.g("this is a", "this is b")) == """
  241. loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = this is a
  242. loading ArgInspector1 argument WITH conversion allowed. Argument value = this is b
  243. 13
  244. loading ArgInspector2 argument WITH conversion allowed. Argument value = (default arg inspector 2)
  245. """ # noqa: E501 line too long
  246. assert msg(a.g("this is a", "this is b", 42)) == """
  247. loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = this is a
  248. loading ArgInspector1 argument WITH conversion allowed. Argument value = this is b
  249. 42
  250. loading ArgInspector2 argument WITH conversion allowed. Argument value = (default arg inspector 2)
  251. """ # noqa: E501 line too long
  252. assert msg(a.g("this is a", "this is b", 42, "this is d")) == """
  253. loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = this is a
  254. loading ArgInspector1 argument WITH conversion allowed. Argument value = this is b
  255. 42
  256. loading ArgInspector2 argument WITH conversion allowed. Argument value = this is d
  257. """
  258. assert (a.h("arg 1") ==
  259. "loading ArgInspector2 argument WITHOUT conversion allowed. Argument value = arg 1")
  260. assert msg(m.arg_inspect_func("A1", "A2")) == """
  261. loading ArgInspector2 argument WITH conversion allowed. Argument value = A1
  262. loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = A2
  263. """
  264. assert m.floats_preferred(4) == 2.0
  265. assert m.floats_only(4.0) == 2.0
  266. with pytest.raises(TypeError) as excinfo:
  267. m.floats_only(4)
  268. assert msg(excinfo.value) == """
  269. floats_only(): incompatible function arguments. The following argument types are supported:
  270. 1. (f: float) -> float
  271. Invoked with: 4
  272. """
  273. assert m.ints_preferred(4) == 2
  274. assert m.ints_preferred(True) == 0
  275. with pytest.raises(TypeError) as excinfo:
  276. m.ints_preferred(4.0)
  277. assert msg(excinfo.value) == """
  278. ints_preferred(): incompatible function arguments. The following argument types are supported:
  279. 1. (i: int) -> int
  280. Invoked with: 4.0
  281. """ # noqa: E501 line too long
  282. assert m.ints_only(4) == 2
  283. with pytest.raises(TypeError) as excinfo:
  284. m.ints_only(4.0)
  285. assert msg(excinfo.value) == """
  286. ints_only(): incompatible function arguments. The following argument types are supported:
  287. 1. (i: int) -> int
  288. Invoked with: 4.0
  289. """
  290. def test_bad_arg_default(msg):
  291. from pybind11_tests import debug_enabled, bad_arg_def_named, bad_arg_def_unnamed
  292. with pytest.raises(RuntimeError) as excinfo:
  293. bad_arg_def_named()
  294. assert msg(excinfo.value) == (
  295. "arg(): could not convert default argument 'a: NotRegistered' in function 'should_fail' "
  296. "into a Python object (type not registered yet?)"
  297. if debug_enabled else
  298. "arg(): could not convert default argument into a Python object (type not registered "
  299. "yet?). Compile in debug mode for more information."
  300. )
  301. with pytest.raises(RuntimeError) as excinfo:
  302. bad_arg_def_unnamed()
  303. assert msg(excinfo.value) == (
  304. "arg(): could not convert default argument 'NotRegistered' in function 'should_fail' "
  305. "into a Python object (type not registered yet?)"
  306. if debug_enabled else
  307. "arg(): could not convert default argument into a Python object (type not registered "
  308. "yet?). Compile in debug mode for more information."
  309. )
  310. def test_accepts_none(msg):
  311. from pybind11_tests import (NoneTester,
  312. no_none1, no_none2, no_none3, no_none4, no_none5,
  313. ok_none1, ok_none2, ok_none3, ok_none4, ok_none5)
  314. a = NoneTester()
  315. assert no_none1(a) == 42
  316. assert no_none2(a) == 42
  317. assert no_none3(a) == 42
  318. assert no_none4(a) == 42
  319. assert no_none5(a) == 42
  320. assert ok_none1(a) == 42
  321. assert ok_none2(a) == 42
  322. assert ok_none3(a) == 42
  323. assert ok_none4(a) == 42
  324. assert ok_none5(a) == 42
  325. with pytest.raises(TypeError) as excinfo:
  326. no_none1(None)
  327. assert "incompatible function arguments" in str(excinfo.value)
  328. with pytest.raises(TypeError) as excinfo:
  329. no_none2(None)
  330. assert "incompatible function arguments" in str(excinfo.value)
  331. with pytest.raises(TypeError) as excinfo:
  332. no_none3(None)
  333. assert "incompatible function arguments" in str(excinfo.value)
  334. with pytest.raises(TypeError) as excinfo:
  335. no_none4(None)
  336. assert "incompatible function arguments" in str(excinfo.value)
  337. with pytest.raises(TypeError) as excinfo:
  338. no_none5(None)
  339. assert "incompatible function arguments" in str(excinfo.value)
  340. # The first one still raises because you can't pass None as a lvalue reference arg:
  341. with pytest.raises(TypeError) as excinfo:
  342. assert ok_none1(None) == -1
  343. assert msg(excinfo.value) == """
  344. ok_none1(): incompatible function arguments. The following argument types are supported:
  345. 1. (arg0: m.NoneTester) -> int
  346. Invoked with: None
  347. """
  348. # The rest take the argument as pointer or holder, and accept None:
  349. assert ok_none2(None) == -1
  350. assert ok_none3(None) == -1
  351. assert ok_none4(None) == -1
  352. assert ok_none5(None) == -1
  353. def test_str_issue(msg):
  354. """#283: __str__ called on uninitialized instance when constructor arguments invalid"""
  355. from pybind11_tests import StrIssue
  356. assert str(StrIssue(3)) == "StrIssue[3]"
  357. with pytest.raises(TypeError) as excinfo:
  358. str(StrIssue("no", "such", "constructor"))
  359. assert msg(excinfo.value) == """
  360. __init__(): incompatible constructor arguments. The following argument types are supported:
  361. 1. m.StrIssue(arg0: int)
  362. 2. m.StrIssue()
  363. Invoked with: 'no', 'such', 'constructor'
  364. """