PageRenderTime 38ms CodeModel.GetById 15ms app.highlight 20ms RepoModel.GetById 0ms app.codeStats 1ms

/Objects/methodobject.c

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