diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs
index 22aaf33e4..0d1ddccac 100644
--- a/src/runtime/methodbinder.cs
+++ b/src/runtime/methodbinder.cs
@@ -375,8 +375,20 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw,
Runtime.Decref(pyoptype);
if (!typematch)
{
- margs = null;
- break;
+ if (SimplePromotableType(clrtype, pi[n].ParameterType))
+ {
+ if (!Converter.ToManaged(op, pi[n].ParameterType, out arg, false))
+ {
+ margs = null;// basically we are failing this match, but can't throw yet
+ break;
+ }
+ }
+ else
+ {
+ margs = null;
+ break;
+ }
+
}
}
else
@@ -455,6 +467,19 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw,
}
return null;
}
+ ///
+ /// Returns true if src type (int -type) is promotable to a higher resolution type (float|double)
+ /// no sanity check for overflow is done, this is done elsewhere when performing
+ /// the actual conversion.
+ ///
+ ///
+ ///
+ ///
+ ///
+ private bool SimplePromotableType(Type src, Type dst)
+ {
+ return (((src == typeof(int) || src == typeof(short) || src == typeof(long) ) && (dst == typeof(double) || dst == typeof(float))));
+ }
internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw)
{
diff --git a/src/testing/constructortests.cs b/src/testing/constructortests.cs
index cffcee888..b7d39d1f6 100644
--- a/src/testing/constructortests.cs
+++ b/src/testing/constructortests.cs
@@ -7,7 +7,28 @@ namespace Python.Test
//========================================================================
// These classes support the CLR constructor unit tests.
//========================================================================
-
+ public class AConstructorTest
+ {
+ public string name;
+ public AConstructorTest(string n) { name = n; }
+ }
+ public class LinkConstructorTest
+ {
+ public LinkConstructorTest()
+ {
+ DefaultCtCalled = true;
+ }
+ public LinkConstructorTest(AConstructorTest a,double matchMe,AConstructorTest b)
+ {
+ MatchMe = matchMe;
+ a1 = a;
+ a2 = b;
+ }
+ public bool DefaultCtCalled;
+ public double MatchMe;
+ public AConstructorTest a1;
+ public AConstructorTest a2;
+ }
public class EnumConstructorTest
{
public TypeCode value;
@@ -50,4 +71,36 @@ public SubclassConstructorTest(Exception v)
this.value = v;
}
}
+ public class ToDoubleConstructorTest
+ {
+ public ToDoubleConstructorTest()
+ {
+ //Just default values
+ }
+ public ToDoubleConstructorTest(string a, double b,string c)
+ {
+ this.a = a;
+ this.b = b;
+ this.c = c;
+ }
+ public string a;
+ public double b;
+ public string c;
+ }
+ public class ToFloatConstructorTest
+ {
+ public ToFloatConstructorTest()
+ {
+ // just default values.
+ }
+ public ToFloatConstructorTest(string a, float b, string c)
+ {
+ this.a = a;
+ this.b = b;
+ this.c = c;
+ }
+ public string a;
+ public float b;
+ public string c;
+ }
}
\ No newline at end of file
diff --git a/src/testing/methodtest.cs b/src/testing/methodtest.cs
index 675b1577c..fcdbbd1cc 100644
--- a/src/testing/methodtest.cs
+++ b/src/testing/methodtest.cs
@@ -73,6 +73,24 @@ public Guid TestStructConversion(Guid v)
{
return v;
}
+ ///
+ /// Method to support testing
+ /// simple promotion of numeric types:
+ ///
+ /// integer types -> double
+ ///
+ ///
+ ///
+ ///
+ ///
+ public double TestSimpleIntToDoubleTypePromotion(double a, double b)
+ {
+ return a + b;
+ }
+ public float TestSimpleIntToFloatTypePromotion(float a, float b)
+ {
+ return a + b;
+ }
public Exception TestSubclassConversion(Exception v)
{
diff --git a/src/tests/test_constructors.py b/src/tests/test_constructors.py
index fdc1ef060..d7bb80cab 100644
--- a/src/tests/test_constructors.py
+++ b/src/tests/test_constructors.py
@@ -5,6 +5,8 @@
import Python.Test as Test
import System
+constructor_throw_on_arg_match_is_fixed = False # currently, failed match on super() is silently ignored, and tests will fail if set to true
+constructor_to_sub_class_accepts_specific_parameters= False # currently, we can't pass arguments to super() class ct.
class ConstructorTests(unittest.TestCase):
"""Test CLR class constructor support."""
@@ -44,9 +46,90 @@ class sub(System.Exception):
instance = sub()
ob = SubclassConstructorTest(instance)
- print(ob)
self.assertTrue(isinstance(ob.value, System.Exception))
+ def testSubClassWithInternalArgsPassedToSuper(self):
+ """
+ Verify we can sub-class a .NET class, in python,
+ and pass a working set of arguments to our super class.
+ """
+ from Python.Test import ToDoubleConstructorTest # does the job for this test
+
+ class PySubClass(ToDoubleConstructorTest):
+ def __init__(self,d):
+ super(PySubClass, self).__init__('a',2.0,'c')
+ self.d = d
+
+ o = PySubClass('d')
+ self.assertEqual( o.d,'d')
+ if constructor_to_sub_class_accepts_specific_parameters:
+ self.assertEqual( o.a,'a')
+ self.assertAlmostEqual(o.b,2.0)
+ self.assertEqual( o.c,'c')
+ else:
+ print("\n\n*** Warning passing parameters to super class is currently not verified\n")
+
+
+ def testConstructorArgumentMatching(self):
+ """ Test that simple type promitions works for int->double """
+ from Python.Test import AConstructorTest, LinkConstructorTest
+ a1=AConstructorTest('a1')
+ a2=AConstructorTest('a2')
+ self.assertEqual(a1.name,'a1')
+ self.assertEqual(a2.name, 'a2')
+ l1=LinkConstructorTest(a1,3000,a2)
+ #l2=LinkConstructorTest(a1,3000.0,a2)
+ self.assertEqual(l1.a1.name, a1.name)
+ self.assertEqual(l1.a2.name, a2.name)
+ self.assertAlmostEqual(3000.0,l1.MatchMe)
+
+ def testIntToDoubleConstructorArguments(self):
+ from Python.Test import ToDoubleConstructorTest
+
+ o = ToDoubleConstructorTest('a',2,'c')
+ self.assertEqual(o.a,'a')
+ self.assertAlmostEqual(o.b,2)
+ self.assertEqual(o.c,'c')
+
+ o = ToDoubleConstructorTest() # just to verify the default constructor is there
+
+ def testIntToFloatConstructorArguments(self):
+ from Python.Test import ToFloatConstructorTest
+
+ o = ToFloatConstructorTest('a',2,'c')
+ self.assertEqual(o.a,'a')
+ self.assertAlmostEqual(o.b,2)
+ self.assertEqual(o.c,'c')
+
+ o = ToFloatConstructorTest()
+
+ def testConstructorRaiseExceptionIfNoMatch(self):
+ """
+ Notice: Due to the feature of .NET object as super-class, there is a
+ 'hack' that after calling a constructor with the supplied arguments
+ (and they fail to match the .NET class constructor for any reason)
+ then it removes all the arguments, and retry the call.
+ Now, if this succeeds, it will return an object, with default values.
+ This *could* make sense, given that the .NET class *IS* subclassed,
+ however, if the process is *not* a part of a sub-class construction,
+ then this is at best very unexpected.
+
+
+ """
+
+ from Python.Test import ToDoubleConstructorTest
+
+
+ if constructor_throw_on_arg_match_is_fixed:
+ try:
+ o = ToDoubleConstructorTest('a','not a number','c') # this should raise exception, because there are no match!
+ except TypeError:
+ return
+ self.fail("exception should be raised for non-matching constructor atempt")
+ else:
+ print("\n\n*** Warning: failing arg match on constructors are currently silently accepted if there is a null constructor\n")
+
+
def test_suite():
return unittest.makeSuite(ConstructorTests)
diff --git a/src/tests/test_method.py b/src/tests/test_method.py
index 4728d13e4..a00b024d1 100644
--- a/src/tests/test_method.py
+++ b/src/tests/test_method.py
@@ -208,6 +208,43 @@ def testMethodCallFlagsConversion(self):
r = object.TestFlagsConversion(flags)
self.assertTrue(r == flags)
+ def testSimpleTypePromotionIntToDouble(self):
+ object = MethodTest()
+ sum_of_a_plus_b = object.TestSimpleIntToDoubleTypePromotion(2,2)
+ self.assertAlmostEqual(sum_of_a_plus_b,2+2)
+ sum_of_a_plus_b = object.TestSimpleIntToDoubleTypePromotion(2.0,2)
+ self.assertAlmostEqual(sum_of_a_plus_b,2+2)
+ sum_of_a_plus_b = object.TestSimpleIntToDoubleTypePromotion(2,2.0)
+ self.assertAlmostEqual(sum_of_a_plus_b,2+2)
+ sum_of_a_plus_b = object.TestSimpleIntToDoubleTypePromotion(2.0,2.0)
+ self.assertAlmostEqual(sum_of_a_plus_b,2.0+2.0)
+
+ #with self.assertRaises(TypeError), wont work on py 2.6, so ..
+ try:
+ should_fail = object.TestSimpleIntToDoubleTypePromotion(2,'x2.0')
+ except TypeError:
+ return
+ self.fail("A string (not convertible to number), should throw type error")
+ # TODO: consider this for consistence: bool True-> 1.0, False -> 0.0
+
+ def testSimpleTypePromotionIntToFloat(self):
+ object = MethodTest()
+
+ sum_of_a_plus_b = object.TestSimpleIntToFloatTypePromotion(2,2)
+ self.assertAlmostEqual(sum_of_a_plus_b,2+2)
+ sum_of_a_plus_b = object.TestSimpleIntToFloatTypePromotion(2.0,2)
+ self.assertAlmostEqual(sum_of_a_plus_b,2+2)
+ sum_of_a_plus_b = object.TestSimpleIntToFloatTypePromotion(2,2.0)
+ self.assertAlmostEqual(sum_of_a_plus_b,2+2)
+ sum_of_a_plus_b = object.TestSimpleIntToFloatTypePromotion(2.0,2.0)
+ self.assertAlmostEqual(sum_of_a_plus_b,2.0+2.0)
+ try:
+ should_fail = object.TestSimpleIntToFloatTypePromotion(2,'x2.0')
+ except TypeError:
+ return
+ self.fail("A string (not convertible to number), should throw type error")
+ # TODO: consider this for consistence: bool True-> 1.0, False -> 0.0
+
def testMethodCallStructConversion(self):
"""Test struct conversion in method call."""
from System import Guid