methodobject.c 7.3 KB
Newer Older
1

Guido van Rossum's avatar
Guido van Rossum committed
2 3
/* Method object implementation */

4
#include "Python.h"
Guido van Rossum's avatar
Guido van Rossum committed
5

6 7
static PyCFunctionObject *free_list = NULL;

8
PyObject *
9
PyCFunction_New(PyMethodDef *ml, PyObject *self)
Guido van Rossum's avatar
Guido van Rossum committed
10
{
11 12
	PyCFunctionObject *op;
	op = free_list;
Guido van Rossum's avatar
Guido van Rossum committed
13
	if (op != NULL) {
14
		free_list = (PyCFunctionObject *)(op->m_self);
15
		PyObject_INIT(op, &PyCFunction_Type);
Guido van Rossum's avatar
Guido van Rossum committed
16
	}
17
	else {
18
		op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
19 20 21 22 23 24
		if (op == NULL)
			return NULL;
	}
	op->m_ml = ml;
	Py_XINCREF(self);
	op->m_self = self;
25
	_PyObject_GC_TRACK(op);
26
	return (PyObject *)op;
Guido van Rossum's avatar
Guido van Rossum committed
27 28
}

29
PyCFunction
30
PyCFunction_GetFunction(PyObject *op)
Guido van Rossum's avatar
Guido van Rossum committed
31
{
32 33
	if (!PyCFunction_Check(op)) {
		PyErr_BadInternalCall();
Guido van Rossum's avatar
Guido van Rossum committed
34 35
		return NULL;
	}
36
	return ((PyCFunctionObject *)op) -> m_ml -> ml_meth;
Guido van Rossum's avatar
Guido van Rossum committed
37 38
}

39
PyObject *
40
PyCFunction_GetSelf(PyObject *op)
Guido van Rossum's avatar
Guido van Rossum committed
41
{
42 43
	if (!PyCFunction_Check(op)) {
		PyErr_BadInternalCall();
Guido van Rossum's avatar
Guido van Rossum committed
44 45
		return NULL;
	}
46
	return ((PyCFunctionObject *)op) -> m_self;
Guido van Rossum's avatar
Guido van Rossum committed
47 48
}

49
int
50
PyCFunction_GetFlags(PyObject *op)
51
{
52 53
	if (!PyCFunction_Check(op)) {
		PyErr_BadInternalCall();
54 55
		return -1;
	}
56
	return ((PyCFunctionObject *)op) -> m_ml -> ml_flags;
57 58
}

59 60 61 62 63 64
PyObject *
PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw)
{
	PyCFunctionObject* f = (PyCFunctionObject*)func;
	PyCFunction meth = PyCFunction_GET_FUNCTION(func);
	PyObject *self = PyCFunction_GET_SELF(func);
65
	int size;
66

67
	switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC)) {
68
	case METH_VARARGS:
69 70 71 72
		if (kw == NULL || PyDict_Size(kw) == 0)
			return (*meth)(self, arg);
		break;
	case METH_VARARGS | METH_KEYWORDS:
73
	case METH_OLDARGS | METH_KEYWORDS:
74
		return (*(PyCFunctionWithKeywords)meth)(self, arg, kw);
75
	case METH_NOARGS:
76 77 78 79 80 81 82 83 84 85
		if (kw == NULL || PyDict_Size(kw) == 0) {
			size = PyTuple_GET_SIZE(arg);
			if (size == 0)
				return (*meth)(self, NULL);
			PyErr_Format(PyExc_TypeError,
			    "%.200s() takes no arguments (%d given)",
			    f->m_ml->ml_name, size);
			return NULL;
		}
		break;
86
	case METH_O:
87 88 89 90 91 92 93 94 95 96
		if (kw == NULL || PyDict_Size(kw) == 0) {
			size = PyTuple_GET_SIZE(arg);
			if (size == 1)
				return (*meth)(self, PyTuple_GET_ITEM(arg, 0));
			PyErr_Format(PyExc_TypeError,
			    "%.200s() takes exactly one argument (%d given)",
			    f->m_ml->ml_name, size);
			return NULL;
		}
		break;
97
	case METH_OLDARGS:
98
		/* the really old style */
99 100 101 102 103 104 105 106 107
		if (kw == NULL || PyDict_Size(kw) == 0) {
			size = PyTuple_GET_SIZE(arg);
			if (size == 1)
				arg = PyTuple_GET_ITEM(arg, 0);
			else if (size == 0)
				arg = NULL;
			return (*meth)(self, arg);
		}
		break;
108 109 110
	default:
		PyErr_BadInternalCall();
		return NULL;
111
	}
