@@ -44,7 +44,7 @@ PyCFunction_GetFunction(PyObject *op)
4444 PyErr_BadInternalCall ();
4545 return NULL ;
4646 }
47- return (( PyCFunctionObject * ) op ) -> m_ml -> ml_meth ;
47+ return PyCFunction_GET_FUNCTION ( op );
4848}
4949
5050PyObject *
@@ -54,7 +54,7 @@ PyCFunction_GetSelf(PyObject *op)
5454 PyErr_BadInternalCall ();
5555 return NULL ;
5656 }
57- return (( PyCFunctionObject * ) op ) -> m_self ;
57+ return PyCFunction_GET_SELF ( op );
5858}
5959
6060int
@@ -64,7 +64,7 @@ PyCFunction_GetFlags(PyObject *op)
6464 PyErr_BadInternalCall ();
6565 return -1 ;
6666 }
67- return (( PyCFunctionObject * ) op ) -> m_ml -> ml_flags ;
67+ return PyCFunction_GET_FLAGS ( op );
6868}
6969
7070PyObject *
@@ -151,6 +151,41 @@ meth_get__name__(PyCFunctionObject *m, void *closure)
151151 return PyUnicode_FromString (m -> m_ml -> ml_name );
152152}
153153
154+ static PyObject *
155+ meth_get__qualname__ (PyCFunctionObject * m , void * closure )
156+ {
157+ /* If __self__ is a module or NULL, return m.__name__
158+ (e.g. len.__qualname__ == 'len')
159+
160+ If __self__ is a type, return m.__self__.__qualname__ + '.' + m.__name__
161+ (e.g. dict.fromkeys.__qualname__ == 'dict.fromkeys')
162+
163+ Otherwise return type(m.__self__).__qualname__ + '.' + m.__name__
164+ (e.g. [].append.__qualname__ == 'list.append') */
165+ PyObject * type , * type_qualname , * res ;
166+ _Py_IDENTIFIER (__qualname__ );
167+
168+ if (m -> m_self == NULL || PyModule_Check (m -> m_self ))
169+ return PyUnicode_FromString (m -> m_ml -> ml_name );
170+
171+ type = PyType_Check (m -> m_self ) ? m -> m_self : (PyObject * )Py_TYPE (m -> m_self );
172+
173+ type_qualname = _PyObject_GetAttrId (type , & PyId___qualname__ );
174+ if (type_qualname == NULL )
175+ return NULL ;
176+
177+ if (!PyUnicode_Check (type_qualname )) {
178+ PyErr_SetString (PyExc_TypeError , "<method>.__class__."
179+ "__qualname__ is not a unicode object" );
180+ Py_XDECREF (type_qualname );
181+ return NULL ;
182+ }
183+
184+ res = PyUnicode_FromFormat ("%S.%s" , type_qualname , m -> m_ml -> ml_name );
185+ Py_DECREF (type_qualname );
186+ return res ;
187+ }
188+
154189static int
155190meth_traverse (PyCFunctionObject * m , visitproc visit , void * arg )
156191{
@@ -164,7 +199,7 @@ meth_get__self__(PyCFunctionObject *m, void *closure)
164199{
165200 PyObject * self ;
166201
167- self = m -> m_self ;
202+ self = PyCFunction_GET_SELF ( m ) ;
168203 if (self == NULL )
169204 self = Py_None ;
170205 Py_INCREF (self );
@@ -174,6 +209,7 @@ meth_get__self__(PyCFunctionObject *m, void *closure)
174209static PyGetSetDef meth_getsets [] = {
175210 {"__doc__" , (getter )meth_get__doc__ , NULL , NULL },
176211 {"__name__" , (getter )meth_get__name__ , NULL , NULL },
212+ {"__qualname__" , (getter )meth_get__qualname__ , NULL , NULL },
177213 {"__self__" , (getter )meth_get__self__ , NULL , NULL },
178214 {0 }
179215};
0 commit comments