@@ -9,6 +9,7 @@ descr_dealloc(PyDescrObject *descr)
9
9
_PyObject_GC_UNTRACK (descr );
10
10
Py_XDECREF (descr -> d_type );
11
11
Py_XDECREF (descr -> d_name );
12
+ Py_XDECREF (descr -> d_qualname );
12
13
PyObject_GC_Del (descr );
13
14
}
14
15
@@ -321,6 +322,44 @@ method_get_doc(PyMethodDescrObject *descr, void *closure)
321
322
return PyUnicode_FromString (descr -> d_method -> ml_doc );
322
323
}
323
324
325
+ static PyObject *
326
+ calculate_qualname (PyDescrObject * descr )
327
+ {
328
+ PyObject * type_qualname , * res ;
329
+ _Py_IDENTIFIER (__qualname__ );
330
+
331
+ if (descr -> d_name == NULL || !PyUnicode_Check (descr -> d_name )) {
332
+ PyErr_SetString (PyExc_TypeError ,
333
+ "<descriptor>.__name__ is not a unicode object" );
334
+ return NULL ;
335
+ }
336
+
337
+ type_qualname = _PyObject_GetAttrId ((PyObject * )descr -> d_type ,
338
+ & PyId___qualname__ );
339
+ if (type_qualname == NULL )
340
+ return NULL ;
341
+
342
+ if (!PyUnicode_Check (type_qualname )) {
343
+ PyErr_SetString (PyExc_TypeError , "<descriptor>.__objclass__."
344
+ "__qualname__ is not a unicode object" );
345
+ Py_XDECREF (type_qualname );
346
+ return NULL ;
347
+ }
348
+
349
+ res = PyUnicode_FromFormat ("%S.%S" , type_qualname , descr -> d_name );
350
+ Py_DECREF (type_qualname );
351
+ return res ;
352
+ }
353
+
354
+ static PyObject *
355
+ descr_get_qualname (PyDescrObject * descr )
356
+ {
357
+ if (descr -> d_qualname == NULL )
358
+ descr -> d_qualname = calculate_qualname (descr );
359
+ Py_XINCREF (descr -> d_qualname );
360
+ return descr -> d_qualname ;
361
+ }
362
+
324
363
static PyMemberDef descr_members [] = {
325
364
{"__objclass__" , T_OBJECT , offsetof(PyDescrObject , d_type ), READONLY },
326
365
{"__name__" , T_OBJECT , offsetof(PyDescrObject , d_name ), READONLY },
@@ -329,6 +368,7 @@ static PyMemberDef descr_members[] = {
329
368
330
369
static PyGetSetDef method_getset [] = {
331
370
{"__doc__" , (getter )method_get_doc },
371
+ {"__qualname__" , (getter )descr_get_qualname },
332
372
{0 }
333
373
};
334
374
@@ -344,6 +384,7 @@ member_get_doc(PyMemberDescrObject *descr, void *closure)
344
384
345
385
static PyGetSetDef member_getset [] = {
346
386
{"__doc__" , (getter )member_get_doc },
387
+ {"__qualname__" , (getter )descr_get_qualname },
347
388
{0 }
348
389
};
349
390
@@ -359,6 +400,7 @@ getset_get_doc(PyGetSetDescrObject *descr, void *closure)
359
400
360
401
static PyGetSetDef getset_getset [] = {
361
402
{"__doc__" , (getter )getset_get_doc },
403
+ {"__qualname__" , (getter )descr_get_qualname },
362
404
{0 }
363
405
};
364
406
@@ -374,6 +416,7 @@ wrapperdescr_get_doc(PyWrapperDescrObject *descr, void *closure)
374
416
375
417
static PyGetSetDef wrapperdescr_getset [] = {
376
418
{"__doc__" , (getter )wrapperdescr_get_doc },
419
+ {"__qualname__" , (getter )descr_get_qualname },
377
420
{0 }
378
421
};
379
422
@@ -585,6 +628,7 @@ descr_new(PyTypeObject *descrtype, PyTypeObject *type, const char *name)
585
628
Py_DECREF (descr );
586
629
descr = NULL ;
587
630
}
631
+ descr -> d_qualname = NULL ;
588
632
}
589
633
return descr ;
590
634
}
@@ -987,9 +1031,16 @@ wrapper_doc(wrapperobject *wp)
987
1031
}
988
1032
}
989
1033
1034
+ static PyObject *
1035
+ wrapper_qualname (wrapperobject * wp )
1036
+ {
1037
+ return descr_get_qualname ((PyDescrObject * )wp -> descr );
1038
+ }
1039
+
990
1040
static PyGetSetDef wrapper_getsets [] = {
991
1041
{"__objclass__" , (getter )wrapper_objclass },
992
1042
{"__name__" , (getter )wrapper_name },
1043
+ {"__qualname__" , (getter )wrapper_qualname },
993
1044
{"__doc__" , (getter )wrapper_doc },
994
1045
{0 }
995
1046
};
0 commit comments