112 113 114
	PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
		     f->m_ml->ml_name);
	return NULL;
115 116
}

Guido van Rossum's avatar
Guido van Rossum committed
117 118 119
/* Methods (the standard built-in methods, that is) */

static void
120
meth_dealloc(PyCFunctionObject *m)
Guido van Rossum's avatar
Guido van Rossum committed
121
{
122
	_PyObject_GC_UNTRACK(m);
123
	Py_XDECREF(m->m_self);
124 125
	m->m_self = (PyObject *)free_list;
	free_list = m;
Guido van Rossum's avatar
Guido van Rossum committed
126 127
}

128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
static PyObject *
meth_get__doc__(PyCFunctionObject *m, void *closure)
{
	char *doc = m->m_ml->ml_doc;

	if (doc != NULL)
		return PyString_FromString(doc);
	Py_INCREF(Py_None);
	return Py_None;
}

static PyObject *
meth_get__name__(PyCFunctionObject *m, void *closure)
{
	return PyString_FromString(m->m_ml->ml_name);
}

145 146 147 148 149 150 151 152 153
static int
meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg)
{
	if (m->m_self != NULL)
		return visit(m->m_self, arg);
	else
		return 0;
}

154
static PyObject *
155
meth_get__self__(PyCFunctionObject *m, void *closure)
156
{
157 158 159 160 161
	PyObject *self;
	if (PyEval_GetRestricted()) {
		PyErr_SetString(PyExc_RuntimeError,
			"method.__self__ not accessible in restricted mode");
		return NULL;
162
	}
163 164 165 166 167
	self = m->m_self;
	if (self == NULL)
		self = Py_None;
	Py_INCREF(self);
	return self;
168 169
}

170
static PyGetSetDef meth_getsets [] = {
171 172 173 174 175 176
	{"__doc__",  (getter)meth_get__doc__,  NULL, NULL},
	{"__name__", (getter)meth_get__name__, NULL, NULL},
	{"__self__", (getter)meth_get__self__, NULL, NULL},
	{0}
};

177
static PyObject *
178
meth_repr(PyCFunctionObject *m)
Guido van Rossum's avatar
Guido van Rossum committed
179 180
{
	if (m->m_self == NULL)
181 182 183 184 185 186
		return PyString_FromFormat("<built-in function %s>",
					   m->m_ml->ml_name);
	return PyString_FromFormat("<built-in method %s of %s object at %p>",
				   m->m_ml->ml_name,
				   m->m_self->ob_type->tp_name,
				   m->m_self);
Guido van Rossum's avatar
Guido van Rossum committed
187 188
}

189
static int
190
meth_compare(PyCFunctionObject *a, PyCFunctionObject *b)
191 192
{
	if (a->m_self != b->m_self)
193
		return (a->m_self < b->m_self) ? -1 : 1;
194
	if (a->m_ml->ml_meth == b->m_ml->ml_meth)
195
		return 0;
196
	if (strcmp(a->m_ml->ml_name, b->m_ml->ml_name) < 0)
197 198 199 200 201 202
		return -1;
	else
		return 1;
}

static long
203
meth_hash(PyCFunctionObject *a)
204
{
205
	long x,y;
206 207 208
	if (a->m_self == NULL)
		x = 0;
	else {
209
		x = PyObject_Hash(a->m_self);
210 211 212
		if (x == -1)
			return -1;
	}
213
	y = _Py_HashPointer((void*)(a->m_ml->ml_meth));
214 215 216 217 218 219
	if (y == -1)
		return -1;
	x ^= y;
	if (x == -1)
		x = -2;
	return x;
220 221
}

222

