Python-2.7.3/Objects/methodobject.c

No issues found

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