@@ -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}
15361537
15371538
1539+ 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)
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)
15661591
15671592 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 ;
16991742
17001743 /* 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
0 commit comments