Change the getset type to take an optional third function argument:
authorGuido van Rossum <guido@python.org>
Fri, 24 Aug 2001 15:23:20 +0000 (15:23 +0000)
committerGuido van Rossum <guido@python.org>
Fri, 24 Aug 2001 15:23:20 +0000 (15:23 +0000)
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.)

Objects/descrobject.c

index c29dd833dfa757b4070e96b4fd7c5c735469ffcc..efed1c02060c72804be1f140595bbb14dc6caf3c 100644 (file)
@@ -868,6 +868,7 @@ typedef struct {
        PyObject_HEAD
        PyObject *get;
        PyObject *set;
+       PyObject *del;
 } getsetobject;
 
 static void
@@ -877,6 +878,7 @@ getset_dealloc(PyObject *self)
 
        Py_XDECREF(gs->get);
        Py_XDECREF(gs->set);
+       Py_XDECREF(gs->del);
        self->ob_type->tp_free(self);
 }
 
@@ -900,16 +902,23 @@ static int
 getset_descr_set(PyObject *self, PyObject *obj, PyObject *value)
 {
        getsetobject *gs = (getsetobject *)self;
-       PyObject *res;
+       PyObject *func, *res;
 
-       if (gs->set == NULL) {
-               PyErr_SetString(PyExc_AttributeError, "unsettable attribute");
+       if (value == NULL)
+               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;
        }
        if (value == NULL)
-               res = PyObject_CallFunction(gs->set, "(O)", obj);
+               res = PyObject_CallFunction(func, "(O)", obj);
        else
-               res = PyObject_CallFunction(gs->set, "(OO)", obj, value);
+               res = PyObject_CallFunction(func, "(OO)", obj, value);
        if (res == NULL)
                return -1;
        Py_DECREF(res);
@@ -919,10 +928,10 @@ getset_descr_set(PyObject *self, PyObject *obj, PyObject *value)
 static int
 getset_init(PyObject *self, PyObject *args, PyObject *kwds)
 {
-       PyObject *get = NULL, *set = NULL;
+       PyObject *get = NULL, *set = NULL, *del = NULL;
        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;
        if (get == Py_None)
                get = NULL;
@@ -930,18 +939,21 @@ getset_init(PyObject *self, PyObject *args, PyObject *kwds)
                set = NULL;
        Py_XINCREF(get);
        Py_XINCREF(set);
+       Py_XINCREF(del);
        gs->get = get;
        gs->set = set;
+       gs->del = del;
        return 0;
 }
 
 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"
 "class C(object):\n"
 "    def getx(self): return self.__x\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 = {
        PyObject_HEAD_INIT(&PyType_Type)