@@ -1172,12 +1172,57 @@ functools_wraps(PyObject *wrapper, PyObject *wrapped)
1172
1172
COPY_ATTR (__name__ );
1173
1173
COPY_ATTR (__qualname__ );
1174
1174
COPY_ATTR (__doc__ );
1175
- COPY_ATTR (__annotations__ );
1176
1175
return 0 ;
1177
1176
1178
1177
#undef COPY_ATTR
1179
1178
}
1180
1179
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
+
1181
1226
1182
1227
/* Class method object */
1183
1228
@@ -1283,10 +1328,37 @@ cm_get___isabstractmethod__(classmethod *cm, void *closure)
1283
1328
Py_RETURN_FALSE ;
1284
1329
}
1285
1330
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
+
1286
1356
static PyGetSetDef cm_getsetlist [] = {
1287
1357
{"__isabstractmethod__" ,
1288
1358
(getter )cm_get___isabstractmethod__ , NULL , NULL , NULL },
1289
1359
{"__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 },
1290
1362
{NULL } /* Sentinel */
1291
1363
};
1292
1364
@@ -1479,10 +1551,36 @@ sm_get___isabstractmethod__(staticmethod *sm, void *closure)
1479
1551
Py_RETURN_FALSE ;
1480
1552
}
1481
1553
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
+
1482
1578
static PyGetSetDef sm_getsetlist [] = {
1483
1579
{"__isabstractmethod__" ,
1484
1580
(getter )sm_get___isabstractmethod__ , NULL , NULL , NULL },
1485
1581
{"__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 },
1486
1584
{NULL } /* Sentinel */
1487
1585
};
1488
1586
0 commit comments