# -*- coding: utf-8 -*- """Test CLR method support.""" import System import pytest from Python.Test import MethodTest def test_instance_method_overwritable(): """Test instance method overwriting.""" ob = MethodTest() ob.OverwritableMethod = lambda: "overwritten" assert ob.OverwritableMethod() == "overwritten" def test_public_instance_method(): """Test public instance method visibility.""" ob = MethodTest() assert ob.PublicMethod() == "public" def test_public_static_method(): """Test public static method visibility.""" ob = MethodTest() assert MethodTest.PublicStaticMethod() == "public static" assert ob.PublicStaticMethod() == "public static" def test_protected_instance_method(): """Test protected instance method visibility.""" ob = MethodTest() assert ob.ProtectedMethod() == "protected" def test_protected_static_method(): """Test protected static method visibility.""" ob = MethodTest() result = "protected static" assert MethodTest.ProtectedStaticMethod() == result assert ob.ProtectedStaticMethod() == result def test_internal_method(): """Test internal method visibility.""" with pytest.raises(AttributeError): _ = MethodTest().InternalMethod with pytest.raises(AttributeError): _ = MethodTest.InternalMethod with pytest.raises(AttributeError): _ = MethodTest().InternalStaticMethod with pytest.raises(AttributeError): _ = MethodTest.InternalStaticMethod def test_private_method(): """Test private method visibility.""" with pytest.raises(AttributeError): _ = MethodTest().PrivateMethod with pytest.raises(AttributeError): _ = MethodTest.PrivateMethod with pytest.raises(AttributeError): _ = MethodTest().PrivateStaticMethod with pytest.raises(AttributeError): _ = MethodTest.PrivateStaticMethod def test_unbound_managed_method_call(): """Test calling unbound managed methods.""" from Python.Test import MethodTestSub ob = MethodTest() assert MethodTest.PublicMethod(ob) == "public" with pytest.raises(TypeError): MethodTest.PublicMethod() ob = MethodTestSub() assert MethodTestSub.PublicMethod(ob) == "public" assert MethodTestSub.PublicMethod(ob, "echo") == "echo" with pytest.raises(TypeError): MethodTestSub.PublicMethod("echo") def test_overloaded_method_inheritance(): """Test that overloads are inherited properly.""" from Python.Test import MethodTestSub ob = MethodTest() assert ob.PublicMethod() == "public" with pytest.raises(TypeError): ob = MethodTest() ob.PublicMethod("echo") ob = MethodTestSub() assert ob.PublicMethod() == "public" assert ob.PublicMethod("echo") == "echo" def test_method_descriptor_abuse(): """Test method descriptor abuse.""" desc = MethodTest.__dict__['PublicMethod'] with pytest.raises(TypeError): desc.__get__(0, 0) with pytest.raises(AttributeError): desc.__set__(0, 0) def test_method_docstrings(): """Test standard method docstring generation""" method = MethodTest.GetType value = 'System.Type GetType()' assert method.__doc__ == value # ====================================================================== # Tests of specific argument and result conversion scenarios # ====================================================================== def test_method_call_enum_conversion(): """Test enum conversion in method call.""" from System import TypeCode ob = MethodTest() r = ob.TestEnumConversion(TypeCode.Int32) assert r == TypeCode.Int32 def test_method_call_flags_conversion(): """Test flags conversion in method call.""" from System.IO import FileAccess ob = MethodTest() flags = FileAccess.Read | FileAccess.Write r = ob.TestFlagsConversion(flags) assert r == flags def test_method_call_struct_conversion(): """Test struct conversion in method call.""" from System import Guid ob = MethodTest() guid = Guid.NewGuid() temp = guid.ToString() r = ob.TestStructConversion(guid) assert r.ToString() == temp def test_subclass_instance_conversion(): """Test subclass instance conversion in method call.""" class TestSubException(System.Exception): pass ob = MethodTest() instance = TestSubException() result = ob.TestSubclassConversion(instance) assert isinstance(result, System.Exception) def test_null_array_conversion(): """Test null array conversion in method call.""" ob = MethodTest() r = ob.TestNullArrayConversion(None) assert r is None def test_string_params_args(): """Test use of string params.""" result = MethodTest.TestStringParamsArg('one', 'two', 'three') assert result.Length == 4 assert len(result) == 4, result assert result[0] == 'one' assert result[1] == 'two' assert result[2] == 'three' # ensures params string[] overload takes precedence over params object[] assert result[3] == 'tail' result = MethodTest.TestStringParamsArg(['one', 'two', 'three']) assert len(result) == 4 assert result[0] == 'one' assert result[1] == 'two' assert result[2] == 'three' assert result[3] == 'tail' def test_object_params_args(): """Test use of object params.""" result = MethodTest.TestObjectParamsArg('one', 'two', 'three') assert len(result) == 3, result assert result[0] == 'one' assert result[1] == 'two' assert result[2] == 'three' result = MethodTest.TestObjectParamsArg(['one', 'two', 'three']) assert len(result) == 3, result assert result[0] == 'one' assert result[1] == 'two' assert result[2] == 'three' def test_value_params_args(): """Test use of value type params.""" result = MethodTest.TestValueParamsArg(1, 2, 3) assert len(result) == 3 assert result[0] == 1 assert result[1] == 2 assert result[2] == 3 result = MethodTest.TestValueParamsArg([1, 2, 3]) assert len(result) == 3 assert result[0] == 1 assert result[1] == 2 assert result[2] == 3 def test_non_params_array_in_last_place(): """Test overload resolution with of non-"params" array as last parameter.""" result = MethodTest.TestNonParamsArrayInLastPlace(1, 2, 3) assert result def test_params_methods_with_no_params(): """Tests that passing no arguments to a params method passes an empty array""" result = MethodTest.TestValueParamsArg() assert len(result) == 0 result = MethodTest.TestOneArgWithParams('Some String') assert len(result) == 0 result = MethodTest.TestTwoArgWithParams('Some String', 'Some Other String') assert len(result) == 0 def test_params_methods_with_non_lists(): """Tests that passing single parameters to a params method will convert into an array on the .NET side""" result = MethodTest.TestOneArgWithParams('Some String', [1, 2, 3, 4]) assert len(result) == 4 result = MethodTest.TestOneArgWithParams('Some String', 1, 2, 3, 4) assert len(result) == 4 result = MethodTest.TestOneArgWithParams('Some String', [5]) assert len(result) == 1 result = MethodTest.TestOneArgWithParams('Some String', 5) assert len(result) == 1 def test_params_method_with_lists(): """Tests passing multiple lists to a params object[] method""" result = MethodTest.TestObjectParamsArg([],[]) assert len(result) == 2 def test_string_out_params(): """Test use of string out-parameters.""" result = MethodTest.TestStringOutParams("hi", "there") assert isinstance(result, tuple) assert len(result) == 2 assert result[0] is True assert result[1] == "output string" result = MethodTest.TestStringOutParams("hi", None) assert isinstance(result, tuple) assert len(result) == 2 assert result[0] is True assert result[1] == "output string" def test_string_out_params_without_passing_string_value(): """Test use of string out-parameters.""" # @eirannejad 2022-01-13 result = MethodTest.TestStringOutParams("hi") assert isinstance(result, tuple) assert len(result) == 2 assert result[0] is True assert result[1] == "output string" def test_string_ref_params(): """Test use of string byref parameters.""" result = MethodTest.TestStringRefParams("hi", "there") assert isinstance(result, tuple) assert len(result) == 2 assert result[0] is True assert result[1] == "output string" result = MethodTest.TestStringRefParams("hi", None) assert isinstance(result, tuple) assert len(result) == 2 assert result[0] is True assert result[1] == "output string" def test_value_out_params(): """Test use of value type out-parameters.""" result = MethodTest.TestValueOutParams("hi", 1) assert isinstance(result, tuple) assert len(result) == 2 assert result[0] is True assert result[1] == 42 # None cannot be converted to a value type like int, long, etc. with pytest.raises(TypeError): MethodTest.TestValueOutParams("hi", None) def test_value_out_params_without_passing_string_value(): """Test use of string out-parameters.""" # @eirannejad 2022-01-13 result = MethodTest.TestValueOutParams("hi") assert isinstance(result, tuple) assert len(result) == 2 assert result[0] is True assert result[1] == 42 def test_value_ref_params(): """Test use of value type byref parameters.""" result = MethodTest.TestValueRefParams("hi", 1) assert isinstance(result, tuple) assert len(result) == 2 assert result[0] is True assert result[1] == 42 # None cannot be converted to a value type like int, long, etc. with pytest.raises(TypeError): MethodTest.TestValueRefParams("hi", None) def test_object_out_params(): """Test use of object out-parameters.""" result = MethodTest.TestObjectOutParams("hi", MethodTest()) assert isinstance(result, tuple) assert len(result) == 2 assert result[0] is True assert isinstance(result[1], System.Exception) result = MethodTest.TestObjectOutParams("hi", None) assert isinstance(result, tuple) assert len(result) == 2 assert result[0] is True assert isinstance(result[1], System.Exception) def test_object_out_params_without_passing_string_value(): """Test use of object out-parameters.""" result = MethodTest.TestObjectOutParams("hi") assert isinstance(result, tuple) assert len(result) == 2 assert result[0] is True assert isinstance(result[1], System.Exception) def test_object_ref_params(): """Test use of object byref parameters.""" result = MethodTest.TestObjectRefParams("hi", MethodTest()) assert isinstance(result, tuple) assert len(result) == 2 assert result[0] is True assert isinstance(result[1], System.Exception) result = MethodTest.TestObjectRefParams("hi", None) assert isinstance(result, tuple) assert len(result) == 2 assert result[0] is True assert isinstance(result[1], System.Exception) def test_struct_out_params(): """Test use of struct out-parameters.""" result = MethodTest.TestStructOutParams("hi", System.Guid.NewGuid()) assert isinstance(result, tuple) assert len(result) == 2 assert result[0] is True assert isinstance(result[1], System.Guid) # None cannot be converted to a value type like a struct with pytest.raises(TypeError): MethodTest.TestValueRefParams("hi", None) def test_struct_out_params_without_passing_string_value(): """Test use of struct out-parameters.""" result = MethodTest.TestStructOutParams("hi") assert isinstance(result, tuple) assert len(result) == 2 assert result[0] is True assert isinstance(result[1], System.Guid) def test_struct_ref_params(): """Test use of struct byref parameters.""" result = MethodTest.TestStructRefParams("hi", System.Guid.NewGuid()) assert isinstance(result, tuple) assert len(result) == 2 assert result[0] is True assert isinstance(result[1], System.Guid) # None cannot be converted to a value type like a struct with pytest.raises(TypeError): MethodTest.TestValueRefParams("hi", None) def test_void_single_out_param(): """Test void method with single out-parameter.""" result = MethodTest.TestVoidSingleOutParam(9) assert result == 42 # None cannot be converted to a value type with pytest.raises(TypeError): MethodTest.TestVoidSingleOutParam(None) def test_void_single_ref_param(): """Test void method with single ref-parameter.""" result = MethodTest.TestVoidSingleRefParam(9) assert result == 42 # None cannot be converted to a value type with pytest.raises(TypeError): MethodTest.TestVoidSingleRefParam(None) def test_single_default_param(): """Test void method with single ref-parameter.""" result = MethodTest.TestSingleDefaultParam() assert result == 5 def test_decimal_default_param(): """Test that decimal default parameters work.""" result = MethodTest.TestDecimalDefaultParam() assert result == System.Decimal(1) def test_one_arg_and_two_default_param(): """Test void method with single ref-parameter.""" result = MethodTest.TestOneArgAndTwoDefaultParam(11) assert result == 22 result = MethodTest.TestOneArgAndTwoDefaultParam(15) assert result == 26 result = MethodTest.TestOneArgAndTwoDefaultParam(20) assert result == 31 def test_two_default_param(): """Test void method with single ref-parameter.""" result = MethodTest.TestTwoDefaultParam() assert result == 11 def test_explicit_selection_with_out_modifier(): """Check explicit overload selection with out modifiers.""" refstr = System.String("").GetType().MakeByRefType() result = MethodTest.TestStringOutParams.__overloads__[str, refstr]( "hi", "there") assert isinstance(result, tuple) assert len(result) == 2 assert result[0] is True assert result[1] == "output string" result = MethodTest.TestStringOutParams.__overloads__[str, refstr]( "hi", None) assert isinstance(result, tuple) assert len(result) == 2 assert result[0] is True assert result[1] == "output string" def test_explicit_selection_with_ref_modifier(): """Check explicit overload selection with ref modifiers.""" refstr = System.String("").GetType().MakeByRefType() result = MethodTest.TestStringRefParams.__overloads__[str, refstr]( "hi", "there") assert isinstance(result, tuple) assert len(result) == 2 assert result[0] is True assert result[1] == "output string" result = MethodTest.TestStringRefParams.__overloads__[str, refstr]( "hi", None) assert isinstance(result, tuple) assert len(result) == 2 assert result[0] is True assert result[1] == "output string" def test_explicit_overload_selection(): """Check explicit overload selection using [] syntax.""" from Python.Test import ISayHello1, InterfaceTest, ShortEnum from System import Array inst = InterfaceTest() value = MethodTest.Overloaded.__overloads__[System.Boolean](True) assert value is True value = MethodTest.Overloaded.__overloads__[bool](True) assert value is True value = MethodTest.Overloaded.__overloads__[System.Byte](255) assert value == 255 value = MethodTest.Overloaded.__overloads__[System.SByte](127) assert value == 127 value = MethodTest.Overloaded.__overloads__[System.Char](u'A') assert value == u'A' value = MethodTest.Overloaded.__overloads__[System.Char](65535) assert value == chr(65535) value = MethodTest.Overloaded.__overloads__[System.Int16](32767) assert value == 32767 value = MethodTest.Overloaded.__overloads__[System.Int32](2147483647) assert value == 2147483647 value = MethodTest.Overloaded.__overloads__[int](2147483647) assert value == 2147483647 value = MethodTest.Overloaded.__overloads__[System.Int64]( 9223372036854775807 ) assert value == 9223372036854775807 value = MethodTest.Overloaded.__overloads__[System.UInt16](65000) assert value == 65000 value = MethodTest.Overloaded.__overloads__[System.UInt32]( 4294967295 ) assert value == 4294967295 value = MethodTest.Overloaded.__overloads__[System.UInt64]( 18446744073709551615 ) assert value == 18446744073709551615 value = MethodTest.Overloaded.__overloads__[System.Single](3.402823e38) assert value == System.Single(3.402823e38) value = MethodTest.Overloaded.__overloads__[System.Double]( 1.7976931348623157e308) assert value == 1.7976931348623157e308 value = MethodTest.Overloaded.__overloads__[float]( 1.7976931348623157e308) assert value == 1.7976931348623157e308 value = MethodTest.Overloaded.__overloads__[System.Decimal]( System.Decimal.One) assert value == System.Decimal.One value = MethodTest.Overloaded.__overloads__[System.String]("spam") assert value == "spam" value = MethodTest.Overloaded.__overloads__[str]("spam") assert value == "spam" value = MethodTest.Overloaded.__overloads__[ShortEnum](ShortEnum.Zero) assert value == ShortEnum.Zero value = MethodTest.Overloaded.__overloads__[System.Object](inst) assert value.__class__ == inst.__class__ value = MethodTest.Overloaded.__overloads__[InterfaceTest](inst) assert value.__class__ == inst.__class__ iface_class = ISayHello1(InterfaceTest()).__class__ value = MethodTest.Overloaded.__overloads__[ISayHello1](inst) assert value.__class__ != inst.__class__ assert value.__class__ == iface_class atype = Array[System.Object] value = MethodTest.Overloaded.__overloads__[str, int, atype]( "one", 1, atype([1, 2, 3])) assert value == 3 value = MethodTest.Overloaded.__overloads__[str, int]("one", 1) assert value == 1 value = MethodTest.Overloaded.__overloads__[int, str](1, "one") assert value == 1 def test_overload_selection_with_array_types(): """Check overload selection using array types.""" from Python.Test import ISayHello1, InterfaceTest, ShortEnum from System import Array inst = InterfaceTest() vtype = Array[System.Boolean] input_ = vtype([True, True]) value = MethodTest.Overloaded.__overloads__[vtype](input_) assert value[0] is True assert value[1] is True vtype = Array[bool] input_ = vtype([True, True]) value = MethodTest.Overloaded.__overloads__[vtype](input_) assert value[0] is True assert value[1] is True vtype = Array[System.Byte] input_ = vtype([0, 255]) value = MethodTest.Overloaded.__overloads__[vtype](input_) assert value[0] == 0 assert value[1] == 255 vtype = Array[System.SByte] input_ = vtype([0, 127]) value = MethodTest.Overloaded.__overloads__[vtype](input_) assert value[0] == 0 assert value[1] == 127 vtype = Array[System.Char] input_ = vtype([u'A', u'Z']) value = MethodTest.Overloaded.__overloads__[vtype](input_) assert value[0] == u'A' assert value[1] == u'Z' vtype = Array[System.Char] input_ = vtype([0, 65535]) value = MethodTest.Overloaded.__overloads__[vtype](input_) assert value[0] == chr(0) assert value[1] == chr(65535) vtype = Array[System.Int16] input_ = vtype([0, 32767]) value = MethodTest.Overloaded.__overloads__[vtype](input_) assert value[0] == 0 assert value[1] == 32767 vtype = Array[System.Int32] input_ = vtype([0, 2147483647]) value = MethodTest.Overloaded.__overloads__[vtype](input_) assert value[0] == 0 assert value[1] == 2147483647 vtype = Array[int] input_ = vtype([0, 2147483647]) value = MethodTest.Overloaded.__overloads__[vtype](input_) assert value[0] == 0 assert value[1] == 2147483647 vtype = Array[System.Int64] input_ = vtype([0, 9223372036854775807]) value = MethodTest.Overloaded.__overloads__[vtype](input_) assert value[0] == 0 assert value[1] == 9223372036854775807 vtype = Array[System.UInt16] input_ = vtype([0, 65000]) value = MethodTest.Overloaded.__overloads__[vtype](input_) assert value[0] == 0 assert value[1] == 65000 vtype = Array[System.UInt32] input_ = vtype([0, 4294967295]) value = MethodTest.Overloaded.__overloads__[vtype](input_) assert value[0] == 0 assert value[1] == 4294967295 vtype = Array[System.UInt64] input_ = vtype([0, 18446744073709551615]) value = MethodTest.Overloaded.__overloads__[vtype](input_) assert value[0] == 0 assert value[1] == 18446744073709551615 vtype = Array[System.Single] input_ = vtype([0.0, 3.402823e38]) value = MethodTest.Overloaded.__overloads__[vtype](input_) assert value[0] == 0.0 assert value[1] == System.Single(3.402823e38) vtype = Array[System.Double] input_ = vtype([0.0, 1.7976931348623157e308]) value = MethodTest.Overloaded.__overloads__[vtype](input_) assert value[0] == 0.0 assert value[1] == 1.7976931348623157e308 vtype = Array[float] input_ = vtype([0.0, 1.7976931348623157e308]) value = MethodTest.Overloaded.__overloads__[vtype](input_) assert value[0] == 0.0 assert value[1] == 1.7976931348623157e308 vtype = Array[System.Decimal] input_ = vtype([System.Decimal.Zero, System.Decimal.One]) value = MethodTest.Overloaded.__overloads__[vtype](input_) assert value[0] == System.Decimal.Zero assert value[1] == System.Decimal.One vtype = Array[System.String] input_ = vtype(["one", "two"]) value = MethodTest.Overloaded.__overloads__[vtype](input_) assert value[0] == "one" assert value[1] == "two" vtype = Array[str] input_ = vtype(["one", "two"]) value = MethodTest.Overloaded.__overloads__[vtype](input_) assert value[0] == "one" assert value[1] == "two" vtype = Array[ShortEnum] input_ = vtype([ShortEnum.Zero, ShortEnum.One]) value = MethodTest.Overloaded.__overloads__[vtype](input_) assert value[0] == ShortEnum.Zero assert value[1] == ShortEnum.One vtype = Array[System.Object] input_ = vtype([inst, inst]) value = MethodTest.Overloaded.__overloads__[vtype](input_) assert value[0].__class__ == inst.__class__ assert value[1].__class__ == inst.__class__ vtype = Array[InterfaceTest] input_ = vtype([inst, inst]) value = MethodTest.Overloaded.__overloads__[vtype](input_) assert value[0].__class__ == inst.__class__ assert value[1].__class__ == inst.__class__ iface_class = ISayHello1(inst).__class__ vtype = Array[ISayHello1] input_ = vtype([inst, inst]) value = MethodTest.Overloaded.__overloads__[vtype](input_) assert value[0].__class__ == iface_class assert value[1].__class__ == iface_class def test_explicit_overload_selection_failure(): """Check that overload selection fails correctly.""" with pytest.raises(TypeError): _ = MethodTest.Overloaded.__overloads__[System.Type](True) with pytest.raises(TypeError): _ = MethodTest.Overloaded.__overloads__[int, int](1, 1) with pytest.raises(TypeError): _ = MethodTest.Overloaded.__overloads__[str, int, int]("", 1, 1) with pytest.raises(TypeError): _ = MethodTest.Overloaded.__overloads__[int, int](1) def test_we_can_bind_to_encoding_get_string(): """Check that we can bind to the Encoding.GetString method with variables.""" from System.Text import Encoding from System.IO import MemoryStream my_bytes = Encoding.UTF8.GetBytes('Some testing string') stream = MemoryStream() stream.Write(my_bytes, 0, my_bytes.Length) stream.Position = 0 buff = System.Array.CreateInstance(System.Byte, 3) buff.Initialize() data = [] read = 1 while read > 0: read = stream.Read(buff, 0, buff.Length) temp = Encoding.UTF8.GetString(buff, 0, read) data.append(temp) data = ''.join(data) assert data == 'Some testing string' def test_wrong_overload(): """Test regression in which implicit conversion caused the wrong types to be used. See #131 for issue. Fixed by #137, #151""" # Used to return `50L` res = System.Math.Abs(50.5) assert res == 50.5 assert type(res) == float res = System.Math.Abs(-50.5) assert res == 50.5 assert type(res) == float res = System.Math.Max(50.5, 50.1) assert res == 50.5 assert type(res) == float res = System.Math.Max(System.Double(10.5), System.Double(50.5)) assert res == 50.5 assert type(res) == float # Should it return a System.Double? res = System.Math.Max(System.Double(50.5), 50.1) assert res == 50.5 assert type(res) == float def test_no_object_in_param(): """Test that fix for #203 doesn't break behavior w/ no object overload""" res = MethodTest.TestOverloadedNoObject(5) assert res == "Got int" res = MethodTest.TestOverloadedNoObject(i=7) assert res == "Got int" with pytest.raises(TypeError): MethodTest.TestOverloadedNoObject("test") with pytest.raises(TypeError): MethodTest.TestOverloadedNoObject(5.5) # Ensure that the top-level error is TypeError even if the inner error is an OverflowError with pytest.raises(TypeError): MethodTest.TestOverloadedNoObject(2147483648) def test_object_in_param(): """Test regression introduced by #151 in which Object method overloads aren't being used. See #203 for issue.""" res = MethodTest.TestOverloadedObject(5) assert res == "Got int" res = MethodTest.TestOverloadedObject(i=7) assert res == "Got int" res = MethodTest.TestOverloadedObject("test") assert res == "Got object" res = MethodTest.TestOverloadedObject(o="test") assert res == "Got object" def test_object_in_multiparam(): """Test method with object multiparams behaves""" res = MethodTest.TestOverloadedObjectTwo(5, 5) assert res == "Got int-int" res = MethodTest.TestOverloadedObjectTwo(5, "foo") assert res == "Got int-string" res = MethodTest.TestOverloadedObjectTwo("foo", 7.24) assert res == "Got string-object" res = MethodTest.TestOverloadedObjectTwo("foo", "bar") assert res == "Got string-string" res = MethodTest.TestOverloadedObjectTwo("foo", 5) assert res == "Got string-int" res = MethodTest.TestOverloadedObjectTwo(7.24, 7.24) assert res == "Got object-object" res = MethodTest.TestOverloadedObjectTwo(a=5, b=5) assert res == "Got int-int" res = MethodTest.TestOverloadedObjectTwo(5, b=5) assert res == "Got int-int" res = MethodTest.TestOverloadedObjectTwo(a=5, b="foo") assert res == "Got int-string" res = MethodTest.TestOverloadedObjectTwo(5, b="foo") assert res == "Got int-string" res = MethodTest.TestOverloadedObjectTwo(a="foo", b=7.24) assert res == "Got string-object" res = MethodTest.TestOverloadedObjectTwo("foo", b=7.24) assert res == "Got string-object" res = MethodTest.TestOverloadedObjectTwo(a="foo", b="bar") assert res == "Got string-string" res = MethodTest.TestOverloadedObjectTwo("foo", b="bar") assert res == "Got string-string" res = MethodTest.TestOverloadedObjectTwo(a="foo", b=5) assert res == "Got string-int" res = MethodTest.TestOverloadedObjectTwo("foo", b=5) assert res == "Got string-int" res = MethodTest.TestOverloadedObjectTwo(a=7.24, b=7.24) assert res == "Got object-object" res = MethodTest.TestOverloadedObjectTwo(7.24, b=7.24) assert res == "Got object-object" def test_object_in_multiparam_exception(): """Test method with object multiparams behaves""" with pytest.raises(TypeError) as excinfo: MethodTest.TestOverloadedObjectThree("foo", "bar") e = excinfo.value c = e.__cause__ assert c.GetType().FullName == 'System.AggregateException' assert len(c.InnerExceptions) == 2 def test_case_sensitive(): """Test that case-sensitivity is respected. GH#81""" res = MethodTest.CaseSensitive() assert res == "CaseSensitive" res = MethodTest.Casesensitive() assert res == "Casesensitive" with pytest.raises(AttributeError): MethodTest.casesensitive() def test_getting_generic_method_binding_does_not_leak_ref_count(): """Test that managed object is freed after calling generic method. Issue #691""" from PlainOldNamespace import PlainOldClass import sys refCount = sys.getrefcount(PlainOldClass().GenericMethod[str]) assert refCount == 1 def test_getting_generic_method_binding_does_not_leak_memory(): """Test that managed object is freed after calling generic method. Issue #691""" from PlainOldNamespace import PlainOldClass import psutil, os, gc, clr process = psutil.Process(os.getpid()) processBytesBeforeCall = process.memory_info().rss print("\n\nMemory consumption (bytes) at start of test: " + str(processBytesBeforeCall)) iterations = 500 for i in range(iterations): PlainOldClass().GenericMethod[str] gc.collect() System.GC.Collect() processBytesAfterCall = process.memory_info().rss print("Memory consumption (bytes) at end of test: " + str(processBytesAfterCall)) processBytesDelta = processBytesAfterCall - processBytesBeforeCall print("Memory delta: " + str(processBytesDelta)) bytesAllocatedPerIteration = pow(2, 20) # 1MB bytesLeakedPerIteration = processBytesDelta / iterations # Allow 50% threshold - this shows the original issue is fixed, which leaks the full allocated bytes per iteration failThresholdBytesLeakedPerIteration = bytesAllocatedPerIteration / 2 assert bytesLeakedPerIteration < failThresholdBytesLeakedPerIteration def test_getting_overloaded_method_binding_does_not_leak_ref_count(): """Test that managed object is freed after calling overloaded method. Issue #691""" from PlainOldNamespace import PlainOldClass import sys refCount = sys.getrefcount(PlainOldClass().OverloadedMethod.Overloads[int]) assert refCount == 1 def test_getting_overloaded_method_binding_does_not_leak_memory(): """Test that managed object is freed after calling overloaded method. Issue #691""" from PlainOldNamespace import PlainOldClass import psutil, os, gc, clr process = psutil.Process(os.getpid()) processBytesBeforeCall = process.memory_info().rss print("\n\nMemory consumption (bytes) at start of test: " + str(processBytesBeforeCall)) iterations = 500 for i in range(iterations): PlainOldClass().OverloadedMethod.Overloads[int] gc.collect() System.GC.Collect() processBytesAfterCall = process.memory_info().rss print("Memory consumption (bytes) at end of test: " + str(processBytesAfterCall)) processBytesDelta = processBytesAfterCall - processBytesBeforeCall print("Memory delta: " + str(processBytesDelta)) bytesAllocatedPerIteration = pow(2, 20) # 1MB bytesLeakedPerIteration = processBytesDelta / iterations # Allow 50% threshold - this shows the original issue is fixed, which leaks the full allocated bytes per iteration failThresholdBytesLeakedPerIteration = bytesAllocatedPerIteration / 2 assert bytesLeakedPerIteration < failThresholdBytesLeakedPerIteration def test_getting_method_overloads_binding_does_not_leak_ref_count(): """Test that managed object is freed after calling overloaded method. Issue #691""" from PlainOldNamespace import PlainOldClass import sys refCount = sys.getrefcount(PlainOldClass().OverloadedMethod.Overloads) assert refCount == 1 @pytest.mark.xfail(reason="Fails locally, need to investigate later", strict=False) def test_getting_method_overloads_binding_does_not_leak_memory(): """Test that managed object is freed after calling overloaded method. Issue #691""" from PlainOldNamespace import PlainOldClass import psutil, os, gc, clr process = psutil.Process(os.getpid()) processBytesBeforeCall = process.memory_info().rss print("\n\nMemory consumption (bytes) at start of test: " + str(processBytesBeforeCall)) iterations = 500 for i in range(iterations): PlainOldClass().OverloadedMethod.Overloads gc.collect() System.GC.Collect() processBytesAfterCall = process.memory_info().rss print("Memory consumption (bytes) at end of test: " + str(processBytesAfterCall)) processBytesDelta = processBytesAfterCall - processBytesBeforeCall print("Memory delta: " + str(processBytesDelta)) bytesAllocatedPerIteration = pow(2, 20) # 1MB bytesLeakedPerIteration = processBytesDelta / iterations # Allow 50% threshold - this shows the original issue is fixed, which leaks the full allocated bytes per iteration failThresholdBytesLeakedPerIteration = bytesAllocatedPerIteration / 2 assert bytesLeakedPerIteration < failThresholdBytesLeakedPerIteration def test_getting_overloaded_constructor_binding_does_not_leak_ref_count(): """Test that managed object is freed after calling overloaded constructor, constructorbinding.cs mp_subscript. Issue #691""" from PlainOldNamespace import PlainOldClass import sys # simple test refCount = sys.getrefcount(PlainOldClass.Overloads[int]) assert refCount == 1 def test_default_params(): # all positional parameters res = MethodTest.DefaultParams(1,2,3,4) assert res == "1234" res = MethodTest.DefaultParams(1, 2, 3) assert res == "1230" res = MethodTest.DefaultParams(1, 2) assert res == "1200" res = MethodTest.DefaultParams(1) assert res == "1000" res = MethodTest.DefaultParams(a=2) assert res == "2000" res = MethodTest.DefaultParams(b=3) assert res == "0300" res = MethodTest.DefaultParams(c=4) assert res == "0040" res = MethodTest.DefaultParams(d=7) assert res == "0007" res = MethodTest.DefaultParams(a=2, c=5) assert res == "2050" res = MethodTest.DefaultParams(1, d=7, c=3) assert res == "1037" with pytest.raises(TypeError): MethodTest.DefaultParams(1,2,3,4,5) def test_optional_params(): res = MethodTest.OptionalParams(1, 2, 3, 4) assert res == "1234" res = MethodTest.OptionalParams(1, 2, 3) assert res == "1230" res = MethodTest.OptionalParams(1, 2) assert res == "1200" res = MethodTest.OptionalParams(1) assert res == "1000" res = MethodTest.OptionalParams(a=2) assert res == "2000" res = MethodTest.OptionalParams(b=3) assert res == "0300" res = MethodTest.OptionalParams(c=4) assert res == "0040" res = MethodTest.OptionalParams(d=7) assert res == "0007" res = MethodTest.OptionalParams(a=2, c=5) assert res == "2050" res = MethodTest.OptionalParams(1, d=7, c=3) assert res == "1037" res = MethodTest.OptionalParams_TestMissing() assert res == True res = MethodTest.OptionalParams_TestMissing(None) assert res == False res = MethodTest.OptionalParams_TestMissing(a = None) assert res == False res = MethodTest.OptionalParams_TestMissing(a='hi') assert res == False res = MethodTest.OptionalParams_TestReferenceType() assert res == True res = MethodTest.OptionalParams_TestReferenceType(None) assert res == True res = MethodTest.OptionalParams_TestReferenceType(a=None) assert res == True res = MethodTest.OptionalParams_TestReferenceType('hi') assert res == False res = MethodTest.OptionalParams_TestReferenceType(a='hi') assert res == False def test_optional_and_default_params(): res = MethodTest.OptionalAndDefaultParams() assert res == "0000" res = MethodTest.OptionalAndDefaultParams(1) assert res == "1000" res = MethodTest.OptionalAndDefaultParams(1, c=4) assert res == "1040" res = MethodTest.OptionalAndDefaultParams(b=4, c=7) assert res == "0470" res = MethodTest.OptionalAndDefaultParams2() assert res == "0012" res = MethodTest.OptionalAndDefaultParams2(a=1,b=2,c=3,d=4) assert res == "1234" res = MethodTest.OptionalAndDefaultParams2(b=2, c=3) assert res == "0232" def test_default_params_overloads(): res = MethodTest.DefaultParamsWithOverloading(1, 2) assert res == "12" res = MethodTest.DefaultParamsWithOverloading(b=5) assert res == "25" res = MethodTest.DefaultParamsWithOverloading("d") assert res == "dbX" res = MethodTest.DefaultParamsWithOverloading(b="c") assert res == "acX" res = MethodTest.DefaultParamsWithOverloading(c=3) assert res == "013XX" res = MethodTest.DefaultParamsWithOverloading(5, c=2) assert res == "512XX" res = MethodTest.DefaultParamsWithOverloading(c=0, d=1) assert res == "5601XXX" res = MethodTest.DefaultParamsWithOverloading(1, d=1) assert res == "1671XXX" def test_default_params_overloads_ambiguous_call(): with pytest.raises(TypeError): MethodTest.DefaultParamsWithOverloading() def test_keyword_arg_method_resolution(): from Python.Test import MethodArityTest ob = MethodArityTest() assert ob.Foo(1, b=2) == "Arity 2" def test_params_array_overload(): res = MethodTest.ParamsArrayOverloaded() assert res == "without params-array" res = MethodTest.ParamsArrayOverloaded(1) assert res == "without params-array" res = MethodTest.ParamsArrayOverloaded(i=1) assert res == "without params-array" res = MethodTest.ParamsArrayOverloaded(1, 2) assert res == "with params-array" res = MethodTest.ParamsArrayOverloaded(1, 2, 3) assert res == "with params-array" res = MethodTest.ParamsArrayOverloaded(1, paramsArray=[]) assert res == "with params-array" res = MethodTest.ParamsArrayOverloaded(1, i=1) assert res == "with params-array" res = MethodTest.ParamsArrayOverloaded(1, 2, 3, i=1) assert res == "with params-array" @pytest.mark.skip(reason="FIXME: incorrectly failing") def test_params_array_overloaded_failing(): res = MethodTest.ParamsArrayOverloaded(1, 2, i=1) assert res == "with params-array" res = MethodTest.ParamsArrayOverloaded(paramsArray=[], i=1) assert res == "with params-array" def test_method_encoding(): MethodTest.EncodingTestà ngström() def test_method_with_pointer_array_argument(): with pytest.raises(TypeError): MethodTest.PointerArray([0]) def test_method_call_implicit_conversion(): class IntAnswerMixin: # For Python >= 3.8 def __index__(self): return 42 # For Python < 3.10 def __int__(self): return 42 class Answer(int, IntAnswerMixin): pass class FloatAnswer(float, IntAnswerMixin): def __float__(self): return 42.0 # TODO: This should also work for integer types but due to some complexities # in the C-API functions (some call __int__/__index__, some don't), it's not # supported, yet. for v in [Answer(), FloatAnswer()]: for t in [System.Double, System.Single]: min_value = t(t.MinValue) compare_to = min_value.CompareTo.__overloads__[t] assert compare_to(v) == -1 class SomeNonFloat: def __float__(self): return 42.0 for t in [System.Double, System.Single]: with pytest.raises(TypeError): min_value = t(t.MinValue) compare_to = min_value.CompareTo.__overloads__[t] assert compare_to(SomeNonFloat()) == -1