From 686385cdac5b0613174739607fd1aef90f817431 Mon Sep 17 00:00:00 2001 From: Danny Date: Fri, 31 Jul 2015 14:35:57 -0600 Subject: [PATCH 1/4] initial changes to add default arguments --- src/runtime/classobject.cs | 26 ++++++++++- src/runtime/indexer.cs | 56 +++++++++++++++++++++++- src/runtime/methodbinder.cs | 71 ++++++++++++++++++++---------- src/testing/indexertest.cs | 17 ++++++++ src/testing/methodtest.cs | 10 +++++ src/tests/test_indexer.py | 13 ++++++ src/tests/test_method.py | 87 +++++++++++++++++++++---------------- 7 files changed, 216 insertions(+), 64 deletions(-) diff --git a/src/runtime/classobject.cs b/src/runtime/classobject.cs index 5e79e8253..261512ea2 100644 --- a/src/runtime/classobject.cs +++ b/src/runtime/classobject.cs @@ -223,7 +223,6 @@ public static int mp_ass_subscript(IntPtr ob, IntPtr idx, IntPtr v) { // Arg may be a tuple in the case of an indexer with multiple // parameters. If so, use it directly, else make a new tuple // with the index arg (method binders expect arg tuples). - IntPtr args = idx; bool free = false; @@ -234,6 +233,7 @@ public static int mp_ass_subscript(IntPtr ob, IntPtr idx, IntPtr v) { free = true; } + // Add args given from caller int i = Runtime.PyTuple_Size(args); IntPtr real = Runtime.PyTuple_New(i + 1); for (int n = 0; n < i; n++) { @@ -241,6 +241,30 @@ public static int mp_ass_subscript(IntPtr ob, IntPtr idx, IntPtr v) { Runtime.Incref(item); Runtime.PyTuple_SetItem(real, n, item); } + + // Do we need default arguments added to the list + if (cls.indexer.NeedsDefaultArgs(ob, real)) { + IntPtr defaultArgs = cls.indexer.GetDefaultArgs(ob, real); + int sizeOfDefaultArgs = Runtime.PyTuple_Size(defaultArgs); + int temp = i + sizeOfDefaultArgs; + real = Runtime.PyTuple_New(temp + 1); + for (int n = 0; n < i; n++) { + IntPtr item = Runtime.PyTuple_GetItem(args, n); + Runtime.Incref(item); + Runtime.PyTuple_SetItem(real, n, item); + } + + for (int n = 0; n < sizeOfDefaultArgs; n++) { + + IntPtr item = Runtime.PyTuple_GetItem(defaultArgs, n); + Runtime.Incref(item); + Runtime.PyTuple_SetItem(real, n + i, item); + } + + i = temp; + } + + // Add value to argument list Runtime.Incref(v); Runtime.PyTuple_SetItem(real, i, v); diff --git a/src/runtime/indexer.cs b/src/runtime/indexer.cs index 8118dc339..d65940947 100644 --- a/src/runtime/indexer.cs +++ b/src/runtime/indexer.cs @@ -62,7 +62,61 @@ internal void SetItem(IntPtr inst, IntPtr args) { SetterBinder.Invoke(inst, args, IntPtr.Zero); } - } + internal bool NeedsDefaultArgs(IntPtr inst, IntPtr args){ + int pynargs = Runtime.PyTuple_Size(args) - 1; + var methods = SetterBinder.GetMethods(); + if(methods.Length == 0) + return false; + + MethodBase mi = methods[0]; + ParameterInfo[] pi = mi.GetParameters(); + // need to subtract one for the value + int clrnargs = pi.Length - 1; + if(pynargs == clrnargs) + return false; + + for (int v = pynargs; v < clrnargs; v++){ + if (pi[v].DefaultValue == DBNull.Value) + return false; + } + return true; + } + + internal IntPtr GetDefaultArgs(IntPtr inst, IntPtr args){ + //IntPtr real = Runtime.PyTuple_New(i + 1); + int pynargs = Runtime.PyTuple_Size(args) - 1; + var methods = SetterBinder.GetMethods(); + IntPtr defaultArgs; + if(methods.Length == 0){ + defaultArgs = Runtime.PyTuple_New(0); + return defaultArgs; + } + MethodBase mi = methods[0]; + ParameterInfo[] pi = mi.GetParameters(); + int clrnargs = pi.Length - 1; + if(pynargs == clrnargs|| pynargs > clrnargs){ + defaultArgs = Runtime.PyTuple_New(0); + return defaultArgs; + } + defaultArgs = Runtime.PyTuple_New(clrnargs - pynargs); + for (int i = 0; i < (clrnargs - pynargs); i++) { + // Here we own the reference to the Python value, and we + // give the ownership to the arg tuple. + if (pi[i + pynargs].DefaultValue == DBNull.Value) + continue; + else{ + IntPtr arg = Converter.ToPython(pi[i + pynargs].DefaultValue, pi[i + pynargs].ParameterType); + Type type = typeof(String); + Object arg2; + Converter.ToManaged(arg, type, out arg2, false); + Runtime.PyTuple_SetItem(defaultArgs, i, arg); + } + } + return defaultArgs; + } + + + } } diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index 80d3968fd..3b83ca379 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -226,7 +226,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, int pynargs = Runtime.PyTuple_Size(args); object arg; bool isGeneric = false; - + ArrayList defaultArgList = null; if (info != null) { _methods = (MethodBase[])Array.CreateInstance( typeof(MethodBase), 1 @@ -247,7 +247,17 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, int outs = 0; if (pynargs == clrnargs) { - match = true; + match = true; + } else if(pynargs < clrnargs){ + match = true; + defaultArgList = new ArrayList(); + for (int v = pynargs; v < clrnargs; v++) + { + if (pi[v].DefaultValue == DBNull.Value) + match = false; + else + defaultArgList.Add((object)pi[v].DefaultValue); + } } else if ((pynargs > clrnargs) && (clrnargs > 0) && (pi[clrnargs-1].ParameterType.IsArray)) { // The last argument of the mananged functions seems to @@ -262,30 +272,43 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, for (int n = 0; n < clrnargs; n++) { IntPtr op; - if (arrayStart == n) { - // map remaining Python arguments to a tuple since - // the managed function accepts it - hopefully :] - op = Runtime.PyTuple_GetSlice(args, arrayStart, pynargs); - } - else { - op = Runtime.PyTuple_GetItem(args, n); - } - Type type = pi[n].ParameterType; - if (pi[n].IsOut || type.IsByRef) { - outs++; - } - - if (!Converter.ToManaged(op, type, out arg, false)) { - Exceptions.Clear(); - margs = null; - break; + if (n < pynargs) + { + if (arrayStart == n) + { + // map remaining Python arguments to a tuple since + // the managed function accepts it - hopefully :] + op = Runtime.PyTuple_GetSlice(args, arrayStart, pynargs); + } + else + { + op = Runtime.PyTuple_GetItem(args, n); + } + Type type = pi[n].ParameterType; + if (pi[n].IsOut || type.IsByRef) + { + outs++; + } + + if (!Converter.ToManaged(op, type, out arg, false)) + { + Exceptions.Clear(); + margs = null; + break; + } + if (arrayStart == n) + { + // GetSlice() creates a new reference but GetItem() + // returns only a borrow reference. + Runtime.Decref(op); + } + margs[n] = arg; } - if (arrayStart == n) { - // GetSlice() creates a new reference but GetItem() - // returns only a borrow reference. - Runtime.Decref(op); + else + { + if (defaultArgList != null) + margs[n] = defaultArgList[n - pynargs]; } - margs[n] = arg; } if (margs == null) { diff --git a/src/testing/indexertest.cs b/src/testing/indexertest.cs index fa4a8c8e2..7caba4e64 100644 --- a/src/testing/indexertest.cs +++ b/src/testing/indexertest.cs @@ -347,6 +347,23 @@ public MultiTypeIndexerTest() : base() {} } + public class MultiDefaultKeyIndexerTest : IndexerBase { + + public MultiDefaultKeyIndexerTest() : base() { } + + public string this[int i1, int i2 = 2] { + get { + string key = i1.ToString() + i2.ToString(); + return (string)t[key]; + } + set { + string key = i1.ToString() + i2.ToString(); + t[key] = value; + } + } + + } + diff --git a/src/testing/methodtest.cs b/src/testing/methodtest.cs index 086aa58d5..8bda5215f 100644 --- a/src/testing/methodtest.cs +++ b/src/testing/methodtest.cs @@ -155,6 +155,16 @@ public static void TestVoidSingleRefParam (ref int i) { i = 42; } + public static int TestSingleDefaultParam(int i = 5) { + return i; + } + public static int TestTwoDefaultParam(int i = 5, int j = 6) { + return i + j; + } + public static int TestOneArgAndTwoDefaultParam(int z, int i = 5, int j = 6) { + return i + j + z; + } + // overload selection test support diff --git a/src/tests/test_indexer.py b/src/tests/test_indexer.py index cb572e3a8..691ebb871 100644 --- a/src/tests/test_indexer.py +++ b/src/tests/test_indexer.py @@ -8,6 +8,8 @@ # =========================================================================== import sys, os, string, unittest, types +import clr +clr.AddReference("Python.Test") import Python.Test as Test import six @@ -630,6 +632,17 @@ def test(): object[0, 1, spam] = "wrong" self.assertRaises(TypeError, test) + + + def testMultiDefaultKeyIndexer(self): + """Test indexers that take multiple indices with a default key arguments.""" + #default argument is 2 in the MultiDefaultKeyIndexerTest object + object = Test.MultiDefaultKeyIndexerTest() + object[0, 2] = "zero one spam" + self.assertTrue(object[0] == "zero one spam") + + object[1] = "one nine spam" + self.assertTrue(object[1, 2] == "one nine spam") def testIndexerWrongKeyType(self): diff --git a/src/tests/test_method.py b/src/tests/test_method.py index cdfc1e33b..af855847a 100644 --- a/src/tests/test_method.py +++ b/src/tests/test_method.py @@ -13,12 +13,6 @@ from Python.Test import MethodTest, MethodTestSub import System -import six - -if six.PY3: - long = int - unichr = chr - class MethodTests(unittest.TestCase): """Test CLR method support.""" @@ -241,11 +235,11 @@ def testMethodCallStructConversion(self): def testSubclassInstanceConversion(self): """Test subclass instance conversion in method call.""" - class TestSubException(System.Exception): + class sub(System.Exception): pass object = MethodTest() - instance = TestSubException() + instance = sub() result = object.TestSubclassConversion(instance) self.assertTrue(isinstance(result, System.Exception)) @@ -447,6 +441,27 @@ def test(): # None cannot be converted to a value type self.assertRaises(TypeError, test) + + def testSingleDefaultParam(self): + """Test void method with single ref-parameter.""" + result = MethodTest.TestSingleDefaultParam() + self.assertTrue(result == 5) + + def testOneArgAndTwoDefaultParam(self): + """Test void method with single ref-parameter.""" + result = MethodTest.TestOneArgAndTwoDefaultParam(11) + self.assertTrue(result == 22) + + result = MethodTest.TestOneArgAndTwoDefaultParam(15) + self.assertTrue(result == 26) + + result = MethodTest.TestOneArgAndTwoDefaultParam(20) + self.assertTrue(result == 31) + + def testTwoDefaultParam(self): + """Test void method with single ref-parameter.""" + result = MethodTest.TestTwoDefaultParam() + self.assertTrue(result == 11) def testExplicitSelectionWithOutModifier(self): @@ -507,8 +522,8 @@ def testExplicitOverloadSelection(self): value = MethodTest.Overloaded.__overloads__[System.SByte](127) self.assertTrue(value == 127) - value = MethodTest.Overloaded.__overloads__[System.Char](six.u('A')) - self.assertTrue(value == six.u('A')) + value = MethodTest.Overloaded.__overloads__[System.Char](u'A') + self.assertTrue(value == u'A') value = MethodTest.Overloaded.__overloads__[System.Char](65535) self.assertTrue(value == unichr(65535)) @@ -523,27 +538,25 @@ def testExplicitOverloadSelection(self): self.assertTrue(value == 2147483647) value = MethodTest.Overloaded.__overloads__[System.Int64]( - long(9223372036854775807) + 9223372036854775807L ) - self.assertTrue(value == long(9223372036854775807)) + self.assertTrue(value == 9223372036854775807L) - # Python 3 has no explicit long type, use System.Int64 instead - if not six.PY3: - value = MethodTest.Overloaded.__overloads__[long]( - long(9223372036854775807) - ) - self.assertTrue(value == long(9223372036854775807)) + value = MethodTest.Overloaded.__overloads__[long]( + 9223372036854775807L + ) + self.assertTrue(value == 9223372036854775807L) value = MethodTest.Overloaded.__overloads__[System.UInt16](65000) self.assertTrue(value == 65000) - value = MethodTest.Overloaded.__overloads__[System.UInt32](long(4294967295)) - self.assertTrue(value == long(4294967295)) + value = MethodTest.Overloaded.__overloads__[System.UInt32](4294967295L) + self.assertTrue(value == 4294967295L) value = MethodTest.Overloaded.__overloads__[System.UInt64]( - long(18446744073709551615) + 18446744073709551615L ) - self.assertTrue(value == long(18446744073709551615)) + self.assertTrue(value == 18446744073709551615L) value = MethodTest.Overloaded.__overloads__[System.Single](3.402823e38) self.assertTrue(value == 3.402823e38) @@ -625,10 +638,10 @@ def testOverloadSelectionWithArrayTypes(self): self.assertTrue(value[1] == 127) vtype = Array[System.Char] - input = vtype([six.u('A'), six.u('Z')]) + input = vtype([u'A', u'Z']) value = MethodTest.Overloaded.__overloads__[vtype](input) - self.assertTrue(value[0] == six.u('A')) - self.assertTrue(value[1] == six.u('Z')) + self.assertTrue(value[0] == u'A') + self.assertTrue(value[1] == u'Z') vtype = Array[System.Char] input = vtype([0, 65535]) @@ -655,18 +668,16 @@ def testOverloadSelectionWithArrayTypes(self): self.assertTrue(value[1] == 2147483647) vtype = Array[System.Int64] - input = vtype([0, long(9223372036854775807)]) + input = vtype([0, 9223372036854775807L]) value = MethodTest.Overloaded.__overloads__[vtype](input) self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == long(9223372036854775807)) + self.assertTrue(value[1] == 9223372036854775807L) - # Python 3 has no explicit long type, use System.Int64 instead - if not six.PY3: - vtype = Array[long] - input = vtype([0, long(9223372036854775807)]) - value = MethodTest.Overloaded.__overloads__[vtype](input) - self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == long(9223372036854775807)) + vtype = Array[long] + input = vtype([0, 9223372036854775807L]) + value = MethodTest.Overloaded.__overloads__[vtype](input) + self.assertTrue(value[0] == 0) + self.assertTrue(value[1] == 9223372036854775807L) vtype = Array[System.UInt16] input = vtype([0, 65000]) @@ -675,16 +686,16 @@ def testOverloadSelectionWithArrayTypes(self): self.assertTrue(value[1] == 65000) vtype = Array[System.UInt32] - input = vtype([0, long(4294967295)]) + input = vtype([0, 4294967295L]) value = MethodTest.Overloaded.__overloads__[vtype](input) self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == long(4294967295)) + self.assertTrue(value[1] == 4294967295L) vtype = Array[System.UInt64] - input = vtype([0, long(18446744073709551615)]) + input = vtype([0, 18446744073709551615L]) value = MethodTest.Overloaded.__overloads__[vtype](input) self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == long(18446744073709551615)) + self.assertTrue(value[1] == 18446744073709551615L) vtype = Array[System.Single] input = vtype([0.0, 3.402823e38]) From 8b179ffcf9676c4c415e89a367c10d81a40e847d Mon Sep 17 00:00:00 2001 From: Danny Date: Sat, 1 Aug 2015 17:08:05 -0600 Subject: [PATCH 2/4] changed method signature to one arg and renamed a local variable name --- src/runtime/classobject.cs | 16 ++++++++-------- src/runtime/indexer.cs | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/runtime/classobject.cs b/src/runtime/classobject.cs index 261512ea2..1cb2e4afc 100644 --- a/src/runtime/classobject.cs +++ b/src/runtime/classobject.cs @@ -233,7 +233,7 @@ public static int mp_ass_subscript(IntPtr ob, IntPtr idx, IntPtr v) { free = true; } - // Add args given from caller + // Add args given from caller + 1 for the value int i = Runtime.PyTuple_Size(args); IntPtr real = Runtime.PyTuple_New(i + 1); for (int n = 0; n < i; n++) { @@ -243,10 +243,12 @@ public static int mp_ass_subscript(IntPtr ob, IntPtr idx, IntPtr v) { } // Do we need default arguments added to the list - if (cls.indexer.NeedsDefaultArgs(ob, real)) { - IntPtr defaultArgs = cls.indexer.GetDefaultArgs(ob, real); - int sizeOfDefaultArgs = Runtime.PyTuple_Size(defaultArgs); - int temp = i + sizeOfDefaultArgs; + if (cls.indexer.NeedsDefaultArgs(real)) { + // Need to add default args to the end of real tuple + // before adding the value v + IntPtr defaultArgs = cls.indexer.GetDefaultArgs(real); + int numOfDefaultArgs = Runtime.PyTuple_Size(defaultArgs); + int temp = i + numOfDefaultArgs; real = Runtime.PyTuple_New(temp + 1); for (int n = 0; n < i; n++) { IntPtr item = Runtime.PyTuple_GetItem(args, n); @@ -254,13 +256,11 @@ public static int mp_ass_subscript(IntPtr ob, IntPtr idx, IntPtr v) { Runtime.PyTuple_SetItem(real, n, item); } - for (int n = 0; n < sizeOfDefaultArgs; n++) { - + for (int n = 0; n < numOfDefaultArgs; n++) { IntPtr item = Runtime.PyTuple_GetItem(defaultArgs, n); Runtime.Incref(item); Runtime.PyTuple_SetItem(real, n + i, item); } - i = temp; } diff --git a/src/runtime/indexer.cs b/src/runtime/indexer.cs index d65940947..e4fda3973 100644 --- a/src/runtime/indexer.cs +++ b/src/runtime/indexer.cs @@ -62,7 +62,7 @@ internal void SetItem(IntPtr inst, IntPtr args) { SetterBinder.Invoke(inst, args, IntPtr.Zero); } - internal bool NeedsDefaultArgs(IntPtr inst, IntPtr args){ + internal bool NeedsDefaultArgs(IntPtr args){ int pynargs = Runtime.PyTuple_Size(args) - 1; var methods = SetterBinder.GetMethods(); if(methods.Length == 0) @@ -82,7 +82,7 @@ internal bool NeedsDefaultArgs(IntPtr inst, IntPtr args){ return true; } - internal IntPtr GetDefaultArgs(IntPtr inst, IntPtr args){ + internal IntPtr GetDefaultArgs(IntPtr args){ //IntPtr real = Runtime.PyTuple_New(i + 1); int pynargs = Runtime.PyTuple_Size(args) - 1; var methods = SetterBinder.GetMethods(); From daaa1312dd373ea5e0c6f12989930a6d68357b4b Mon Sep 17 00:00:00 2001 From: Danny Date: Sat, 1 Aug 2015 18:50:52 -0600 Subject: [PATCH 3/4] accidently overwrote original test script changes for python 3 testing --- src/tests/test_method.py | 66 +++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/src/tests/test_method.py b/src/tests/test_method.py index af855847a..3f9c1fdff 100644 --- a/src/tests/test_method.py +++ b/src/tests/test_method.py @@ -13,6 +13,12 @@ from Python.Test import MethodTest, MethodTestSub import System +import six + +if six.PY3: + long = int + unichr = chr + class MethodTests(unittest.TestCase): """Test CLR method support.""" @@ -235,11 +241,11 @@ def testMethodCallStructConversion(self): def testSubclassInstanceConversion(self): """Test subclass instance conversion in method call.""" - class sub(System.Exception): + class TestSubException(System.Exception): pass object = MethodTest() - instance = sub() + instance = TestSubException() result = object.TestSubclassConversion(instance) self.assertTrue(isinstance(result, System.Exception)) @@ -522,8 +528,8 @@ def testExplicitOverloadSelection(self): value = MethodTest.Overloaded.__overloads__[System.SByte](127) self.assertTrue(value == 127) - value = MethodTest.Overloaded.__overloads__[System.Char](u'A') - self.assertTrue(value == u'A') + value = MethodTest.Overloaded.__overloads__[System.Char](six.u('A')) + self.assertTrue(value == six.u('A')) value = MethodTest.Overloaded.__overloads__[System.Char](65535) self.assertTrue(value == unichr(65535)) @@ -538,25 +544,27 @@ def testExplicitOverloadSelection(self): self.assertTrue(value == 2147483647) value = MethodTest.Overloaded.__overloads__[System.Int64]( - 9223372036854775807L + long(9223372036854775807) ) - self.assertTrue(value == 9223372036854775807L) + self.assertTrue(value == long(9223372036854775807)) - value = MethodTest.Overloaded.__overloads__[long]( - 9223372036854775807L - ) - self.assertTrue(value == 9223372036854775807L) + # Python 3 has no explicit long type, use System.Int64 instead + if not six.PY3: + value = MethodTest.Overloaded.__overloads__[long]( + long(9223372036854775807) + ) + self.assertTrue(value == long(9223372036854775807)) value = MethodTest.Overloaded.__overloads__[System.UInt16](65000) self.assertTrue(value == 65000) - value = MethodTest.Overloaded.__overloads__[System.UInt32](4294967295L) - self.assertTrue(value == 4294967295L) + value = MethodTest.Overloaded.__overloads__[System.UInt32](long(4294967295)) + self.assertTrue(value == long(4294967295)) value = MethodTest.Overloaded.__overloads__[System.UInt64]( - 18446744073709551615L + long(18446744073709551615) ) - self.assertTrue(value == 18446744073709551615L) + self.assertTrue(value == long(18446744073709551615)) value = MethodTest.Overloaded.__overloads__[System.Single](3.402823e38) self.assertTrue(value == 3.402823e38) @@ -638,10 +646,10 @@ def testOverloadSelectionWithArrayTypes(self): self.assertTrue(value[1] == 127) vtype = Array[System.Char] - input = vtype([u'A', u'Z']) + input = vtype([six.u('A'), six.u('Z')]) value = MethodTest.Overloaded.__overloads__[vtype](input) - self.assertTrue(value[0] == u'A') - self.assertTrue(value[1] == u'Z') + self.assertTrue(value[0] == six.u('A')) + self.assertTrue(value[1] == six.u('Z')) vtype = Array[System.Char] input = vtype([0, 65535]) @@ -668,16 +676,18 @@ def testOverloadSelectionWithArrayTypes(self): self.assertTrue(value[1] == 2147483647) vtype = Array[System.Int64] - input = vtype([0, 9223372036854775807L]) + input = vtype([0, long(9223372036854775807)]) value = MethodTest.Overloaded.__overloads__[vtype](input) self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == 9223372036854775807L) + self.assertTrue(value[1] == long(9223372036854775807)) - vtype = Array[long] - input = vtype([0, 9223372036854775807L]) - value = MethodTest.Overloaded.__overloads__[vtype](input) - self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == 9223372036854775807L) + # Python 3 has no explicit long type, use System.Int64 instead + if not six.PY3: + vtype = Array[long] + input = vtype([0, long(9223372036854775807)]) + value = MethodTest.Overloaded.__overloads__[vtype](input) + self.assertTrue(value[0] == 0) + self.assertTrue(value[1] == long(9223372036854775807)) vtype = Array[System.UInt16] input = vtype([0, 65000]) @@ -686,16 +696,16 @@ def testOverloadSelectionWithArrayTypes(self): self.assertTrue(value[1] == 65000) vtype = Array[System.UInt32] - input = vtype([0, 4294967295L]) + input = vtype([0, long(4294967295)]) value = MethodTest.Overloaded.__overloads__[vtype](input) self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == 4294967295L) + self.assertTrue(value[1] == long(4294967295)) vtype = Array[System.UInt64] - input = vtype([0, 18446744073709551615L]) + input = vtype([0, long(18446744073709551615)]) value = MethodTest.Overloaded.__overloads__[vtype](input) self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == 18446744073709551615L) + self.assertTrue(value[1] == long(18446744073709551615)) vtype = Array[System.Single] input = vtype([0.0, 3.402823e38]) From 20d81f102f4329fabeba33852c75b73e647f2859 Mon Sep 17 00:00:00 2001 From: Danny Date: Mon, 3 Aug 2015 21:56:16 -0600 Subject: [PATCH 4/4] remove redundant code and add comments --- src/runtime/classobject.cs | 35 +++++++++++++---------------------- src/runtime/indexer.cs | 36 ++++++++++++++++-------------------- 2 files changed, 29 insertions(+), 42 deletions(-) diff --git a/src/runtime/classobject.cs b/src/runtime/classobject.cs index 1cb2e4afc..03f784ed7 100644 --- a/src/runtime/classobject.cs +++ b/src/runtime/classobject.cs @@ -233,36 +233,27 @@ public static int mp_ass_subscript(IntPtr ob, IntPtr idx, IntPtr v) { free = true; } - // Add args given from caller + 1 for the value + // Get the args passed in. int i = Runtime.PyTuple_Size(args); - IntPtr real = Runtime.PyTuple_New(i + 1); + IntPtr defaultArgs = cls.indexer.GetDefaultArgs(args); + int numOfDefaultArgs = Runtime.PyTuple_Size(defaultArgs); + int temp = i + numOfDefaultArgs; + IntPtr real = Runtime.PyTuple_New(temp + 1); for (int n = 0; n < i; n++) { IntPtr item = Runtime.PyTuple_GetItem(args, n); Runtime.Incref(item); Runtime.PyTuple_SetItem(real, n, item); } - // Do we need default arguments added to the list - if (cls.indexer.NeedsDefaultArgs(real)) { - // Need to add default args to the end of real tuple - // before adding the value v - IntPtr defaultArgs = cls.indexer.GetDefaultArgs(real); - int numOfDefaultArgs = Runtime.PyTuple_Size(defaultArgs); - int temp = i + numOfDefaultArgs; - real = Runtime.PyTuple_New(temp + 1); - for (int n = 0; n < i; n++) { - IntPtr item = Runtime.PyTuple_GetItem(args, n); - Runtime.Incref(item); - Runtime.PyTuple_SetItem(real, n, item); - } - - for (int n = 0; n < numOfDefaultArgs; n++) { - IntPtr item = Runtime.PyTuple_GetItem(defaultArgs, n); - Runtime.Incref(item); - Runtime.PyTuple_SetItem(real, n + i, item); - } - i = temp; + // Add Default Args if needed + for (int n = 0; n < numOfDefaultArgs; n++) { + IntPtr item = Runtime.PyTuple_GetItem(defaultArgs, n); + Runtime.Incref(item); + Runtime.PyTuple_SetItem(real, n + i, item); } + // no longer need defaultArgs + Runtime.Decref(defaultArgs); + i = temp; // Add value to argument list Runtime.Incref(v); diff --git a/src/runtime/indexer.cs b/src/runtime/indexer.cs index e4fda3973..0781a3a0a 100644 --- a/src/runtime/indexer.cs +++ b/src/runtime/indexer.cs @@ -63,7 +63,7 @@ internal void SetItem(IntPtr inst, IntPtr args) { } internal bool NeedsDefaultArgs(IntPtr args){ - int pynargs = Runtime.PyTuple_Size(args) - 1; + int pynargs = Runtime.PyTuple_Size(args); var methods = SetterBinder.GetMethods(); if(methods.Length == 0) return false; @@ -72,7 +72,7 @@ internal bool NeedsDefaultArgs(IntPtr args){ ParameterInfo[] pi = mi.GetParameters(); // need to subtract one for the value int clrnargs = pi.Length - 1; - if(pynargs == clrnargs) + if (pynargs == clrnargs || pynargs > clrnargs) return false; for (int v = pynargs; v < clrnargs; v++){ @@ -82,34 +82,30 @@ internal bool NeedsDefaultArgs(IntPtr args){ return true; } + /// + /// This will return default arguments a new instance of a tuple. The size + /// of the tuple will indicate the number of default arguments. + /// + /// This is pointing to the tuple args passed in + /// a new instance of the tuple containing the default args internal IntPtr GetDefaultArgs(IntPtr args){ - //IntPtr real = Runtime.PyTuple_New(i + 1); - int pynargs = Runtime.PyTuple_Size(args) - 1; + + // if we don't need default args return empty tuple + if(!NeedsDefaultArgs(args)) + return Runtime.PyTuple_New(0); + int pynargs = Runtime.PyTuple_Size(args); + + // Get the default arg tuple var methods = SetterBinder.GetMethods(); - IntPtr defaultArgs; - if(methods.Length == 0){ - defaultArgs = Runtime.PyTuple_New(0); - return defaultArgs; - } MethodBase mi = methods[0]; ParameterInfo[] pi = mi.GetParameters(); int clrnargs = pi.Length - 1; - if(pynargs == clrnargs|| pynargs > clrnargs){ - defaultArgs = Runtime.PyTuple_New(0); - return defaultArgs; - } - - defaultArgs = Runtime.PyTuple_New(clrnargs - pynargs); + IntPtr defaultArgs = Runtime.PyTuple_New(clrnargs - pynargs); for (int i = 0; i < (clrnargs - pynargs); i++) { - // Here we own the reference to the Python value, and we - // give the ownership to the arg tuple. if (pi[i + pynargs].DefaultValue == DBNull.Value) continue; else{ IntPtr arg = Converter.ToPython(pi[i + pynargs].DefaultValue, pi[i + pynargs].ParameterType); - Type type = typeof(String); - Object arg2; - Converter.ToManaged(arg, type, out arg2, false); Runtime.PyTuple_SetItem(defaultArgs, i, arg); } }