bpo-27794: Add `name` attribute to `property` class (GH-23967) · python/cpython@c56387f
@@ -1490,6 +1490,7 @@ typedef struct {
14901490PyObject *prop_set;
14911491PyObject *prop_del;
14921492PyObject *prop_doc;
1493+PyObject *prop_name;
14931494int getter_doc;
14941495} propertyobject;
14951496@@ -1535,10 +1536,33 @@ property_deleter(PyObject *self, PyObject *deleter)
15351536}
15361537153715381539+PyDoc_STRVAR(set_name_doc,
1540+"Method to set name of a property.");
1541+1542+static PyObject *
1543+property_set_name(PyObject *self, PyObject *args) {
1544+if (PyTuple_GET_SIZE(args) != 2) {
1545+PyErr_Format(
1546+PyExc_TypeError,
1547+"__set_name__() takes 2 positional arguments but %d were given",
1548+PyTuple_GET_SIZE(args));
1549+return NULL;
1550+ }
1551+1552+propertyobject *prop = (propertyobject *)self;
1553+PyObject *name = PyTuple_GET_ITEM(args, 1);
1554+1555+Py_XINCREF(name);
1556+Py_XSETREF(prop->prop_name, name);
1557+1558+Py_RETURN_NONE;
1559+}
1560+15381561static PyMethodDef property_methods[] = {
15391562 {"getter", property_getter, METH_O, getter_doc},
15401563 {"setter", property_setter, METH_O, setter_doc},
15411564 {"deleter", property_deleter, METH_O, deleter_doc},
1565+ {"__set_name__", property_set_name, METH_VARARGS, set_name_doc},
15421566 {0}
15431567};
15441568@@ -1553,6 +1577,7 @@ property_dealloc(PyObject *self)
15531577Py_XDECREF(gs->prop_set);
15541578Py_XDECREF(gs->prop_del);
15551579Py_XDECREF(gs->prop_doc);
1580+Py_XDECREF(gs->prop_name);
15561581Py_TYPE(self)->tp_free(self);
15571582}
15581583@@ -1566,7 +1591,12 @@ property_descr_get(PyObject *self, PyObject *obj, PyObject *type)
1566159115671592propertyobject *gs = (propertyobject *)self;
15681593if (gs->prop_get == NULL) {
1569-PyErr_SetString(PyExc_AttributeError, "unreadable attribute");
1594+if (gs->prop_name != NULL) {
1595+PyErr_Format(PyExc_AttributeError, "unreadable attribute %R", gs->prop_name);
1596+ } else {
1597+PyErr_SetString(PyExc_AttributeError, "unreadable attribute");
1598+ }
1599+15701600return NULL;
15711601 }
15721602@@ -1584,10 +1614,18 @@ property_descr_set(PyObject *self, PyObject *obj, PyObject *value)
15841614else
15851615func = gs->prop_set;
15861616if (func == NULL) {
1587-PyErr_SetString(PyExc_AttributeError,
1617+if (gs->prop_name != NULL) {
1618+PyErr_Format(PyExc_AttributeError,
15881619value == NULL ?
1589-"can't delete attribute" :
1590-"can't set attribute");
1620+"can't delete attribute %R" :
1621+"can't set attribute %R",
1622+gs->prop_name);
1623+ } else {
1624+PyErr_SetString(PyExc_AttributeError,
1625+value == NULL ?
1626+"can't delete attribute" :
1627+"can't set attribute");
1628+ }
15911629return -1;
15921630 }
15931631if (value == NULL)
@@ -1634,6 +1672,9 @@ property_copy(PyObject *old, PyObject *get, PyObject *set, PyObject *del)
16341672Py_DECREF(type);
16351673if (new == NULL)
16361674return NULL;
1675+1676+Py_XINCREF(pold->prop_name);
1677+Py_XSETREF(((propertyobject *) new)->prop_name, pold->prop_name);
16371678return new;
16381679}
16391680@@ -1695,6 +1736,8 @@ property_init_impl(propertyobject *self, PyObject *fget, PyObject *fset,
16951736Py_XSETREF(self->prop_set, fset);
16961737Py_XSETREF(self->prop_del, fdel);
16971738Py_XSETREF(self->prop_doc, doc);
1739+Py_XSETREF(self->prop_name, NULL);
1740+16981741self->getter_doc = 0;
1699174217001743/* if no docstring given and the getter has one, use that one */
@@ -1769,6 +1812,7 @@ property_traverse(PyObject *self, visitproc visit, void *arg)
17691812Py_VISIT(pp->prop_set);
17701813Py_VISIT(pp->prop_del);
17711814Py_VISIT(pp->prop_doc);
1815+Py_VISIT(pp->prop_name);
17721816return 0;
17731817}
17741818