From: <zy...@us...> - 2010-09-08 07:18:55
|
Revision: 7113 http://jython.svn.sourceforge.net/jython/?rev=7113&view=rev Author: zyasoft Date: 2010-09-08 07:18:48 +0000 (Wed, 08 Sep 2010) Log Message: ----------- Fixed #1503, Java constructors should take keyword arguments. Thanks Geoffrey French! Modified Paths: -------------- trunk/jython/NEWS trunk/jython/src/org/python/core/PyReflectedConstructor.java Modified: trunk/jython/NEWS =================================================================== --- trunk/jython/NEWS 2010-09-08 06:27:14 UTC (rev 7112) +++ trunk/jython/NEWS 2010-09-08 07:18:48 UTC (rev 7113) @@ -2,6 +2,7 @@ Jython 2.5.2b2 Bugs Fixed + - [ 1503 ] Java constructors should take keyword arguments - [ 1648 ] Incomplete implementation of pep328 for relative imports - [ 1611 ] Jython bytecode violated JLS, causing NPE on Sun's JVM when using -Xcomp option - [ 1643 ] Tools subdirectory still exists in trunk Modified: trunk/jython/src/org/python/core/PyReflectedConstructor.java =================================================================== --- trunk/jython/src/org/python/core/PyReflectedConstructor.java 2010-09-08 06:27:14 UTC (rev 7112) +++ trunk/jython/src/org/python/core/PyReflectedConstructor.java 2010-09-08 07:18:48 UTC (rev 7113) @@ -115,32 +115,77 @@ } ReflectedCallData callData = new ReflectedCallData(); Object method = null; - // Remove keyword args + + // If we have keyword args, there are two ways this can be handled; + // a) we find a constructor that takes keyword args, and use it. + // b) we don't, in which case we strip the keyword args, and pass the + // non-keyword args, and then use the keyword args to set bean properties + // If we don't have keyword args; just look for a constructor that + // takes the right number of args. int nkeywords = keywords.length; + ReflectedArgs rargs = null; PyObject[] allArgs = args; + boolean usingKeywordArgsCtor = false; if (nkeywords > 0) { - args = new PyObject[allArgs.length - nkeywords]; - System.arraycopy(allArgs, 0, args, 0, args.length); - } - // Check for a matching constructor to call - int n = nargs; - for (int i = 0; i < n; i++) { - ReflectedArgs rargs = argslist[i]; - if (rargs.matches(null, args, Py.NoKeywords, callData)) { - method = rargs.data; - break; + // We have keyword args. + + // Look for a constructor; the ReflectedArgs#matches() method exits early in the case + // where keyword args are used + int n = nargs; + for (int i = 0; i < n; i++) { + rargs = argslist[i]; + if (rargs.matches(null, args, keywords, callData)) { + method = rargs.data; + break; + } } - } + + if (method != null) { + // Constructor found that will accept the keyword args + usingKeywordArgsCtor = true; + } else { + // No constructor found that will take keyword args + + // Remove the keyword args + args = new PyObject[allArgs.length - nkeywords]; + System.arraycopy(allArgs, 0, args, 0, args.length); + + // Look for a constructor with no keyword args + for (int i = 0; i < n; i++) { + rargs = argslist[i]; + if (rargs.matches(null, args, Py.NoKeywords, callData)) { + method = rargs.data; + break; + } + } + } + } else { + // Just look for a constructor with no keyword args + int n = nargs; + for (int i = 0; i < n; i++) { + rargs = argslist[i]; + if (rargs.matches(null, args, Py.NoKeywords, callData)) { + method = rargs.data; + break; + } + } + } + // Throw an error if no valid set of arguments if (method == null) { throwError(callData.errArg, args.length, false, false); } // Do the actual constructor call constructProxy(self, (Constructor<?>)method, callData.getArgsArray(), javaClass); - // Do setattr's for keyword args - int offset = args.length; - for (int i = 0; i < nkeywords; i++) { - self.__setattr__(keywords[i], allArgs[i + offset]); + // Do setattr's for keyword args. This convenience allows Java bean properties to be set in + // by a Python constructor call. + // However, this is not done if the Java constructor accepts (PyObject[], String[]) as its arguments, + // in which case the intention is that the Java constructor will handle the keyword arguments itself. + if (!usingKeywordArgsCtor) { + int offset = args.length; + for (int i = 0; i < nkeywords; i++) { + self.__setattr__(keywords[i], allArgs[i + offset]); + } } return Py.None; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |