diff options
Diffstat (limited to 'Objects/methodobject.c')
| -rw-r--r-- | Objects/methodobject.c | 56 | 
1 files changed, 50 insertions, 6 deletions
| diff --git a/Objects/methodobject.c b/Objects/methodobject.c index f1a9f4b..1d143f9 100644 --- a/Objects/methodobject.c +++ b/Objects/methodobject.c @@ -44,7 +44,7 @@ PyCFunction_GetFunction(PyObject *op)          PyErr_BadInternalCall();          return NULL;      } -    return ((PyCFunctionObject *)op) -> m_ml -> ml_meth; +    return PyCFunction_GET_FUNCTION(op);  }  PyObject * @@ -54,7 +54,7 @@ PyCFunction_GetSelf(PyObject *op)          PyErr_BadInternalCall();          return NULL;      } -    return ((PyCFunctionObject *)op) -> m_self; +    return PyCFunction_GET_SELF(op);  }  int @@ -64,7 +64,7 @@ PyCFunction_GetFlags(PyObject *op)          PyErr_BadInternalCall();          return -1;      } -    return ((PyCFunctionObject *)op) -> m_ml -> ml_flags; +    return PyCFunction_GET_FLAGS(op);  }  PyObject * @@ -151,6 +151,41 @@ meth_get__name__(PyCFunctionObject *m, void *closure)      return PyUnicode_FromString(m->m_ml->ml_name);  } +static PyObject * +meth_get__qualname__(PyCFunctionObject *m, void *closure) +{ +    /* If __self__ is a module or NULL, return m.__name__ +       (e.g. len.__qualname__ == 'len') + +       If __self__ is a type, return m.__self__.__qualname__ + '.' + m.__name__ +       (e.g. dict.fromkeys.__qualname__ == 'dict.fromkeys') + +       Otherwise return type(m.__self__).__qualname__ + '.' + m.__name__ +       (e.g. [].append.__qualname__ == 'list.append') */ +    PyObject *type, *type_qualname, *res; +    _Py_IDENTIFIER(__qualname__); + +    if (m->m_self == NULL || PyModule_Check(m->m_self)) +        return PyUnicode_FromString(m->m_ml->ml_name); + +    type = PyType_Check(m->m_self) ? m->m_self : (PyObject*)Py_TYPE(m->m_self); + +    type_qualname = _PyObject_GetAttrId(type, &PyId___qualname__); +    if (type_qualname == NULL) +        return NULL; + +    if (!PyUnicode_Check(type_qualname)) { +        PyErr_SetString(PyExc_TypeError, "<method>.__class__." +                        "__qualname__ is not a unicode object"); +        Py_XDECREF(type_qualname); +        return NULL; +    } + +    res = PyUnicode_FromFormat("%S.%s", type_qualname, m->m_ml->ml_name); +    Py_DECREF(type_qualname); +    return res; +} +  static int  meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg)  { @@ -164,7 +199,7 @@ meth_get__self__(PyCFunctionObject *m, void *closure)  {      PyObject *self; -    self = m->m_self; +    self = PyCFunction_GET_SELF(m);      if (self == NULL)          self = Py_None;      Py_INCREF(self); @@ -174,6 +209,7 @@ meth_get__self__(PyCFunctionObject *m, void *closure)  static PyGetSetDef meth_getsets [] = {      {"__doc__",  (getter)meth_get__doc__,  NULL, NULL},      {"__name__", (getter)meth_get__name__, NULL, NULL}, +    {"__qualname__", (getter)meth_get__qualname__, NULL, NULL},      {"__self__", (getter)meth_get__self__, NULL, NULL},      {0}  }; @@ -208,8 +244,7 @@ meth_richcompare(PyObject *self, PyObject *other, int op)          !PyCFunction_Check(self) ||          !PyCFunction_Check(other))      { -        Py_INCREF(Py_NotImplemented); -        return Py_NotImplemented; +        Py_RETURN_NOTIMPLEMENTED;      }      a = (PyCFunctionObject *)self;      b = (PyCFunctionObject *)other; @@ -303,6 +338,15 @@ PyCFunction_Fini(void)      (void)PyCFunction_ClearFreeList();  } +/* Print summary info about the state of the optimized allocator */ +void +_PyCFunction_DebugMallocStats(FILE *out) +{ +    _PyDebugAllocatorStats(out, +                           "free PyCFunction", +                           numfree, sizeof(PyCFunction)); +} +  /* PyCFunction_New() is now just a macro that calls PyCFunction_NewEx(),     but it's part of the API so we need to keep a function around that     existing C extensions can call. | 
