LCOV - code coverage report
Current view: top level - Objects - methodobject.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 62 203 30.5 %
Date: 2017-04-19 Functions: 8 20 40.0 %

          Line data    Source code
       1             : 
       2             : /* Method object implementation */
       3             : 
       4             : #include "Python.h"
       5             : #include "structmember.h"
       6             : 
       7             : /* Free list for method objects to safe malloc/free overhead
       8             :  * The m_self element is used to chain the objects.
       9             :  */
      10             : static PyCFunctionObject *free_list = NULL;
      11             : static int numfree = 0;
      12             : #ifndef PyCFunction_MAXFREELIST
      13             : #define PyCFunction_MAXFREELIST 256
      14             : #endif
      15             : 
      16             : PyObject *
      17       63326 : PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)
      18             : {
      19             :     PyCFunctionObject *op;
      20       63326 :     op = free_list;
      21       63326 :     if (op != NULL) {
      22       61253 :         free_list = (PyCFunctionObject *)(op->m_self);
      23       61253 :         (void)PyObject_INIT(op, &PyCFunction_Type);
      24       61253 :         numfree--;
      25             :     }
      26             :     else {
      27        2073 :         op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
      28        2073 :         if (op == NULL)
      29           0 :             return NULL;
      30             :     }
      31       63326 :     op->m_ml = ml;
      32       63326 :     Py_XINCREF(self);
      33       63326 :     op->m_self = self;
      34       63326 :     Py_XINCREF(module);
      35       63326 :     op->m_module = module;
      36       63326 :     _PyObject_GC_TRACK(op);
      37       63326 :     return (PyObject *)op;
      38             : }
      39             : 
      40             : PyCFunction
      41           0 : PyCFunction_GetFunction(PyObject *op)
      42             : {
      43           0 :     if (!PyCFunction_Check(op)) {
      44           0 :         PyErr_BadInternalCall();
      45           0 :         return NULL;
      46             :     }
      47           0 :     return ((PyCFunctionObject *)op) -> m_ml -> ml_meth;
      48             : }
      49             : 
      50             : PyObject *
      51           0 : PyCFunction_GetSelf(PyObject *op)
      52             : {
      53           0 :     if (!PyCFunction_Check(op)) {
      54           0 :         PyErr_BadInternalCall();
      55           0 :         return NULL;
      56             :     }
      57           0 :     return ((PyCFunctionObject *)op) -> m_self;
      58             : }
      59             : 
      60             : int
      61           0 : PyCFunction_GetFlags(PyObject *op)
      62             : {
      63           0 :     if (!PyCFunction_Check(op)) {
      64           0 :         PyErr_BadInternalCall();
      65           0 :         return -1;
      66             :     }
      67           0 :     return ((PyCFunctionObject *)op) -> m_ml -> ml_flags;
      68             : }
      69             : 
      70             : PyObject *
      71       70084 : PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw)
      72             : {
      73       70084 :     PyCFunctionObject* f = (PyCFunctionObject*)func;
      74       70084 :     PyCFunction meth = PyCFunction_GET_FUNCTION(func);
      75       70084 :     PyObject *self = PyCFunction_GET_SELF(func);
      76             :     Py_ssize_t size;
      77             : 
      78       70084 :     switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) {
      79             :     case METH_VARARGS:
      80       38779 :         if (kw == NULL || PyDict_Size(kw) == 0)
      81       38779 :             return (*meth)(self, arg);
      82           0 :         break;
      83             :     case METH_VARARGS | METH_KEYWORDS:
      84             :     case METH_OLDARGS | METH_KEYWORDS:
      85       10878 :         return (*(PyCFunctionWithKeywords)meth)(self, arg, kw);
      86             :     case METH_NOARGS:
      87        3276 :         if (kw == NULL || PyDict_Size(kw) == 0) {
      88        3276 :             size = PyTuple_GET_SIZE(arg);
      89        3276 :             if (size == 0)
      90        3276 :                 return (*meth)(self, NULL);
      91           0 :             PyErr_Format(PyExc_TypeError,
      92             :                 "%.200s() takes no arguments (%zd given)",
      93           0 :                 f->m_ml->ml_name, size);
      94           0 :             return NULL;
      95             :         }
      96           0 :         break;
      97             :     case METH_O:
      98       17151 :         if (kw == NULL || PyDict_Size(kw) == 0) {
      99       17151 :             size = PyTuple_GET_SIZE(arg);
     100       17151 :             if (size == 1)
     101       17151 :                 return (*meth)(self, PyTuple_GET_ITEM(arg, 0));
     102           0 :             PyErr_Format(PyExc_TypeError,
     103             :                 "%.200s() takes exactly one argument (%zd given)",
     104           0 :                 f->m_ml->ml_name, size);
     105           0 :             return NULL;
     106             :         }
     107           0 :         break;
     108             :     case METH_OLDARGS:
     109             :         /* the really old style */
     110           0 :         if (kw == NULL || PyDict_Size(kw) == 0) {
     111           0 :             size = PyTuple_GET_SIZE(arg);
     112           0 :             if (size == 1)
     113           0 :                 arg = PyTuple_GET_ITEM(arg, 0);
     114           0 :             else if (size == 0)
     115           0 :                 arg = NULL;
     116           0 :             return (*meth)(self, arg);
     117             :         }
     118           0 :         break;
     119             :     default:
     120           0 :         PyErr_BadInternalCall();
     121           0 :         return NULL;
     122             :     }
     123           0 :     PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
     124           0 :                  f->m_ml->ml_name);
     125           0 :     return NULL;
     126             : }
     127             : 
     128             : /* Methods (the standard built-in methods, that is) */
     129             : 
     130             : static void
     131       62921 : meth_dealloc(PyCFunctionObject *m)
     132             : {
     133       62921 :     _PyObject_GC_UNTRACK(m);
     134       62921 :     Py_XDECREF(m->m_self);
     135       62921 :     Py_XDECREF(m->m_module);
     136       62921 :     if (numfree < PyCFunction_MAXFREELIST) {
     137       62039 :         m->m_self = (PyObject *)free_list;
     138       62039 :         free_list = m;
     139       62039 :         numfree++;
     140             :     }
     141             :     else {
     142         882 :         PyObject_GC_Del(m);
     143             :     }
     144       62921 : }
     145             : 
     146             : static PyObject *
     147           3 : meth_get__doc__(PyCFunctionObject *m, void *closure)
     148             : {
     149           3 :     const char *doc = m->m_ml->ml_doc;
     150             : 
     151           3 :     if (doc != NULL)
     152           3 :         return PyString_FromString(doc);
     153           0 :     Py_INCREF(Py_None);
     154           0 :     return Py_None;
     155             : }
     156             : 
     157             : static PyObject *
     158           3 : meth_get__name__(PyCFunctionObject *m, void *closure)
     159             : {
     160           3 :     return PyString_FromString(m->m_ml->ml_name);
     161             : }
     162             : 
     163             : static int
     164       12216 : meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg)
     165             : {
     166       12216 :     Py_VISIT(m->m_self);
     167       12216 :     Py_VISIT(m->m_module);
     168       12216 :     return 0;
     169             : }
     170             : 
     171             : static PyObject *
     172           0 : meth_get__self__(PyCFunctionObject *m, void *closure)
     173             : {
     174             :     PyObject *self;
     175           0 :     if (PyEval_GetRestricted()) {
     176           0 :         PyErr_SetString(PyExc_RuntimeError,
     177             :             "method.__self__ not accessible in restricted mode");
     178           0 :         return NULL;
     179             :     }
     180           0 :     self = m->m_self;
     181           0 :     if (self == NULL)
     182           0 :         self = Py_None;
     183           0 :     Py_INCREF(self);
     184           0 :     return self;
     185             : }
     186             : 
     187             : static PyGetSetDef meth_getsets [] = {
     188             :     {"__doc__",  (getter)meth_get__doc__,  NULL, NULL},
     189             :     {"__name__", (getter)meth_get__name__, NULL, NULL},
     190             :     {"__self__", (getter)meth_get__self__, NULL, NULL},
     191             :     {0}
     192             : };
     193             : 
     194             : #define OFF(x) offsetof(PyCFunctionObject, x)
     195             : 
     196             : static PyMemberDef meth_members[] = {
     197             :     {"__module__",    T_OBJECT,     OFF(m_module), PY_WRITE_RESTRICTED},
     198             :     {NULL}
     199             : };
     200             : 
     201             : static PyObject *
     202           0 : meth_repr(PyCFunctionObject *m)
     203             : {
     204           0 :     if (m->m_self == NULL)
     205           0 :         return PyString_FromFormat("<built-in function %s>",
     206           0 :                                    m->m_ml->ml_name);
     207           0 :     return PyString_FromFormat("<built-in method %s of %s object at %p>",
     208           0 :                                m->m_ml->ml_name,
     209           0 :                                m->m_self->ob_type->tp_name,
     210             :                                m->m_self);
     211             : }
     212             : 
     213             : static int
     214           0 : meth_compare(PyCFunctionObject *a, PyCFunctionObject *b)
     215             : {
     216           0 :     if (a->m_self != b->m_self)
     217           0 :         return (a->m_self < b->m_self) ? -1 : 1;
     218           0 :     if (a->m_ml->ml_meth == b->m_ml->ml_meth)
     219           0 :         return 0;
     220           0 :     if (strcmp(a->m_ml->ml_name, b->m_ml->ml_name) < 0)
     221           0 :         return -1;
     222             :     else
     223           0 :         return 1;
     224             : }
     225             : 
     226             : static PyObject *
     227           0 : meth_richcompare(PyObject *self, PyObject *other, int op)
     228             : {
     229             :     PyCFunctionObject *a, *b;
     230             :     PyObject *res;
     231             :     int eq;
     232             : 
     233           0 :     if (op != Py_EQ && op != Py_NE) {
     234             :         /* Py3K warning if comparison isn't == or !=.  */
     235           0 :         if (PyErr_WarnPy3k("builtin_function_or_method order "
     236           0 :                            "comparisons not supported in 3.x", 1) < 0) {
     237           0 :             return NULL;
     238             :         }
     239             : 
     240           0 :         Py_INCREF(Py_NotImplemented);
     241           0 :         return Py_NotImplemented;
     242             :     }
     243           0 :     else if (!PyCFunction_Check(self) || !PyCFunction_Check(other)) {
     244           0 :         Py_INCREF(Py_NotImplemented);
     245           0 :         return Py_NotImplemented;
     246             :     }
     247           0 :     a = (PyCFunctionObject *)self;
     248           0 :     b = (PyCFunctionObject *)other;
     249           0 :     eq = a->m_self == b->m_self;
     250           0 :     if (eq)
     251           0 :         eq = a->m_ml->ml_meth == b->m_ml->ml_meth;
     252           0 :     if (op == Py_EQ)
     253           0 :         res = eq ? Py_True : Py_False;
     254             :     else
     255           0 :         res = eq ? Py_False : Py_True;
     256           0 :     Py_INCREF(res);
     257           0 :     return res;
     258             : }
     259             : 
     260             : static long
     261           0 : meth_hash(PyCFunctionObject *a)
     262             : {
     263             :     long x,y;
     264           0 :     if (a->m_self == NULL)
     265           0 :         x = 0;
     266             :     else {
     267           0 :         x = PyObject_Hash(a->m_self);
     268           0 :         if (x == -1)
     269           0 :             return -1;
     270             :     }
     271           0 :     y = _Py_HashPointer((void*)(a->m_ml->ml_meth));
     272           0 :     if (y == -1)
     273           0 :         return -1;
     274           0 :     x ^= y;
     275           0 :     if (x == -1)
     276           0 :         x = -2;
     277           0 :     return x;
     278             : }
     279             : 
     280             : 
     281             : PyTypeObject PyCFunction_Type = {
     282             :     PyVarObject_HEAD_INIT(&PyType_Type, 0)
     283             :     "builtin_function_or_method",
     284             :     sizeof(PyCFunctionObject),
     285             :     0,
     286             :     (destructor)meth_dealloc,                   /* tp_dealloc */
     287             :     0,                                          /* tp_print */
     288             :     0,                                          /* tp_getattr */
     289             :     0,                                          /* tp_setattr */
     290             :     (cmpfunc)meth_compare,                      /* tp_compare */
     291             :     (reprfunc)meth_repr,                        /* tp_repr */
     292             :     0,                                          /* tp_as_number */
     293             :     0,                                          /* tp_as_sequence */
     294             :     0,                                          /* tp_as_mapping */
     295             :     (hashfunc)meth_hash,                        /* tp_hash */
     296             :     PyCFunction_Call,                           /* tp_call */
     297             :     0,                                          /* tp_str */
     298             :     PyObject_GenericGetAttr,                    /* tp_getattro */
     299             :     0,                                          /* tp_setattro */
     300             :     0,                                          /* tp_as_buffer */
     301             :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
     302             :     0,                                          /* tp_doc */
     303             :     (traverseproc)meth_traverse,                /* tp_traverse */
     304             :     0,                                          /* tp_clear */
     305             :     meth_richcompare,                                           /* tp_richcompare */
     306             :     0,                                          /* tp_weaklistoffset */
     307             :     0,                                          /* tp_iter */
     308             :     0,                                          /* tp_iternext */
     309             :     0,                                          /* tp_methods */
     310             :     meth_members,                               /* tp_members */
     311             :     meth_getsets,                               /* tp_getset */
     312             :     0,                                          /* tp_base */
     313             :     0,                                          /* tp_dict */
     314             : };
     315             : 
     316             : /* List all methods in a chain -- helper for findmethodinchain */
     317             : 
     318             : static PyObject *
     319           0 : listmethodchain(PyMethodChain *chain)
     320             : {
     321             :     PyMethodChain *c;
     322             :     PyMethodDef *ml;
     323             :     int i, n;
     324             :     PyObject *v;
     325             : 
     326           0 :     n = 0;
     327           0 :     for (c = chain; c != NULL; c = c->link) {
     328           0 :         for (ml = c->methods; ml->ml_name != NULL; ml++)
     329           0 :             n++;
     330             :     }
     331           0 :     v = PyList_New(n);
     332           0 :     if (v == NULL)
     333           0 :         return NULL;
     334           0 :     i = 0;
     335           0 :     for (c = chain; c != NULL; c = c->link) {
     336           0 :         for (ml = c->methods; ml->ml_name != NULL; ml++) {
     337           0 :             PyList_SetItem(v, i, PyString_FromString(ml->ml_name));
     338           0 :             i++;
     339             :         }
     340             :     }
     341           0 :     if (PyErr_Occurred()) {
     342           0 :         Py_DECREF(v);
     343           0 :         return NULL;
     344             :     }
     345           0 :     PyList_Sort(v);
     346           0 :     return v;
     347             : }
     348             : 
     349             : /* Find a method in a method chain */
     350             : 
     351             : PyObject *
     352           0 : Py_FindMethodInChain(PyMethodChain *chain, PyObject *self, const char *name)
     353             : {
     354           0 :     if (name[0] == '_' && name[1] == '_') {
     355           0 :         if (strcmp(name, "__methods__") == 0) {
     356           0 :             if (PyErr_WarnPy3k("__methods__ not supported in 3.x",
     357           0 :                                1) < 0)
     358           0 :                 return NULL;
     359           0 :             return listmethodchain(chain);
     360             :         }
     361           0 :         if (strcmp(name, "__doc__") == 0) {
     362           0 :             const char *doc = self->ob_type->tp_doc;
     363           0 :             if (doc != NULL)
     364           0 :                 return PyString_FromString(doc);
     365             :         }
     366             :     }
     367           0 :     while (chain != NULL) {
     368           0 :         PyMethodDef *ml = chain->methods;
     369           0 :         for (; ml->ml_name != NULL; ml++) {
     370           0 :             if (name[0] == ml->ml_name[0] &&
     371           0 :                 strcmp(name+1, ml->ml_name+1) == 0)
     372             :                 /* XXX */
     373           0 :                 return PyCFunction_New(ml, self);
     374             :         }
     375           0 :         chain = chain->link;
     376             :     }
     377           0 :     PyErr_SetString(PyExc_AttributeError, name);
     378           0 :     return NULL;
     379             : }
     380             : 
     381             : /* Find a method in a single method list */
     382             : 
     383             : PyObject *
     384           0 : Py_FindMethod(PyMethodDef *methods, PyObject *self, const char *name)
     385             : {
     386             :     PyMethodChain chain;
     387           0 :     chain.methods = methods;
     388           0 :     chain.link = NULL;
     389           0 :     return Py_FindMethodInChain(&chain, self, name);
     390             : }
     391             : 
     392             : /* Clear out the free list */
     393             : 
     394             : int
     395           6 : PyCFunction_ClearFreeList(void)
     396             : {
     397           6 :     int freelist_size = numfree;
     398             : 
     399         798 :     while (free_list) {
     400         786 :         PyCFunctionObject *v = free_list;
     401         786 :         free_list = (PyCFunctionObject *)(v->m_self);
     402         786 :         PyObject_GC_Del(v);
     403         786 :         numfree--;
     404             :     }
     405             :     assert(numfree == 0);
     406           6 :     return freelist_size;
     407             : }
     408             : 
     409             : void
     410           3 : PyCFunction_Fini(void)
     411             : {
     412           3 :     (void)PyCFunction_ClearFreeList();
     413           3 : }
     414             : 
     415             : /* PyCFunction_New() is now just a macro that calls PyCFunction_NewEx(),
     416             :    but it's part of the API so we need to keep a function around that
     417             :    existing C extensions can call.
     418             : */
     419             : 
     420             : #undef PyCFunction_New
     421             : PyAPI_FUNC(PyObject *) PyCFunction_New(PyMethodDef *, PyObject *);
     422             : 
     423             : PyObject *
     424           0 : PyCFunction_New(PyMethodDef *ml, PyObject *self)
     425             : {
     426           0 :     return PyCFunction_NewEx(ml, self, NULL);
     427             : }

Generated by: LCOV version 1.10