@@ -1172,12 +1172,57 @@ functools_wraps(PyObject *wrapper, PyObject *wrapped)
11721172 COPY_ATTR (__name__ );
11731173 COPY_ATTR (__qualname__ );
11741174 COPY_ATTR (__doc__ );
1175- COPY_ATTR (__annotations__ );
11761175 return 0 ;
11771176
11781177#undef COPY_ATTR
11791178}
11801179
1180+ // Used for wrapping __annotations__ and __annotate__ on classmethod
1181+ // and staticmethod objects.
1182+ static PyObject *
1183+ descriptor_get_wrapped_attribute (PyObject * wrapped , PyObject * dict , PyObject * name )
1184+ {
1185+ PyObject * res ;
1186+ if (PyDict_GetItemRef (dict , name , & res ) < 0 ) {
1187+ return NULL ;
1188+ }
1189+ if (res != NULL ) {
1190+ return res ;
1191+ }
1192+ res = PyObject_GetAttr (wrapped , name );
1193+ if (res == NULL ) {
1194+ return NULL ;
1195+ }
1196+ if (PyDict_SetItem (dict , name , res ) < 0 ) {
1197+ Py_DECREF (res );
1198+ return NULL ;
1199+ }
1200+ return res ;
1201+ }
1202+
1203+ static int
1204+ descriptor_set_wrapped_attribute (PyObject * dict , PyObject * name , PyObject * value ,
1205+ char * type_name )
1206+ {
1207+ if (value == NULL ) {
1208+ if (PyDict_DelItem (dict , name ) < 0 ) {
1209+ if (PyErr_ExceptionMatches (PyExc_KeyError )) {
1210+ PyErr_Clear ();
1211+ PyErr_Format (PyExc_AttributeError ,
1212+ "'%.200s' object has no attribute '%U'" ,
1213+ type_name , name );
1214+ }
1215+ else {
1216+ return -1 ;
1217+ }
1218+ }
1219+ return 0 ;
1220+ }
1221+ else {
1222+ return PyDict_SetItem (dict , name , value );
1223+ }
1224+ }
1225+
11811226
11821227/* Class method object */
11831228
@@ -1283,10 +1328,37 @@ cm_get___isabstractmethod__(classmethod *cm, void *closure)
12831328 Py_RETURN_FALSE ;
12841329}
12851330
1331+ static PyObject *
1332+ cm_get___annotations__ (classmethod * cm , void * closure )
1333+ {
1334+ return descriptor_get_wrapped_attribute (cm -> cm_callable , cm -> cm_dict , & _Py_ID (__annotations__ ));
1335+ }
1336+
1337+ static int
1338+ cm_set___annotations__ (classmethod * cm , PyObject * value , void * closure )
1339+ {
1340+ return descriptor_set_wrapped_attribute (cm -> cm_dict , & _Py_ID (__annotations__ ), value , "classmethod" );
1341+ }
1342+
1343+ static PyObject *
1344+ cm_get___annotate__ (classmethod * cm , void * closure )
1345+ {
1346+ return descriptor_get_wrapped_attribute (cm -> cm_callable , cm -> cm_dict , & _Py_ID (__annotate__ ));
1347+ }
1348+
1349+ static int
1350+ cm_set___annotate__ (classmethod * cm , PyObject * value , void * closure )
1351+ {
1352+ return descriptor_set_wrapped_attribute (cm -> cm_dict , & _Py_ID (__annotate__ ), value , "classmethod" );
1353+ }
1354+
1355+
12861356static PyGetSetDef cm_getsetlist [] = {
12871357 {"__isabstractmethod__" ,
12881358 (getter )cm_get___isabstractmethod__ , NULL , NULL , NULL },
12891359 {"__dict__" , PyObject_GenericGetDict , PyObject_GenericSetDict , NULL , NULL },
1360+ {"__annotations__" , (getter )cm_get___annotations__ , (setter )cm_set___annotations__ , NULL , NULL },
1361+ {"__annotate__" , (getter )cm_get___annotate__ , (setter )cm_set___annotate__ , NULL , NULL },
12901362 {NULL } /* Sentinel */
12911363};
12921364
@@ -1479,10 +1551,36 @@ sm_get___isabstractmethod__(staticmethod *sm, void *closure)
14791551 Py_RETURN_FALSE ;
14801552}
14811553
1554+ static PyObject *
1555+ sm_get___annotations__ (staticmethod * sm , void * closure )
1556+ {
1557+ return descriptor_get_wrapped_attribute (sm -> sm_callable , sm -> sm_dict , & _Py_ID (__annotations__ ));
1558+ }
1559+
1560+ static int
1561+ sm_set___annotations__ (staticmethod * sm , PyObject * value , void * closure )
1562+ {
1563+ return descriptor_set_wrapped_attribute (sm -> sm_dict , & _Py_ID (__annotations__ ), value , "staticmethod" );
1564+ }
1565+
1566+ static PyObject *
1567+ sm_get___annotate__ (staticmethod * sm , void * closure )
1568+ {
1569+ return descriptor_get_wrapped_attribute (sm -> sm_callable , sm -> sm_dict , & _Py_ID (__annotate__ ));
1570+ }
1571+
1572+ static int
1573+ sm_set___annotate__ (staticmethod * sm , PyObject * value , void * closure )
1574+ {
1575+ return descriptor_set_wrapped_attribute (sm -> sm_dict , & _Py_ID (__annotate__ ), value , "staticmethod" );
1576+ }
1577+
14821578static PyGetSetDef sm_getsetlist [] = {
14831579 {"__isabstractmethod__" ,
14841580 (getter )sm_get___isabstractmethod__ , NULL , NULL , NULL },
14851581 {"__dict__" , PyObject_GenericGetDict , PyObject_GenericSetDict , NULL , NULL },
1582+ {"__annotations__" , (getter )sm_get___annotations__ , (setter )sm_set___annotations__ , NULL , NULL },
1583+ {"__annotate__" , (getter )sm_get___annotate__ , (setter )sm_set___annotate__ , NULL , NULL },
14861584 {NULL } /* Sentinel */
14871585};
14881586
0 commit comments