223 224
PyTypeObject PyCFunction_Type = {
	PyObject_HEAD_INIT(&PyType_Type)
Guido van Rossum's avatar
Guido van Rossum committed
225
	0,
226
	"builtin_function_or_method",
227
	sizeof(PyCFunctionObject),
Guido van Rossum's avatar
Guido van Rossum committed
228
	0,
229 230
	(destructor)meth_dealloc, 		/* tp_dealloc */
	0,					/* tp_print */
231
	0,					/* tp_getattr */
232 233 234 235 236 237 238
	0,					/* tp_setattr */
	(cmpfunc)meth_compare,			/* tp_compare */
	(reprfunc)meth_repr,			/* tp_repr */
	0,					/* tp_as_number */
	0,					/* tp_as_sequence */
	0,					/* tp_as_mapping */
	(hashfunc)meth_hash,			/* tp_hash */
239
	PyCFunction_Call,			/* tp_call */
240
	0,					/* tp_str */
241
	PyObject_GenericGetAttr,		/* tp_getattro */
242 243
	0,					/* tp_setattro */
	0,					/* tp_as_buffer */
244
	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
245 246
 	0,					/* tp_doc */
 	(traverseproc)meth_traverse,		/* tp_traverse */
247 248 249 250 251 252 253 254 255 256
	0,					/* tp_clear */
	0,					/* tp_richcompare */
	0,					/* tp_weaklistoffset */
	0,					/* tp_iter */
	0,					/* tp_iternext */
	0,					/* tp_methods */
	0,					/* tp_members */
	meth_getsets,				/* tp_getset */
	0,					/* tp_base */
	0,					/* tp_dict */
Guido van Rossum's avatar
Guido van Rossum committed
257
};
Guido van Rossum's avatar
Guido van Rossum committed
258

259
/* List all methods in a chain -- helper for findmethodinchain */
260

261
static PyObject *
262
listmethodchain(PyMethodChain *chain)
263
{
264 265
	PyMethodChain *c;
	PyMethodDef *ml;
266
	int i, n;
267
	PyObject *v;
268

269 270 271 272 273
	n = 0;
	for (c = chain; c != NULL; c = c->link) {
		for (ml = c->methods; ml->ml_name != NULL; ml++)
			n++;
	}
274
	v = PyList_New(n);
275 276 277 278 279
	if (v == NULL)
		return NULL;
	i = 0;
	for (c = chain; c != NULL; c = c->link) {
		for (ml = c->methods; ml->ml_name != NULL; ml++) {
280
			PyList_SetItem(v, i, PyString_FromString(ml->ml_name));
281
			i++;
282 283
		}
	}
284 285
	if (PyErr_Occurred()) {
		Py_DECREF(v);
286 287
		return NULL;
	}
288
	PyList_Sort(v);
289 290 291
	return v;
}

292
/* Find a method in a method chain */
Guido van Rossum's avatar
Guido van Rossum committed
293

294
PyObject *
295
Py_FindMethodInChain(PyMethodChain *chain, PyObject *self, char *name)
Guido van Rossum's avatar
Guido van Rossum committed
296
{
297 298 299 300 301 302 303 304 305
	if (name[0] == '_' && name[1] == '_') {
		if (strcmp(name, "__methods__") == 0)
			return listmethodchain(chain);
		if (strcmp(name, "__doc__") == 0) {
			char *doc = self->ob_type->tp_doc;
			if (doc != NULL)
				return PyString_FromString(doc);
		}
	}
306
	while (chain != NULL) {
307
		PyMethodDef *ml = chain->methods;
308 309 310
		for (; ml->ml_name != NULL; ml++) {
			if (name[0] == ml->ml_name[0] &&
			    strcmp(name+1, ml->ml_name+1) == 0)
311
				return PyCFunction_New(ml, self);
312 313
		}
		chain = chain->link;
Guido van Rossum's avatar
Guido van Rossum committed
314
	}
315
	PyErr_SetString(PyExc_AttributeError, name);
Guido van Rossum's avatar
Guido van Rossum committed
316 317
	return NULL;
}
318 319 320

/* Find a method in a single method list */

321
PyObject *
322
Py_FindMethod(PyMethodDef *methods, PyObject *self, char *name)
323
{
324
	PyMethodChain chain;
325 326
	chain.methods = methods;
	chain.link = NULL;
327
	return Py_FindMethodInChain(&chain, self, name);
328
}
329 330 331 332

/* Clear out the free list */

void
333
PyCFunction_Fini(void)
334 335 336 337
{
	while (free_list) {
		PyCFunctionObject *v = free_list;
		free_list = (PyCFunctionObject *)(v->m_self);
338
		PyObject_GC_Del(v);
339 340
	}
}