Commit 8b596e27 authored by Guido van Rossum's avatar Guido van Rossum

Change the getset type to take an optional third function argument:

the delete function.  (Question: should the attribute name also be
recorded in the getset object?  That makes the protocol more work, but
may give us better error messages.)
parent a15fc19b
...@@ -868,6 +868,7 @@ typedef struct { ...@@ -868,6 +868,7 @@ typedef struct {
PyObject_HEAD PyObject_HEAD
PyObject *get; PyObject *get;
PyObject *set; PyObject *set;
PyObject *del;
} getsetobject; } getsetobject;
static void static void
...@@ -877,6 +878,7 @@ getset_dealloc(PyObject *self) ...@@ -877,6 +878,7 @@ getset_dealloc(PyObject *self)
Py_XDECREF(gs->get); Py_XDECREF(gs->get);
Py_XDECREF(gs->set); Py_XDECREF(gs->set);
Py_XDECREF(gs->del);
self->ob_type->tp_free(self); self->ob_type->tp_free(self);
} }
...@@ -900,16 +902,23 @@ static int ...@@ -900,16 +902,23 @@ static int
getset_descr_set(PyObject *self, PyObject *obj, PyObject *value) getset_descr_set(PyObject *self, PyObject *obj, PyObject *value)
{ {
getsetobject *gs = (getsetobject *)self; getsetobject *gs = (getsetobject *)self;
PyObject *res; PyObject *func, *res;
if (gs->set == NULL) { if (value == NULL)
PyErr_SetString(PyExc_AttributeError, "unsettable attribute"); func = gs->del;
else
func = gs->set;
if (func == NULL) {
PyErr_SetString(PyExc_AttributeError,
value == NULL ?
"can't delete attribute" :
"can't set attribute");
return -1; return -1;
} }
if (value == NULL) if (value == NULL)
res = PyObject_CallFunction(gs->set, "(O)", obj); res = PyObject_CallFunction(func, "(O)", obj);
else else
res = PyObject_CallFunction(gs->set, "(OO)", obj, value); res = PyObject_CallFunction(func, "(OO)", obj, value);
if (res == NULL) if (res == NULL)
return -1; return -1;
Py_DECREF(res); Py_DECREF(res);
...@@ -919,10 +928,10 @@ getset_descr_set(PyObject *self, PyObject *obj, PyObject *value) ...@@ -919,10 +928,10 @@ getset_descr_set(PyObject *self, PyObject *obj, PyObject *value)
static int static int
getset_init(PyObject *self, PyObject *args, PyObject *kwds) getset_init(PyObject *self, PyObject *args, PyObject *kwds)
{ {
PyObject *get = NULL, *set = NULL; PyObject *get = NULL, *set = NULL, *del = NULL;
getsetobject *gs = (getsetobject *)self; getsetobject *gs = (getsetobject *)self;
if (!PyArg_ParseTuple(args, "|OO:getset.__init__", &get, &set)) if (!PyArg_ParseTuple(args, "|OOO:getset.__init__", &get, &set, &del))
return -1; return -1;
if (get == Py_None) if (get == Py_None)
get = NULL; get = NULL;
...@@ -930,18 +939,21 @@ getset_init(PyObject *self, PyObject *args, PyObject *kwds) ...@@ -930,18 +939,21 @@ getset_init(PyObject *self, PyObject *args, PyObject *kwds)
set = NULL; set = NULL;
Py_XINCREF(get); Py_XINCREF(get);
Py_XINCREF(set); Py_XINCREF(set);
Py_XINCREF(del);
gs->get = get; gs->get = get;
gs->set = set; gs->set = set;
gs->del = del;
return 0; return 0;
} }
static char getset_doc[] = static char getset_doc[] =
"getset([getfunc[, setfunc]]) -> getset attribute\n" "getset([getfunc[, setfunc[, delfunc]]]) -> getset attribute\n"
"Typical use to define a managed attribute x of C instances:\n" "Typical use to define a managed attribute x of C instances:\n"
"class C(object):\n" "class C(object):\n"
" def getx(self): return self.__x\n" " def getx(self): return self.__x\n"
" def setx(self, value): self.__x = value\n" " def setx(self, value): self.__x = value\n"
" x = getset(getx, setx)"; " def delx(self): del self.__x\n"
" x = getset(getx, setx, delx)";
PyTypeObject PyGetSet_Type = { PyTypeObject PyGetSet_Type = {
PyObject_HEAD_INIT(&PyType_Type) PyObject_HEAD_INIT(&PyType_Type)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment