Skip to content

Commit 533ff6f

Browse files
committed
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.
1 parent f3c4ad1 commit 533ff6f

File tree

4 files changed

+33
-0
lines changed

4 files changed

+33
-0
lines changed

Doc/lib/libfuncs.tex

+5
Original file line numberDiff line numberDiff line change
@@ -771,7 +771,12 @@ \section{Built-in Functions \label{built-in-funcs}}
771771
x = property(getx, setx, delx, "I'm the 'x' property.")
772772
\end{verbatim}
773773

774+
If given, \var{doc} will be the docstring of the property attribute.
775+
Otherwise, the property will copy \var{fget}'s docstring (if it
776+
exists).
777+
774778
\versionadded{2.2}
779+
\versionchanged[Use \var{fget}'s docstring if no \var{doc} given]{2.5}
775780
\end{funcdesc}
776781

777782
\begin{funcdesc}{range}{\optional{start,} stop\optional{, step}}

Lib/test/test_descr.py

+12
Original file line numberDiff line numberDiff line change
@@ -2008,6 +2008,18 @@ class D(object):
20082008
else:
20092009
raise TestFailed, "expected ZeroDivisionError from bad property"
20102010

2011+
class E(object):
2012+
def getter(self):
2013+
"getter method"
2014+
return 0
2015+
def setter(self, value):
2016+
"setter method"
2017+
pass
2018+
prop = property(getter)
2019+
vereq(prop.__doc__, "getter method")
2020+
prop2 = property(fset=setter)
2021+
vereq(prop2.__doc__, None)
2022+
20112023
def supers():
20122024
if verbose: print "Testing super..."
20132025

Misc/NEWS

+4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ What's New in Python 2.5 alpha 1?
1212
Core and builtins
1313
-----------------
1414

15+
- Patch #1434038: property() now uses the getter's docstring if there is
16+
no "doc" argument given. This makes it possible to legitimately use
17+
property() as a decorator to produce a read-only property.
18+
1519
- PEP 357, patch 1436368: add an __index__ method to int/long and a matching
1620
nb_index slot to the PyNumberMethods struct. The slot is consulted instead
1721
of requiring an int or long in slicing and a few other contexts, enabling

Objects/descrobject.c

+12
Original file line numberDiff line numberDiff line change
@@ -1081,6 +1081,8 @@ PyWrapper_New(PyObject *d, PyObject *self)
10811081
class property(object):
10821082
10831083
def __init__(self, fget=None, fset=None, fdel=None, doc=None):
1084+
if doc is None and fget is not None and hasattr(fget, "__doc__"):
1085+
doc = fget.__doc__
10841086
self.__get = fget
10851087
self.__set = fset
10861088
self.__del = fdel
@@ -1182,6 +1184,7 @@ static int
11821184
property_init(PyObject *self, PyObject *args, PyObject *kwds)
11831185
{
11841186
PyObject *get = NULL, *set = NULL, *del = NULL, *doc = NULL;
1187+
PyObject *get_doc = NULL;
11851188
static char *kwlist[] = {"fget", "fset", "fdel", "doc", 0};
11861189
propertyobject *gs = (propertyobject *)self;
11871190

@@ -1196,6 +1199,15 @@ property_init(PyObject *self, PyObject *args, PyObject *kwds)
11961199
if (del == Py_None)
11971200
del = NULL;
11981201

1202+
/* if no docstring given and the getter has one, use that one */
1203+
if ((doc == NULL || doc == Py_None) && get != NULL &&
1204+
PyObject_HasAttrString(get, "__doc__")) {
1205+
if (!(get_doc = PyObject_GetAttrString(get, "__doc__")))
1206+
return -1;
1207+
Py_DECREF(get_doc); /* it is INCREF'd again below */
1208+
doc = get_doc;
1209+
}
1210+
11991211
Py_XINCREF(get);
12001212
Py_XINCREF(set);
12011213
Py_XINCREF(del);

0 commit comments

Comments
 (0)