bpo-27794: Add `name` attribute to `property` class (GH-23967) · python/cpython@c56387f

@@ -1490,6 +1490,7 @@ typedef struct {

14901490

PyObject *prop_set;

14911491

PyObject *prop_del;

14921492

PyObject *prop_doc;

1493+

PyObject *prop_name;

14931494

int 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+15381561

static 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)

15531577

Py_XDECREF(gs->prop_set);

15541578

Py_XDECREF(gs->prop_del);

15551579

Py_XDECREF(gs->prop_doc);

1580+

Py_XDECREF(gs->prop_name);

15561581

Py_TYPE(self)->tp_free(self);

15571582

}

15581583

@@ -1566,7 +1591,12 @@ property_descr_get(PyObject *self, PyObject *obj, PyObject *type)

1566159115671592

propertyobject *gs = (propertyobject *)self;

15681593

if (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+15701600

return NULL;

15711601

}

15721602

@@ -1584,10 +1614,18 @@ property_descr_set(PyObject *self, PyObject *obj, PyObject *value)

15841614

else

15851615

func = gs->prop_set;

15861616

if (func == NULL) {

1587-

PyErr_SetString(PyExc_AttributeError,

1617+

if (gs->prop_name != NULL) {

1618+

PyErr_Format(PyExc_AttributeError,

15881619

value == 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+

}

15911629

return -1;

15921630

}

15931631

if (value == NULL)

@@ -1634,6 +1672,9 @@ property_copy(PyObject *old, PyObject *get, PyObject *set, PyObject *del)

16341672

Py_DECREF(type);

16351673

if (new == NULL)

16361674

return NULL;

1675+1676+

Py_XINCREF(pold->prop_name);

1677+

Py_XSETREF(((propertyobject *) new)->prop_name, pold->prop_name);

16371678

return new;

16381679

}

16391680

@@ -1695,6 +1736,8 @@ property_init_impl(propertyobject *self, PyObject *fget, PyObject *fset,

16951736

Py_XSETREF(self->prop_set, fset);

16961737

Py_XSETREF(self->prop_del, fdel);

16971738

Py_XSETREF(self->prop_doc, doc);

1739+

Py_XSETREF(self->prop_name, NULL);

1740+16981741

self->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)

17691812

Py_VISIT(pp->prop_set);

17701813

Py_VISIT(pp->prop_del);

17711814

Py_VISIT(pp->prop_doc);

1815+

Py_VISIT(pp->prop_name);

17721816

return 0;

17731817

}

17741818