SF.net SVN: jython:[7237] trunk/jython/src/org/python/core/PyProperty.java

[email protected] Mon, 14 Mar 2011 16:30:19 +0000
Newsgroups gmane.comp.lang.jython.cvs
Message-ID <[email protected]>
Revision: 7237
          http://jython.svn.sourceforge.net/jython/?rev=7237&view=rev
Author:   pjenvey
Date:     2011-03-14 16:30:18 +0000 (Mon, 14 Mar 2011)

Log Message:
-----------
add property.getter/setter/deleter

Modified Paths:
--------------
    trunk/jython/src/org/python/core/PyProperty.java

Modified: trunk/jython/src/org/python/core/PyProperty.java
===================================================================
--- trunk/jython/src/org/python/core/PyProperty.java	2011-03-14 04:31:54 UTC (rev 7236)
+++ trunk/jython/src/org/python/core/PyProperty.java	2011-03-14 16:30:18 UTC (rev 7237)
@@ -1,3 +1,4 @@
+/* Copyright (c) Jython Developers */
 package org.python.core;
 
 import org.python.expose.ExposedGet;
@@ -19,6 +20,9 @@
     @ExposedGet(doc = BuiltinDocs.property_fdel_doc)
     protected PyObject fdel;
 
+    /** Whether this property's __doc__ was copied from its getter. */
+    protected boolean docFromGetter;
+
     @ExposedGet(name = "__doc__")
     protected PyObject doc;
 
@@ -30,9 +34,8 @@
         super(subType);
     }
 
-    //XXX: needs __doc__
     @ExposedNew
-    @ExposedMethod
+    @ExposedMethod(doc = BuiltinDocs.property___init___doc)
     public void property___init__(PyObject[] args, String[] keywords) {
         ArgParser ap = new ArgParser("property", args, keywords,
                                      new String[] {"fget", "fset", "fdel", "doc"}, 0);
@@ -46,14 +49,24 @@
 
         // if no docstring given and the getter has one, use fget's
         if ((doc == null || doc == Py.None) && fget != null) {
-            doc = fget.__findattr__("__doc__");
+            PyObject getDoc = fget.__findattr__("__doc__");
+            if (getType() == TYPE) {
+                doc = getDoc;
+            } else {
+                // Put __doc__ in dict of the subclass instance instead, otherwise it gets
+                // shadowed by class's __doc__
+                __setattr__("__doc__", getDoc);
+            }
+            docFromGetter = true;
         }
     }
 
+    @Override
     public PyObject __call__(PyObject arg1, PyObject args[], String keywords[]) {
         return fget.__call__(arg1);
     }
 
+    @Override
     public PyObject __get__(PyObject obj, PyObject type) {
         return property___get__(obj,type);
     }
@@ -69,6 +82,7 @@
         return fget.__call__(obj);
     }
 
+    @Override
     public void __set__(PyObject obj, PyObject value) {
         property___set__(obj, value);
     }
@@ -81,6 +95,7 @@
         fset.__call__(obj, value);
     }
 
+    @Override
     public void __delete__(PyObject obj) {
         property___delete__(obj);
     }
@@ -92,4 +107,57 @@
         }
         fdel.__call__(obj);
     }
+
+    public PyObject getter(PyObject getter) {
+        return property_getter(getter);
+    }
+
+    @ExposedMethod(doc = BuiltinDocs.property_getter_doc)
+    final PyObject property_getter(PyObject getter) {
+        return propertyCopy(getter, null, null);
+    }
+
+    public PyObject setter(PyObject setter) {
+        return property_setter(setter);
+    }
+
+    @ExposedMethod(doc = BuiltinDocs.property_setter_doc)
+    final PyObject property_setter(PyObject setter) {
+        return propertyCopy(null, setter, null);
+    }
+
+    public PyObject deleter(PyObject deleter) {
+        return property_deleter(deleter);
+    }
+
+    @ExposedMethod(doc = BuiltinDocs.property_deleter_doc)
+    final PyObject property_deleter(PyObject deleter) {
+        return propertyCopy(null, null, deleter);
+    }
+
+    /**
+     * Return a copy of this property with the optional addition of a get/set/del. Helper
+     * method for the getter/setter/deleter methods.
+     */
+    private PyObject propertyCopy(PyObject get, PyObject set, PyObject del) {
+        if (get == null) {
+            get = fget != null ? fget : Py.None;
+        }
+        if (set == null) {
+            set = fset != null ? fset : Py.None;
+        }
+        if (del == null) {
+            del = fdel != null ? fdel : Py.None;
+        }
+
+        PyObject doc;
+        if (docFromGetter) {
+            // make _init use __doc__ from getter
+            doc = Py.None;
+        } else {
+            doc = this.doc != null ? this.doc : Py.None;
+        }
+
+        return getType().__call__(get, set, del, doc);
+    }
 }


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.

------------------------------------------------------------------------------
Colocation vs. Managed Hosting
A question and answer guide to determining the best fit
for your organization - today and in the future.
http://p.sf.net/sfu/internap-sfd2d