aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYurii Karabas <1998uriyyo@gmail.com>2020-12-30 11:51:24 +0200
committerGitHub <noreply@github.com>2020-12-30 01:51:24 -0800
commitc56387f80c5aabf8100ceaffe365cc004ce0d7e0 (patch)
treec45546d1a311c87f58e9721a1bd232096ff07335 /Objects
parentbpo-40137: Fix refleak in _functools_exec() (GH-24006) (diff)
downloadcpython-c56387f80c5aabf8100ceaffe365cc004ce0d7e0.tar.gz
cpython-c56387f80c5aabf8100ceaffe365cc004ce0d7e0.tar.bz2
cpython-c56387f80c5aabf8100ceaffe365cc004ce0d7e0.zip
bpo-27794: Add `name` attribute to `property` class (GH-23967)
Diffstat (limited to 'Objects')
-rw-r--r--Objects/descrobject.c52
1 files changed, 48 insertions, 4 deletions
diff --git a/Objects/descrobject.c b/Objects/descrobject.c
index a8ce13c7aa4..16c695a08f4 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;
}