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 : }
|