From: <pj...@us...> - 2011-03-14 16:30:25
|
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. |