From 533ff6fc0622bfae5d13d3a3838fbec3d9d21092 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Wed, 8 Mar 2006 18:09:27 +0000 Subject: 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. --- Doc/lib/libfuncs.tex | 5 +++++ Lib/test/test_descr.py | 12 ++++++++++++ Misc/NEWS | 4 ++++ Objects/descrobject.c | 12 ++++++++++++ 4 files changed, 33 insertions(+) diff --git a/Doc/lib/libfuncs.tex b/Doc/lib/libfuncs.tex index 12dbc0c..9b6bfe9 100644 --- a/Doc/lib/libfuncs.tex +++ b/Doc/lib/libfuncs.tex @@ -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}} diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 68a11fa..57a8f44 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -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..." diff --git a/Misc/NEWS b/Misc/NEWS index 6657f3a..ed4e97b 100644 --- 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 diff --git a/Objects/descrobject.c b/Objects/descrobject.c index b96ad6e..9494062 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -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); -- cgit v0.12