Patch #1434038: property() now uses the getter's docstring if there is
authorGeorg Brandl <georg@python.org>
Wed, 8 Mar 2006 18:09:27 +0000 (18:09 +0000)
committerGeorg Brandl <georg@python.org>
Wed, 8 Mar 2006 18:09:27 +0000 (18:09 +0000)
no "doc" argument given. This makes it possible to legitimately use
property() as a decorator to produce a read-only property.

Doc/lib/libfuncs.tex
Lib/test/test_descr.py
Misc/NEWS
Objects/descrobject.c

index 12dbc0c3454549016696b1124abf9ab96385f4f2..9b6bfe9d7b4c5604acc0089245290d977d132ae0 100644 (file)
@@ -771,7 +771,12 @@ class C(object):
     x = property(getx, setx, delx, "I'm the 'x' property.")
 \end{verbatim}
 
+  If given, \var{doc} will be the docstring of the property attribute.
+  Otherwise, the property will copy \var{fget}'s docstring (if it
+  exists).
+
   \versionadded{2.2}
+  \versionchanged[Use \var{fget}'s docstring if no \var{doc} given]{2.5}
 \end{funcdesc}
 
 \begin{funcdesc}{range}{\optional{start,} stop\optional{, step}}
index 68a11facdc12dcc9ceb47c0714de7c73821e79ed..57a8f4454e6c2d9d400693833c4ef056328ea0aa 100644 (file)
@@ -2008,6 +2008,18 @@ def properties():
     else:
         raise TestFailed, "expected ZeroDivisionError from bad property"
 
+    class E(object):
+        def getter(self):
+            "getter method"
+            return 0
+        def setter(self, value):
+            "setter method"
+            pass
+        prop = property(getter)
+        vereq(prop.__doc__, "getter method")
+        prop2 = property(fset=setter)
+        vereq(prop2.__doc__, None)
+
 def supers():
     if verbose: print "Testing super..."
 
index 6657f3ad631f8ef56cd4c2c637e806057d6d48de..ed4e97be7a50348d51465324fa1a0a48c3ef6a74 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,10 @@ What's New in Python 2.5 alpha 1?
 Core and builtins
 -----------------
 
+- Patch #1434038: property() now uses the getter's docstring if there is
+  no "doc" argument given. This makes it possible to legitimately use
+  property() as a decorator to produce a read-only property.
+
 - PEP 357, patch 1436368: add an __index__ method to int/long and a matching
   nb_index slot to the PyNumberMethods struct.  The slot is consulted instead
   of requiring an int or long in slicing and a few other contexts, enabling
index b96ad6e7e65c1f94a3fd3c74210325915e24e241..949406250fc10e11794c91c4bade8766d370a1f3 100644 (file)
@@ -1081,6 +1081,8 @@ PyWrapper_New(PyObject *d, PyObject *self)
     class property(object):
 
         def __init__(self, fget=None, fset=None, fdel=None, doc=None):
+            if doc is None and fget is not None and hasattr(fget, "__doc__"):
+                doc = fget.__doc__
             self.__get = fget
             self.__set = fset
             self.__del = fdel
@@ -1182,6 +1184,7 @@ static int
 property_init(PyObject *self, PyObject *args, PyObject *kwds)
 {
        PyObject *get = NULL, *set = NULL, *del = NULL, *doc = NULL;
+       PyObject *get_doc = NULL;
        static char *kwlist[] = {"fget", "fset", "fdel", "doc", 0};
        propertyobject *gs = (propertyobject *)self;
 
@@ -1196,6 +1199,15 @@ property_init(PyObject *self, PyObject *args, PyObject *kwds)
        if (del == Py_None)
                del = NULL;
 
+       /* if no docstring given and the getter has one, use that one */
+       if ((doc == NULL || doc == Py_None) && get != NULL && 
+           PyObject_HasAttrString(get, "__doc__")) {
+               if (!(get_doc = PyObject_GetAttrString(get, "__doc__")))
+                       return -1;
+               Py_DECREF(get_doc); /* it is INCREF'd again below */
+               doc = get_doc;
+       }
+
        Py_XINCREF(get);
        Py_XINCREF(set);
        Py_XINCREF(del);