From 6daccdd2d547af0a4eddbb4924b4c8a035290e9f Mon Sep 17 00:00:00 2001 From: denfromufa Date: Sat, 27 Feb 2016 04:30:22 -0600 Subject: [PATCH] fixes overloading of integer types which is py2/3 version dependent, added tests for checking overloading behavior for main value types --- demo/wordpad.py | 2 +- src/runtime/converter.cs | 35 +++++++++++++++++++++++++++ src/runtime/methodbinder.cs | 48 +++++++++++++++++++++++++------------ src/tests/test_generic.py | 33 +++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 16 deletions(-) diff --git a/demo/wordpad.py b/demo/wordpad.py index 32844b1d4..a67deef23 100644 --- a/demo/wordpad.py +++ b/demo/wordpad.py @@ -205,7 +205,7 @@ def InitializeComponent(self): self.richTextBox.TabIndex = 0 self.richTextBox.AutoSize = 1 self.richTextBox.ScrollBars = WinForms.RichTextBoxScrollBars.ForcedBoth - self.richTextBox.Font = System.Drawing.Font("Tahoma", 10) + self.richTextBox.Font = System.Drawing.Font("Tahoma", 10.0) self.richTextBox.AcceptsTab = 1 self.richTextBox.Location = System.Drawing.Point(0, 0) diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs index 039294d13..effde4bc4 100644 --- a/src/runtime/converter.cs +++ b/src/runtime/converter.cs @@ -29,7 +29,10 @@ private Converter() {} static NumberFormatInfo nfi; static Type objectType; static Type stringType; + static Type singleType; static Type doubleType; + static Type decimalType; + static Type int16Type; static Type int32Type; static Type int64Type; static Type flagsType; @@ -40,9 +43,12 @@ static Converter () { nfi = NumberFormatInfo.InvariantInfo; objectType = typeof(Object); stringType = typeof(String); + int16Type = typeof(Int16); int32Type = typeof(Int32); int64Type = typeof(Int64); + singleType = typeof(Single); doubleType = typeof(Double); + decimalType = typeof(Decimal); flagsType = typeof(FlagsAttribute); boolType = typeof(Boolean); typeType = typeof(Type); @@ -73,6 +79,35 @@ internal static Type GetTypeByAlias(IntPtr op) { return null; } + internal static IntPtr GetPythonTypeByAlias(Type op) + { + if (op == stringType) { + return Runtime.PyUnicodeType; + } +#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) + else if ((op == int16Type) || + (op == int32Type) || + (op == int64Type)) { + return Runtime.PyIntType; + } +#endif + else if ((op == int16Type) || + (op == int32Type)) { + return Runtime.PyIntType; + } + else if (op == int64Type) { + return Runtime.PyLongType; + } + else if ((op == doubleType) || + (op == singleType)) { + return Runtime.PyFloatType; + } + else if (op == boolType) { + return Runtime.PyBoolType; + } + return IntPtr.Zero; + } + //==================================================================== // Return a Python object for the given native object, converting diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index 8760ad26f..2464ea790 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -245,7 +245,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, else { _methods = GetMethods(); } - Type type; + Type clrtype; for (int i = 0; i < _methods.Length; i++) { MethodBase mi = _methods[i]; @@ -295,34 +295,52 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, // this logic below handles cases when multiple overloading methods // are ambiguous, hence comparison between Python and CLR types // is necessary - type = null; - - if (_methods.Length>1) { - IntPtr pyoptype = IntPtr.Zero; + clrtype = null; + IntPtr pyoptype; + if (_methods.Length > 1) { + pyoptype = IntPtr.Zero; pyoptype = Runtime.PyObject_Type(op); Exceptions.Clear(); - if (pyoptype != IntPtr.Zero) { } - type = Converter.GetTypeByAlias(pyoptype); - Runtime.Decref(pyoptype); + if (pyoptype != IntPtr.Zero) { + clrtype = Converter.GetTypeByAlias(pyoptype); } + Runtime.Decref(pyoptype); + } - if (type != null) { - if (pi[n].ParameterType != type) { - margs = null; - break; + if (clrtype != null) { + if (pi[n].ParameterType != clrtype) { + IntPtr pytype = Converter.GetPythonTypeByAlias(pi[n].ParameterType); + pyoptype = Runtime.PyObject_Type(op); + Exceptions.Clear(); + if (pyoptype != IntPtr.Zero) { + if (pytype != pyoptype) { + Runtime.Decref(pyoptype); + margs = null; + break; + } + else { + clrtype = pi[n].ParameterType; + } + } + else { + Runtime.Decref(pyoptype); + margs = null; + break; + } + Runtime.Decref(pyoptype); } } else { - type = pi[n].ParameterType; + clrtype = pi[n].ParameterType; } - if (pi[n].IsOut || type.IsByRef) + if (pi[n].IsOut || clrtype.IsByRef) { outs++; } - if (!Converter.ToManaged(op, type, out arg, false)) + if (!Converter.ToManaged(op, clrtype, out arg, false)) { Exceptions.Clear(); margs = null; diff --git a/src/tests/test_generic.py b/src/tests/test_generic.py index d7ae2e26b..bb2b7fbbc 100644 --- a/src/tests/test_generic.py +++ b/src/tests/test_generic.py @@ -341,6 +341,39 @@ def testGenericMethodTypeHandling(self): self._testGenericMethodByType(InterfaceTest, InterfaceTest(), 1) self._testGenericMethodByType(ISayHello1, InterfaceTest(), 1) + def testCorrectOverloadSelection(self): + """ + Test correct overloading selection for common types. + """ + from System.Drawing import Font + + from System import (String, Double, Single, + Int16, Int32, Int64) + from System import Math + + substr = String("substring") + self.assertTrue(substr.Substring(2) == substr.Substring.__overloads__[Int32]( + Int32(2))) + self.assertTrue(substr.Substring(2, 3) == substr.Substring.__overloads__[Int32,Int32]( + Int32(2), Int32(3))) + + for atype, value1, value2 in zip([Double, Single, Int16, Int32, Int64], + [1.0, 1.0, 1, 1, 1], + [2.0, 0.5, 2, 0, -1]): + self.assertTrue(Math.Abs(atype(value1)) == Math.Abs.__overloads__[atype](atype(value1))) + self.assertTrue(Math.Abs(value1) == Math.Abs.__overloads__[atype](atype(value1))) + self.assertTrue( + Math.Max(atype(value1), + atype(value2)) == Math.Max.__overloads__[atype, atype]( + atype(value1), + atype(value2))) + if (atype is Int64) and six.PY2: + value2 = long(value2) + self.assertTrue( + Math.Max(atype(value1), + value2) == Math.Max.__overloads__[atype, atype]( + atype(value1), + atype(value2))) def testGenericMethodOverloadSelection(self): """