Home | History | Annotate | Download | only in Objects
      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 PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)
     18 {
     19     PyCFunctionObject *op;
     20     op = free_list;
     21     if (op != NULL) {
     22         free_list = (PyCFunctionObject *)(op->m_self);
     23         (void)PyObject_INIT(op, &PyCFunction_Type);
     24         numfree--;
     25     }
     26     else {
     27         op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
     28         if (op == NULL)
     29             return NULL;
     30     }
     31     op->m_ml = ml;
     32     Py_XINCREF(self);
     33     op->m_self = self;
     34     Py_XINCREF(module);
     35     op->m_module = module;
     36     _PyObject_GC_TRACK(op);
     37     return (PyObject *)op;
     38 }
     39 
     40 PyCFunction
     41 PyCFunction_GetFunction(PyObject *op)
     42 {
     43     if (!PyCFunction_Check(op)) {
     44         PyErr_BadInternalCall();
     45         return NULL;
     46     }
     47     return ((PyCFunctionObject *)op) -> m_ml -> ml_meth;
     48 }
     49 
     50 PyObject *
     51 PyCFunction_GetSelf(PyObject *op)
     52 {
     53     if (!PyCFunction_Check(op)) {
     54         PyErr_BadInternalCall();
     55         return NULL;
     56     }
     57     return ((PyCFunctionObject *)op) -> m_self;
     58 }
     59 
     60 int
     61 PyCFunction_GetFlags(PyObject *op)
     62 {
     63     if (!PyCFunction_Check(op)) {
     64         PyErr_BadInternalCall();
     65         return -1;
     66     }
     67     return ((PyCFunctionObject *)op) -> m_ml -> ml_flags;
     68 }
     69 
     70 PyObject *
     71 PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw)
     72 {
     73     PyCFunctionObject* f = (PyCFunctionObject*)func;
     74     PyCFunction meth = PyCFunction_GET_FUNCTION(func);
     75     PyObject *self = PyCFunction_GET_SELF(func);
     76     Py_ssize_t size;
     77 
     78     switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) {
     79     case METH_VARARGS:
     80         if (kw == NULL || PyDict_Size(kw) == 0)
     81             return (*meth)(self, arg);
     82         break;
     83     case METH_VARARGS | METH_KEYWORDS:
     84     case METH_OLDARGS | METH_KEYWORDS:
     85         return (*(PyCFunctionWithKeywords)meth)(self, arg, kw);
     86     case METH_NOARGS:
     87         if (kw == NULL || PyDict_Size(kw) == 0) {
     88             size = PyTuple_GET_SIZE(arg);
     89             if (size == 0)
     90                 return (*meth)(self, NULL);
     91             PyErr_Format(PyExc_TypeError,
     92                 "%.200s() takes no arguments (%zd given)",
     93                 f->m_ml->ml_name, size);
     94             return NULL;
     95         }
     96         break;
     97     case METH_O:
     98         if (kw == NULL || PyDict_Size(kw) == 0) {
     99             size = PyTuple_GET_SIZE(arg);
    100             if (size == 1)
    101                 return (*meth)(self, PyTuple_GET_ITEM(arg, 0));
    102             PyErr_Format(PyExc_TypeError,
    103                 "%.200s() takes exactly one argument (%zd given)",
    104                 f->m_ml->ml_name, size);
    105             return NULL;
    106         }
    107         break;
    108     case METH_OLDARGS:
    109         /* the really old style */
    110         if (kw == NULL || PyDict_Size(kw) == 0) {
    111             size = PyTuple_GET_SIZE(arg);
    112             if (size == 1)
    113                 arg = PyTuple_GET_ITEM(arg, 0);
    114             else if (size == 0)
    115                 arg = NULL;
    116             return (*meth)(self, arg);
    117         }
    118         break;
    119     default:
    120         PyErr_BadInternalCall();
    121         return NULL;
    122     }
    123     PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
    124                  f->m_ml->ml_name);
    125     return NULL;
    126 }
    127 
    128 /* Methods (the standard built-in methods, that is) */
    129 
    130 static void
    131 meth_dealloc(PyCFunctionObject *m)
    132 {
    133     _PyObject_GC_UNTRACK(m);
    134     Py_XDECREF(m->m_self);
    135     Py_XDECREF(m->m_module);
    136     if (numfree < PyCFunction_MAXFREELIST) {
    137         m->m_self = (PyObject *)free_list;
    138         free_list = m;
    139         numfree++;
    140     }
    141     else {
    142         PyObject_GC_Del(m);
    143     }
    144 }
    145 
    146 static PyObject *
    147 meth_get__doc__(PyCFunctionObject *m, void *closure)
    148 {
    149     const char *doc = m->m_ml->ml_doc;
    150 
    151     if (doc != NULL)
    152         return PyString_FromString(doc);
    153     Py_INCREF(Py_None);
    154     return Py_None;
    155 }
    156 
    157 static PyObject *
    158 meth_get__name__(PyCFunctionObject *m, void *closure)
    159 {
    160     return PyString_FromString(m->m_ml->ml_name);
    161 }
    162 
    163 static int
    164 meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg)
    165 {
    166     Py_VISIT(m->m_self);
    167     Py_VISIT(m->m_module);
    168     return 0;
    169 }
    170 
    171 static PyObject *
    172 meth_get__self__(PyCFunctionObject *m, void *closure)
    173 {
    174     PyObject *self;
    175     if (PyEval_GetRestricted()) {
    176         PyErr_SetString(PyExc_RuntimeError,
    177             "method.__self__ not accessible in restricted mode");
    178         return NULL;
    179     }
    180     self = m->m_self;
    181     if (self == NULL)
    182         self = Py_None;
    183     Py_INCREF(self);
    184     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 meth_repr(PyCFunctionObject *m)
    203 {
    204     if (m->m_self == NULL)
    205         return PyString_FromFormat("<built-in function %s>",
    206                                    m->m_ml->ml_name);
    207     return PyString_FromFormat("<built-in method %s of %s object at %p>",
    208                                m->m_ml->ml_name,
    209                                m->m_self->ob_type->tp_name,
    210                                m->m_self);
    211 }
    212 
    213 static int
    214 meth_compare(PyCFunctionObject *a, PyCFunctionObject *b)
    215 {
    216     if (a->m_self != b->m_self)
    217         return (a->m_self < b->m_self) ? -1 : 1;
    218     if (a->m_ml->ml_meth == b->m_ml->ml_meth)
    219         return 0;
    220     if (strcmp(a->m_ml->ml_name, b->m_ml->ml_name) < 0)
    221         return -1;
    222     else
    223         return 1;
    224 }
    225 
    226 static PyObject *
    227 meth_richcompare(PyObject *self, PyObject *other, int op)
    228 {
    229     PyCFunctionObject *a, *b;
    230     PyObject *res;
    231     int eq;
    232 
    233     if (op != Py_EQ && op != Py_NE) {
    234         /* Py3K warning if comparison isn't == or !=.  */
    235         if (PyErr_WarnPy3k("builtin_function_or_method order "
    236                            "comparisons not supported in 3.x", 1) < 0) {
    237             return NULL;
    238         }
    239 
    240         Py_INCREF(Py_NotImplemented);
    241         return Py_NotImplemented;
    242     }
    243     else if (!PyCFunction_Check(self) || !PyCFunction_Check(other)) {
    244         Py_INCREF(Py_NotImplemented);
    245         return Py_NotImplemented;
    246     }
    247     a = (PyCFunctionObject *)self;
    248     b = (PyCFunctionObject *)other;
    249     eq = a->m_self == b->m_self;
    250     if (eq)
    251         eq = a->m_ml->ml_meth == b->m_ml->ml_meth;
    252     if (op == Py_EQ)
    253         res = eq ? Py_True : Py_False;
    254     else
    255         res = eq ? Py_False : Py_True;
    256     Py_INCREF(res);
    257     return res;
    258 }
    259 
    260 static long
    261 meth_hash(PyCFunctionObject *a)
    262 {
    263     long x,y;
    264     if (a->m_self == NULL)
    265         x = 0;
    266     else {
    267         x = PyObject_Hash(a->m_self);
    268         if (x == -1)
    269             return -1;
    270     }
    271     y = _Py_HashPointer((void*)(a->m_ml->ml_meth));
    272     if (y == -1)
    273         return -1;
    274     x ^= y;
    275     if (x == -1)
    276         x = -2;
    277     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 listmethodchain(PyMethodChain *chain)
    320 {
    321     PyMethodChain *c;
    322     PyMethodDef *ml;
    323     int i, n;
    324     PyObject *v;
    325 
    326     n = 0;
    327     for (c = chain; c != NULL; c = c->link) {
    328         for (ml = c->methods; ml->ml_name != NULL; ml++)
    329             n++;
    330     }
    331     v = PyList_New(n);
    332     if (v == NULL)
    333         return NULL;
    334     i = 0;
    335     for (c = chain; c != NULL; c = c->link) {
    336         for (ml = c->methods; ml->ml_name != NULL; ml++) {
    337             PyList_SetItem(v, i, PyString_FromString(ml->ml_name));
    338             i++;
    339         }
    340     }
    341     if (PyErr_Occurred()) {
    342         Py_DECREF(v);
    343         return NULL;
    344     }
    345     PyList_Sort(v);
    346     return v;
    347 }
    348 
    349 /* Find a method in a method chain */
    350 
    351 PyObject *
    352 Py_FindMethodInChain(PyMethodChain *chain, PyObject *self, const char *name)
    353 {
    354     if (name[0] == '_' && name[1] == '_') {
    355         if (strcmp(name, "__methods__") == 0) {
    356             if (PyErr_WarnPy3k("__methods__ not supported in 3.x",
    357                                1) < 0)
    358                 return NULL;
    359             return listmethodchain(chain);
    360         }
    361         if (strcmp(name, "__doc__") == 0) {
    362             const char *doc = self->ob_type->tp_doc;
    363             if (doc != NULL)
    364                 return PyString_FromString(doc);
    365         }
    366     }
    367     while (chain != NULL) {
    368         PyMethodDef *ml = chain->methods;
    369         for (; ml->ml_name != NULL; ml++) {
    370             if (name[0] == ml->ml_name[0] &&
    371                 strcmp(name+1, ml->ml_name+1) == 0)
    372                 /* XXX */
    373                 return PyCFunction_New(ml, self);
    374         }
    375         chain = chain->link;
    376     }
    377     PyErr_SetString(PyExc_AttributeError, name);
    378     return NULL;
    379 }
    380 
    381 /* Find a method in a single method list */
    382 
    383 PyObject *
    384 Py_FindMethod(PyMethodDef *methods, PyObject *self, const char *name)
    385 {
    386     PyMethodChain chain;
    387     chain.methods = methods;
    388     chain.link = NULL;
    389     return Py_FindMethodInChain(&chain, self, name);
    390 }
    391 
    392 /* Clear out the free list */
    393 
    394 int
    395 PyCFunction_ClearFreeList(void)
    396 {
    397     int freelist_size = numfree;
    398 
    399     while (free_list) {
    400         PyCFunctionObject *v = free_list;
    401         free_list = (PyCFunctionObject *)(v->m_self);
    402         PyObject_GC_Del(v);
    403         numfree--;
    404     }
    405     assert(numfree == 0);
    406     return freelist_size;
    407 }
    408 
    409 void
    410 PyCFunction_Fini(void)
    411 {
    412     (void)PyCFunction_ClearFreeList();
    413 }
    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 PyCFunction_New(PyMethodDef *ml, PyObject *self)
    425 {
    426     return PyCFunction_NewEx(ml, self, NULL);
    427 }
    428