test_methods_and_attributes.py revision 11986
111986Sandreas.sandberg@arm.comimport pytest 211986Sandreas.sandberg@arm.comfrom pybind11_tests import ExampleMandA, ConstructorStats 311986Sandreas.sandberg@arm.com 411986Sandreas.sandberg@arm.com 511986Sandreas.sandberg@arm.comdef test_methods_and_attributes(): 611986Sandreas.sandberg@arm.com instance1 = ExampleMandA() 711986Sandreas.sandberg@arm.com instance2 = ExampleMandA(32) 811986Sandreas.sandberg@arm.com 911986Sandreas.sandberg@arm.com instance1.add1(instance2) 1011986Sandreas.sandberg@arm.com instance1.add2(instance2) 1111986Sandreas.sandberg@arm.com instance1.add3(instance2) 1211986Sandreas.sandberg@arm.com instance1.add4(instance2) 1311986Sandreas.sandberg@arm.com instance1.add5(instance2) 1411986Sandreas.sandberg@arm.com instance1.add6(32) 1511986Sandreas.sandberg@arm.com instance1.add7(32) 1611986Sandreas.sandberg@arm.com instance1.add8(32) 1711986Sandreas.sandberg@arm.com instance1.add9(32) 1811986Sandreas.sandberg@arm.com instance1.add10(32) 1911986Sandreas.sandberg@arm.com 2011986Sandreas.sandberg@arm.com assert str(instance1) == "ExampleMandA[value=320]" 2111986Sandreas.sandberg@arm.com assert str(instance2) == "ExampleMandA[value=32]" 2211986Sandreas.sandberg@arm.com assert str(instance1.self1()) == "ExampleMandA[value=320]" 2311986Sandreas.sandberg@arm.com assert str(instance1.self2()) == "ExampleMandA[value=320]" 2411986Sandreas.sandberg@arm.com assert str(instance1.self3()) == "ExampleMandA[value=320]" 2511986Sandreas.sandberg@arm.com assert str(instance1.self4()) == "ExampleMandA[value=320]" 2611986Sandreas.sandberg@arm.com assert str(instance1.self5()) == "ExampleMandA[value=320]" 2711986Sandreas.sandberg@arm.com 2811986Sandreas.sandberg@arm.com assert instance1.internal1() == 320 2911986Sandreas.sandberg@arm.com assert instance1.internal2() == 320 3011986Sandreas.sandberg@arm.com assert instance1.internal3() == 320 3111986Sandreas.sandberg@arm.com assert instance1.internal4() == 320 3211986Sandreas.sandberg@arm.com assert instance1.internal5() == 320 3311986Sandreas.sandberg@arm.com 3411986Sandreas.sandberg@arm.com assert instance1.overloaded(1, 1.0) == "(int, float)" 3511986Sandreas.sandberg@arm.com assert instance1.overloaded(2.0, 2) == "(float, int)" 3611986Sandreas.sandberg@arm.com assert instance1.overloaded_const(3, 3.0) == "(int, float) const" 3711986Sandreas.sandberg@arm.com assert instance1.overloaded_const(4.0, 4) == "(float, int) const" 3811986Sandreas.sandberg@arm.com 3911986Sandreas.sandberg@arm.com assert instance1.value == 320 4011986Sandreas.sandberg@arm.com instance1.value = 100 4111986Sandreas.sandberg@arm.com assert str(instance1) == "ExampleMandA[value=100]" 4211986Sandreas.sandberg@arm.com 4311986Sandreas.sandberg@arm.com cstats = ConstructorStats.get(ExampleMandA) 4411986Sandreas.sandberg@arm.com assert cstats.alive() == 2 4511986Sandreas.sandberg@arm.com del instance1, instance2 4611986Sandreas.sandberg@arm.com assert cstats.alive() == 0 4711986Sandreas.sandberg@arm.com assert cstats.values() == ["32"] 4811986Sandreas.sandberg@arm.com assert cstats.default_constructions == 1 4911986Sandreas.sandberg@arm.com assert cstats.copy_constructions == 3 5011986Sandreas.sandberg@arm.com assert cstats.move_constructions >= 1 5111986Sandreas.sandberg@arm.com assert cstats.copy_assignments == 0 5211986Sandreas.sandberg@arm.com assert cstats.move_assignments == 0 5311986Sandreas.sandberg@arm.com 5411986Sandreas.sandberg@arm.com 5511986Sandreas.sandberg@arm.comdef test_properties(): 5611986Sandreas.sandberg@arm.com from pybind11_tests import TestProperties 5711986Sandreas.sandberg@arm.com 5811986Sandreas.sandberg@arm.com instance = TestProperties() 5911986Sandreas.sandberg@arm.com 6011986Sandreas.sandberg@arm.com assert instance.def_readonly == 1 6111986Sandreas.sandberg@arm.com with pytest.raises(AttributeError): 6211986Sandreas.sandberg@arm.com instance.def_readonly = 2 6311986Sandreas.sandberg@arm.com 6411986Sandreas.sandberg@arm.com instance.def_readwrite = 2 6511986Sandreas.sandberg@arm.com assert instance.def_readwrite == 2 6611986Sandreas.sandberg@arm.com 6711986Sandreas.sandberg@arm.com assert instance.def_property_readonly == 2 6811986Sandreas.sandberg@arm.com with pytest.raises(AttributeError): 6911986Sandreas.sandberg@arm.com instance.def_property_readonly = 3 7011986Sandreas.sandberg@arm.com 7111986Sandreas.sandberg@arm.com instance.def_property = 3 7211986Sandreas.sandberg@arm.com assert instance.def_property == 3 7311986Sandreas.sandberg@arm.com 7411986Sandreas.sandberg@arm.com 7511986Sandreas.sandberg@arm.comdef test_static_properties(): 7611986Sandreas.sandberg@arm.com from pybind11_tests import TestProperties as Type 7711986Sandreas.sandberg@arm.com 7811986Sandreas.sandberg@arm.com assert Type.def_readonly_static == 1 7911986Sandreas.sandberg@arm.com with pytest.raises(AttributeError): 8011986Sandreas.sandberg@arm.com Type.def_readonly_static = 2 8111986Sandreas.sandberg@arm.com 8211986Sandreas.sandberg@arm.com Type.def_readwrite_static = 2 8311986Sandreas.sandberg@arm.com assert Type.def_readwrite_static == 2 8411986Sandreas.sandberg@arm.com 8511986Sandreas.sandberg@arm.com assert Type.def_property_readonly_static == 2 8611986Sandreas.sandberg@arm.com with pytest.raises(AttributeError): 8711986Sandreas.sandberg@arm.com Type.def_property_readonly_static = 3 8811986Sandreas.sandberg@arm.com 8911986Sandreas.sandberg@arm.com Type.def_property_static = 3 9011986Sandreas.sandberg@arm.com assert Type.def_property_static == 3 9111986Sandreas.sandberg@arm.com 9211986Sandreas.sandberg@arm.com 9311986Sandreas.sandberg@arm.com@pytest.mark.parametrize("access", ["ro", "rw", "static_ro", "static_rw"]) 9411986Sandreas.sandberg@arm.comdef test_property_return_value_policies(access): 9511986Sandreas.sandberg@arm.com from pybind11_tests import TestPropRVP 9611986Sandreas.sandberg@arm.com 9711986Sandreas.sandberg@arm.com if not access.startswith("static"): 9811986Sandreas.sandberg@arm.com obj = TestPropRVP() 9911986Sandreas.sandberg@arm.com else: 10011986Sandreas.sandberg@arm.com obj = TestPropRVP 10111986Sandreas.sandberg@arm.com 10211986Sandreas.sandberg@arm.com ref = getattr(obj, access + "_ref") 10311986Sandreas.sandberg@arm.com assert ref.value == 1 10411986Sandreas.sandberg@arm.com ref.value = 2 10511986Sandreas.sandberg@arm.com assert getattr(obj, access + "_ref").value == 2 10611986Sandreas.sandberg@arm.com ref.value = 1 # restore original value for static properties 10711986Sandreas.sandberg@arm.com 10811986Sandreas.sandberg@arm.com copy = getattr(obj, access + "_copy") 10911986Sandreas.sandberg@arm.com assert copy.value == 1 11011986Sandreas.sandberg@arm.com copy.value = 2 11111986Sandreas.sandberg@arm.com assert getattr(obj, access + "_copy").value == 1 11211986Sandreas.sandberg@arm.com 11311986Sandreas.sandberg@arm.com copy = getattr(obj, access + "_func") 11411986Sandreas.sandberg@arm.com assert copy.value == 1 11511986Sandreas.sandberg@arm.com copy.value = 2 11611986Sandreas.sandberg@arm.com assert getattr(obj, access + "_func").value == 1 11711986Sandreas.sandberg@arm.com 11811986Sandreas.sandberg@arm.com 11911986Sandreas.sandberg@arm.comdef test_property_rvalue_policy(): 12011986Sandreas.sandberg@arm.com """When returning an rvalue, the return value policy is automatically changed from 12111986Sandreas.sandberg@arm.com `reference(_internal)` to `move`. The following would not work otherwise. 12211986Sandreas.sandberg@arm.com """ 12311986Sandreas.sandberg@arm.com from pybind11_tests import TestPropRVP 12411986Sandreas.sandberg@arm.com 12511986Sandreas.sandberg@arm.com instance = TestPropRVP() 12611986Sandreas.sandberg@arm.com o = instance.rvalue 12711986Sandreas.sandberg@arm.com assert o.value == 1 12811986Sandreas.sandberg@arm.com o = TestPropRVP.static_rvalue 12911986Sandreas.sandberg@arm.com assert o.value == 1 13011986Sandreas.sandberg@arm.com 13111986Sandreas.sandberg@arm.com 13211986Sandreas.sandberg@arm.comdef test_dynamic_attributes(): 13311986Sandreas.sandberg@arm.com from pybind11_tests import DynamicClass, CppDerivedDynamicClass 13411986Sandreas.sandberg@arm.com 13511986Sandreas.sandberg@arm.com instance = DynamicClass() 13611986Sandreas.sandberg@arm.com assert not hasattr(instance, "foo") 13711986Sandreas.sandberg@arm.com assert "foo" not in dir(instance) 13811986Sandreas.sandberg@arm.com 13911986Sandreas.sandberg@arm.com # Dynamically add attribute 14011986Sandreas.sandberg@arm.com instance.foo = 42 14111986Sandreas.sandberg@arm.com assert hasattr(instance, "foo") 14211986Sandreas.sandberg@arm.com assert instance.foo == 42 14311986Sandreas.sandberg@arm.com assert "foo" in dir(instance) 14411986Sandreas.sandberg@arm.com 14511986Sandreas.sandberg@arm.com # __dict__ should be accessible and replaceable 14611986Sandreas.sandberg@arm.com assert "foo" in instance.__dict__ 14711986Sandreas.sandberg@arm.com instance.__dict__ = {"bar": True} 14811986Sandreas.sandberg@arm.com assert not hasattr(instance, "foo") 14911986Sandreas.sandberg@arm.com assert hasattr(instance, "bar") 15011986Sandreas.sandberg@arm.com 15111986Sandreas.sandberg@arm.com with pytest.raises(TypeError) as excinfo: 15211986Sandreas.sandberg@arm.com instance.__dict__ = [] 15311986Sandreas.sandberg@arm.com assert str(excinfo.value) == "__dict__ must be set to a dictionary, not a 'list'" 15411986Sandreas.sandberg@arm.com 15511986Sandreas.sandberg@arm.com cstats = ConstructorStats.get(DynamicClass) 15611986Sandreas.sandberg@arm.com assert cstats.alive() == 1 15711986Sandreas.sandberg@arm.com del instance 15811986Sandreas.sandberg@arm.com assert cstats.alive() == 0 15911986Sandreas.sandberg@arm.com 16011986Sandreas.sandberg@arm.com # Derived classes should work as well 16111986Sandreas.sandberg@arm.com class PythonDerivedDynamicClass(DynamicClass): 16211986Sandreas.sandberg@arm.com pass 16311986Sandreas.sandberg@arm.com 16411986Sandreas.sandberg@arm.com for cls in CppDerivedDynamicClass, PythonDerivedDynamicClass: 16511986Sandreas.sandberg@arm.com derived = cls() 16611986Sandreas.sandberg@arm.com derived.foobar = 100 16711986Sandreas.sandberg@arm.com assert derived.foobar == 100 16811986Sandreas.sandberg@arm.com 16911986Sandreas.sandberg@arm.com assert cstats.alive() == 1 17011986Sandreas.sandberg@arm.com del derived 17111986Sandreas.sandberg@arm.com assert cstats.alive() == 0 17211986Sandreas.sandberg@arm.com 17311986Sandreas.sandberg@arm.com 17411986Sandreas.sandberg@arm.comdef test_cyclic_gc(): 17511986Sandreas.sandberg@arm.com from pybind11_tests import DynamicClass 17611986Sandreas.sandberg@arm.com 17711986Sandreas.sandberg@arm.com # One object references itself 17811986Sandreas.sandberg@arm.com instance = DynamicClass() 17911986Sandreas.sandberg@arm.com instance.circular_reference = instance 18011986Sandreas.sandberg@arm.com 18111986Sandreas.sandberg@arm.com cstats = ConstructorStats.get(DynamicClass) 18211986Sandreas.sandberg@arm.com assert cstats.alive() == 1 18311986Sandreas.sandberg@arm.com del instance 18411986Sandreas.sandberg@arm.com assert cstats.alive() == 0 18511986Sandreas.sandberg@arm.com 18611986Sandreas.sandberg@arm.com # Two object reference each other 18711986Sandreas.sandberg@arm.com i1 = DynamicClass() 18811986Sandreas.sandberg@arm.com i2 = DynamicClass() 18911986Sandreas.sandberg@arm.com i1.cycle = i2 19011986Sandreas.sandberg@arm.com i2.cycle = i1 19111986Sandreas.sandberg@arm.com 19211986Sandreas.sandberg@arm.com assert cstats.alive() == 2 19311986Sandreas.sandberg@arm.com del i1, i2 19411986Sandreas.sandberg@arm.com assert cstats.alive() == 0 195