[Jython-checkins] jython: Partial fix of #2476: Restore workability of functools.wraps() by adding

stefan.richthofer jython-checkins at python.org
Mon Feb 6 21:18:16 EST 2017


https://hg.python.org/jython/rev/f56f3eeca6f2
changeset:   8017:f56f3eeca6f2
user:        Stefan Richthofer <stefan.richthofer at gmx.de>
date:        Tue Feb 07 03:17:39 2017 +0100
summary:
  Partial fix of #2476: Restore workability of functools.wraps() by adding __module__ field to PyReflectedFunction. Also moves forward #2475.

files:
  src/org/python/core/PyJavaType.java          |  28 ++++++++-
  src/org/python/core/PyReflectedFunction.java |  10 ++-
  2 files changed, 31 insertions(+), 7 deletions(-)


diff --git a/src/org/python/core/PyJavaType.java b/src/org/python/core/PyJavaType.java
--- a/src/org/python/core/PyJavaType.java
+++ b/src/org/python/core/PyJavaType.java
@@ -24,6 +24,7 @@
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Queue;
@@ -304,6 +305,8 @@
         Arrays.sort(methods, new MethodComparator(new ClassComparator()));
 
         boolean isInAwt = name.startsWith("java.awt.") && name.indexOf('.', 9) == -1;
+        ArrayList<PyReflectedFunction> reflectedFuncs = new ArrayList<>(methods.length);
+        PyReflectedFunction reflfunc;
         for (Method meth : methods) {
             if (!declaredOnMember(baseClass, meth) || ignore(meth)) {
                 continue;
@@ -319,9 +322,11 @@
             }
 
             String nmethname = normalize(methname);
-            PyReflectedFunction reflfunc = (PyReflectedFunction)dict.__finditem__(nmethname);
+            reflfunc = (PyReflectedFunction) dict.__finditem__(nmethname);
             if (reflfunc == null) {
-                dict.__setitem__(nmethname, new PyReflectedFunction(meth));
+                reflfunc = new PyReflectedFunction(meth);
+                reflectedFuncs.add(reflfunc);
+                dict.__setitem__(nmethname, reflfunc);
             } else {
                 reflfunc.addMethod(meth);
             }
@@ -390,7 +395,7 @@
         // Add superclass methods
         for (Method meth : methods) {
             String nmethname = normalize(meth.getName());
-            PyReflectedFunction reflfunc = (PyReflectedFunction)dict.__finditem__(nmethname);
+            reflfunc = (PyReflectedFunction)dict.__finditem__(nmethname);
             if (reflfunc != null) {
                 // The superclass method has the same name as one declared on this class, so add
                 // the superclass version's arguments
@@ -401,7 +406,9 @@
                 // visible from Java on this class, so do the same for Python here.  This is the
                 // flipside of what handleSuperMethodArgCollisions does for inherited public methods
                 // on package protected classes.
-                dict.__setitem__(nmethname, new PyReflectedFunction(meth));
+                reflfunc = new PyReflectedFunction(meth);
+                reflectedFuncs.add(reflfunc);
+                dict.__setitem__(nmethname, reflfunc);
             }
         }
 
@@ -557,12 +564,13 @@
             }
         }
 
+        PyObject nameSpecified = null;
         if (ClassDictInit.class.isAssignableFrom(forClass) && forClass != ClassDictInit.class) {
             try {
                 Method m = forClass.getMethod("classDictInit", PyObject.class);
                 m.invoke(null, dict);
                 // allow the class to override its name after it is loaded
-                PyObject nameSpecified = dict.__finditem__("__name__");
+                nameSpecified = dict.__finditem__("__name__");
                 if (nameSpecified != null) {
                     name = nameSpecified.toString();
                 }
@@ -571,6 +579,16 @@
             }
         }
 
+        // Fill __module__ attribute of PyReflectedFunctions...
+        if (reflectedFuncs.size() > 0) {
+            if (nameSpecified == null) {
+                nameSpecified = Py.newString(name);
+            }
+            for (PyReflectedFunction func: reflectedFuncs) {
+                func.__module__ = nameSpecified;
+            }
+        }
+
         if (baseClass != Object.class) {
             hasGet = getDescrMethod(forClass, "__get__", OO) != null
                     || getDescrMethod(forClass, "_doget", PyObject.class) != null
diff --git a/src/org/python/core/PyReflectedFunction.java b/src/org/python/core/PyReflectedFunction.java
--- a/src/org/python/core/PyReflectedFunction.java
+++ b/src/org/python/core/PyReflectedFunction.java
@@ -13,6 +13,8 @@
 
     public PyObject __doc__ = Py.None;
 
+    public PyObject __module__ = Py.None;
+
     public ReflectedArgs[] argslist = new ReflectedArgs[1];
 
     public int nargs;
@@ -64,6 +66,7 @@
     public PyReflectedFunction copy() {
         PyReflectedFunction func = new PyReflectedFunction(__name__);
         func.__doc__ = __doc__;
+        func.__module__ = __module__;
         func.nargs = nargs;
         func.argslist = new ReflectedArgs[nargs];
         System.arraycopy(argslist, 0, func.argslist, 0, nargs);
@@ -158,7 +161,6 @@
         ReflectedCallData callData = new ReflectedCallData();
         ReflectedArgs match = null;
         for (int i = 0; i < nargs && match == null; i++) {
-            // System.err.println(rargs.toString());
             if (argslist[i].matches(self, args, keywords, callData)) {
                 match = argslist[i];
             }
@@ -340,11 +342,15 @@
     /* Traverseproc implementation */
     @Override
     public int traverse(Visitproc visit, Object arg) {
+        if (__module__ != null) {
+            int res = visit.visit(__module__, arg);
+            if (res != 0) return res;
+        }
         return __doc__ != null ? visit.visit(__doc__, arg) : 0;
     }
 
     @Override
     public boolean refersDirectlyTo(PyObject ob) {
-        return ob != null && ob == __doc__;
+        return ob != null && (ob == __doc__ || ob == __module__);
     }
 }

-- 
Repository URL: https://hg.python.org/jython


More information about the Jython-checkins mailing list