Issue 1416. Add getter, setter, deleter methods to properties that can be
used as decorators to create fully-populated properties.
This commit is contained in:
parent
d3ffd341b8
commit
d1ef78942a
|
@ -2131,6 +2131,71 @@ def properties():
|
|||
p = property(_testcapi.test_with_docstring)
|
||||
|
||||
|
||||
def properties_plus():
|
||||
class C:
|
||||
foo = property(doc="hello")
|
||||
@foo.getter
|
||||
def foo(self):
|
||||
return self._foo
|
||||
@foo.setter
|
||||
def foo(self, value):
|
||||
self._foo = abs(value)
|
||||
@foo.deleter
|
||||
def foo(self):
|
||||
del self._foo
|
||||
c = C()
|
||||
assert C.foo.__doc__ == "hello"
|
||||
assert not hasattr(c, "foo")
|
||||
c.foo = -42
|
||||
assert c.foo == 42
|
||||
del c.foo
|
||||
assert not hasattr(c, "foo")
|
||||
|
||||
class D(C):
|
||||
@C.foo.deleter
|
||||
def foo(self):
|
||||
try:
|
||||
del self._foo
|
||||
except AttributeError:
|
||||
pass
|
||||
d = D()
|
||||
d.foo = 24
|
||||
assert d.foo == 24
|
||||
del d.foo
|
||||
del d.foo
|
||||
|
||||
class E:
|
||||
@property
|
||||
def foo(self):
|
||||
return self._foo
|
||||
@foo.setter
|
||||
def foo (self, value):
|
||||
raise RuntimeError
|
||||
@foo.setter
|
||||
@foo.deleter
|
||||
def foo(self, value=None):
|
||||
if value is None:
|
||||
del self._foo
|
||||
else:
|
||||
self._foo = abs(value)
|
||||
e = E()
|
||||
e.foo = -42
|
||||
assert e.foo == 42
|
||||
del e.foo
|
||||
|
||||
class F(E):
|
||||
@E.foo.deleter
|
||||
def foo(self):
|
||||
del self._foo
|
||||
@foo.setter
|
||||
def foo(self, value):
|
||||
self._foo = max(0, value)
|
||||
f = F()
|
||||
f.foo = -10
|
||||
assert f.foo == 0
|
||||
del f.foo
|
||||
|
||||
|
||||
def supers():
|
||||
if verbose: print "Testing super..."
|
||||
|
||||
|
|
|
@ -1108,6 +1108,60 @@ static PyMemberDef property_members[] = {
|
|||
{0}
|
||||
};
|
||||
|
||||
PyDoc_STRVAR(getter_doc,
|
||||
"Descriptor to change the getter on a property.");
|
||||
|
||||
PyObject *
|
||||
property_getter(PyObject *self, PyObject *getter)
|
||||
{
|
||||
Py_XDECREF(((propertyobject *)self)->prop_get);
|
||||
if (getter == Py_None)
|
||||
getter = NULL;
|
||||
Py_XINCREF(getter);
|
||||
((propertyobject *)self)->prop_get = getter;
|
||||
Py_INCREF(self);
|
||||
return self;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(setter_doc,
|
||||
"Descriptor to change the setter on a property.\n");
|
||||
|
||||
PyObject *
|
||||
property_setter(PyObject *self, PyObject *setter)
|
||||
{
|
||||
Py_XDECREF(((propertyobject *)self)->prop_set);
|
||||
if (setter == Py_None)
|
||||
setter = NULL;
|
||||
Py_XINCREF(setter);
|
||||
((propertyobject *)self)->prop_set = setter;
|
||||
Py_INCREF(self);
|
||||
return self;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(deleter_doc,
|
||||
"Descriptor to change the deleter on a property.");
|
||||
|
||||
PyObject *
|
||||
property_deleter(PyObject *self, PyObject *deleter)
|
||||
{
|
||||
Py_XDECREF(((propertyobject *)self)->prop_del);
|
||||
if (deleter == Py_None)
|
||||
deleter = NULL;
|
||||
Py_XINCREF(deleter);
|
||||
((propertyobject *)self)->prop_del = deleter;
|
||||
Py_INCREF(self);
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static PyMethodDef property_methods[] = {
|
||||
{"getter", property_getter, METH_O, getter_doc},
|
||||
{"setter", property_setter, METH_O, setter_doc},
|
||||
{"deleter", property_deleter, METH_O, deleter_doc},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
property_dealloc(PyObject *self)
|
||||
|
@ -1260,7 +1314,7 @@ PyTypeObject PyProperty_Type = {
|
|||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
0, /* tp_methods */
|
||||
property_methods, /* tp_methods */
|
||||
property_members, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
|
|
Loading…
Reference in New Issue