diff options
author | Yurii Karabas <1998uriyyo@gmail.com> | 2020-12-30 09:51:24 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-30 09:51:24 (GMT) |
commit | c56387f80c5aabf8100ceaffe365cc004ce0d7e0 (patch) | |
tree | c45546d1a311c87f58e9721a1bd232096ff07335 /Objects/descrobject.c | |
parent | ba0e49a4648e727d1a16b3ce479499eb39f22311 (diff) | |
download | cpython-c56387f80c5aabf8100ceaffe365cc004ce0d7e0.zip cpython-c56387f80c5aabf8100ceaffe365cc004ce0d7e0.tar.gz cpython-c56387f80c5aabf8100ceaffe365cc004ce0d7e0.tar.bz2 |
bpo-27794: Add `name` attribute to `property` class (GH-23967)
Diffstat (limited to 'Objects/descrobject.c')
-rw-r--r-- | Objects/descrobject.c | 52 |
1 files changed, 48 insertions, 4 deletions
diff --git a/Objects/descrobject.c b/Objects/descrobject.c index a8ce13c..16c695a 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -1490,6 +1490,7 @@ typedef struct { PyObject *prop_set; PyObject *prop_del; PyObject *prop_doc; + PyObject *prop_name; int getter_doc; } propertyobject; @@ -1535,10 +1536,33 @@ property_deleter(PyObject *self, PyObject *deleter) } +PyDoc_STRVAR(set_name_doc, + "Method to set name of a property."); + +static PyObject * +property_set_name(PyObject *self, PyObject *args) { + if (PyTuple_GET_SIZE(args) != 2) { + PyErr_Format( + PyExc_TypeError, + "__set_name__() takes 2 positional arguments but %d were given", + PyTuple_GET_SIZE(args)); + return NULL; + } + + propertyobject *prop = (propertyobject *)self; + PyObject *name = PyTuple_GET_ITEM(args, 1); + + Py_XINCREF(name); + Py_XSETREF(prop->prop_name, name); + + Py_RETURN_NONE; +} + 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}, + {"__set_name__", property_set_name, METH_VARARGS, set_name_doc}, {0} }; @@ -1553,6 +1577,7 @@ property_dealloc(PyObject *self) Py_XDECREF(gs->prop_set); Py_XDECREF(gs->prop_del); Py_XDECREF(gs->prop_doc); + Py_XDECREF(gs->prop_name); Py_TYPE(self)->tp_free(self); } @@ -1566,7 +1591,12 @@ property_descr_get(PyObject *self, PyObject *obj, PyObject *type) propertyobject *gs = (propertyobject *)self; if (gs->prop_get == NULL) { - PyErr_SetString(PyExc_AttributeError, "unreadable attribute"); + if (gs->prop_name != NULL) { + PyErr_Format(PyExc_AttributeError, "unreadable attribute %R", gs->prop_name); + } else { + PyErr_SetString(PyExc_AttributeError, "unreadable attribute"); + } + return NULL; } @@ -1584,10 +1614,18 @@ property_descr_set(PyObject *self, PyObject *obj, PyObject *value) else func = gs->prop_set; if (func == NULL) { - PyErr_SetString(PyExc_AttributeError, + if (gs->prop_name != NULL) { + PyErr_Format(PyExc_AttributeError, value == NULL ? - "can't delete attribute" : - "can't set attribute"); + "can't delete attribute %R" : + "can't set attribute %R", + gs->prop_name); + } else { + PyErr_SetString(PyExc_AttributeError, + value == NULL ? + "can't delete attribute" : + "can't set attribute"); + } return -1; } if (value == NULL) @@ -1634,6 +1672,9 @@ property_copy(PyObject *old, PyObject *get, PyObject *set, PyObject *del) Py_DECREF(type); if (new == NULL) return NULL; + + Py_XINCREF(pold->prop_name); + Py_XSETREF(((propertyobject *) new)->prop_name, pold->prop_name); return new; } @@ -1695,6 +1736,8 @@ property_init_impl(propertyobject *self, PyObject *fget, PyObject *fset, Py_XSETREF(self->prop_set, fset); Py_XSETREF(self->prop_del, fdel); Py_XSETREF(self->prop_doc, doc); + Py_XSETREF(self->prop_name, NULL); + self->getter_doc = 0; /* if no docstring given and the getter has one, use that one */ @@ -1769,6 +1812,7 @@ property_traverse(PyObject *self, visitproc visit, void *arg) Py_VISIT(pp->prop_set); Py_VISIT(pp->prop_del); Py_VISIT(pp->prop_doc); + Py_VISIT(pp->prop_name); return 0; } |