Move items implemented after a2 into the new a3 section
[python.git] / Objects / methodobject.c
blobecc9a0ab5257e5730f12afa2d3cb93946ead9ec9
2 /* Method object implementation */
4 #include "Python.h"
5 #include "structmember.h"
7 static PyCFunctionObject *free_list = NULL;
9 PyObject *
10 PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)
12 PyCFunctionObject *op;
13 op = free_list;
14 if (op != NULL) {
15 free_list = (PyCFunctionObject *)(op->m_self);
16 PyObject_INIT(op, &PyCFunction_Type);
18 else {
19 op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
20 if (op == NULL)
21 return NULL;
23 op->m_ml = ml;
24 Py_XINCREF(self);
25 op->m_self = self;
26 Py_XINCREF(module);
27 op->m_module = module;
28 _PyObject_GC_TRACK(op);
29 return (PyObject *)op;
32 PyCFunction
33 PyCFunction_GetFunction(PyObject *op)
35 if (!PyCFunction_Check(op)) {
36 PyErr_BadInternalCall();
37 return NULL;
39 return ((PyCFunctionObject *)op) -> m_ml -> ml_meth;
42 PyObject *
43 PyCFunction_GetSelf(PyObject *op)
45 if (!PyCFunction_Check(op)) {
46 PyErr_BadInternalCall();
47 return NULL;
49 return ((PyCFunctionObject *)op) -> m_self;
52 int
53 PyCFunction_GetFlags(PyObject *op)
55 if (!PyCFunction_Check(op)) {
56 PyErr_BadInternalCall();
57 return -1;
59 return ((PyCFunctionObject *)op) -> m_ml -> ml_flags;
62 PyObject *
63 PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw)
65 PyCFunctionObject* f = (PyCFunctionObject*)func;
66 PyCFunction meth = PyCFunction_GET_FUNCTION(func);
67 PyObject *self = PyCFunction_GET_SELF(func);
68 Py_ssize_t size;
70 switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) {
71 case METH_VARARGS:
72 if (kw == NULL || PyDict_Size(kw) == 0)
73 return (*meth)(self, arg);
74 break;
75 case METH_VARARGS | METH_KEYWORDS:
76 case METH_OLDARGS | METH_KEYWORDS:
77 return (*(PyCFunctionWithKeywords)meth)(self, arg, kw);
78 case METH_NOARGS:
79 if (kw == NULL || PyDict_Size(kw) == 0) {
80 size = PyTuple_GET_SIZE(arg);
81 if (size == 0)
82 return (*meth)(self, NULL);
83 PyErr_Format(PyExc_TypeError,
84 "%.200s() takes no arguments (%zd given)",
85 f->m_ml->ml_name, size);
86 return NULL;
88 break;
89 case METH_O:
90 if (kw == NULL || PyDict_Size(kw) == 0) {
91 size = PyTuple_GET_SIZE(arg);
92 if (size == 1)
93 return (*meth)(self, PyTuple_GET_ITEM(arg, 0));
94 PyErr_Format(PyExc_TypeError,
95 "%.200s() takes exactly one argument (%zd given)",
96 f->m_ml->ml_name, size);
97 return NULL;
99 break;
100 case METH_OLDARGS:
101 /* the really old style */
102 if (kw == NULL || PyDict_Size(kw) == 0) {
103 size = PyTuple_GET_SIZE(arg);
104 if (size == 1)
105 arg = PyTuple_GET_ITEM(arg, 0);
106 else if (size == 0)
107 arg = NULL;
108 return (*meth)(self, arg);
110 break;
111 default:
112 PyErr_BadInternalCall();
113 return NULL;
115 PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
116 f->m_ml->ml_name);
117 return NULL;
120 /* Methods (the standard built-in methods, that is) */
122 static void
123 meth_dealloc(PyCFunctionObject *m)
125 _PyObject_GC_UNTRACK(m);
126 Py_XDECREF(m->m_self);
127 Py_XDECREF(m->m_module);
128 m->m_self = (PyObject *)free_list;
129 free_list = m;
132 static PyObject *
133 meth_get__doc__(PyCFunctionObject *m, void *closure)
135 const char *doc = m->m_ml->ml_doc;
137 if (doc != NULL)
138 return PyString_FromString(doc);
139 Py_INCREF(Py_None);
140 return Py_None;
143 static PyObject *
144 meth_get__name__(PyCFunctionObject *m, void *closure)
146 return PyString_FromString(m->m_ml->ml_name);
149 static int
150 meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg)
152 Py_VISIT(m->m_self);
153 Py_VISIT(m->m_module);
154 return 0;
157 static PyObject *
158 meth_get__self__(PyCFunctionObject *m, void *closure)
160 PyObject *self;
161 if (PyEval_GetRestricted()) {
162 PyErr_SetString(PyExc_RuntimeError,
163 "method.__self__ not accessible in restricted mode");
164 return NULL;
166 self = m->m_self;
167 if (self == NULL)
168 self = Py_None;
169 Py_INCREF(self);
170 return self;
173 static PyGetSetDef meth_getsets [] = {
174 {"__doc__", (getter)meth_get__doc__, NULL, NULL},
175 {"__name__", (getter)meth_get__name__, NULL, NULL},
176 {"__self__", (getter)meth_get__self__, NULL, NULL},
180 #define OFF(x) offsetof(PyCFunctionObject, x)
182 static PyMemberDef meth_members[] = {
183 {"__module__", T_OBJECT, OFF(m_module), WRITE_RESTRICTED},
184 {NULL}
187 static PyObject *
188 meth_repr(PyCFunctionObject *m)
190 if (m->m_self == NULL)
191 return PyString_FromFormat("<built-in function %s>",
192 m->m_ml->ml_name);
193 return PyString_FromFormat("<built-in method %s of %s object at %p>",
194 m->m_ml->ml_name,
195 m->m_self->ob_type->tp_name,
196 m->m_self);
199 static int
200 meth_compare(PyCFunctionObject *a, PyCFunctionObject *b)
202 if (a->m_self != b->m_self)
203 return (a->m_self < b->m_self) ? -1 : 1;
204 if (a->m_ml->ml_meth == b->m_ml->ml_meth)
205 return 0;
206 if (strcmp(a->m_ml->ml_name, b->m_ml->ml_name) < 0)
207 return -1;
208 else
209 return 1;
212 static long
213 meth_hash(PyCFunctionObject *a)
215 long x,y;
216 if (a->m_self == NULL)
217 x = 0;
218 else {
219 x = PyObject_Hash(a->m_self);
220 if (x == -1)
221 return -1;
223 y = _Py_HashPointer((void*)(a->m_ml->ml_meth));
224 if (y == -1)
225 return -1;
226 x ^= y;
227 if (x == -1)
228 x = -2;
229 return x;
233 PyTypeObject PyCFunction_Type = {
234 PyObject_HEAD_INIT(&PyType_Type)
236 "builtin_function_or_method",
237 sizeof(PyCFunctionObject),
239 (destructor)meth_dealloc, /* tp_dealloc */
240 0, /* tp_print */
241 0, /* tp_getattr */
242 0, /* tp_setattr */
243 (cmpfunc)meth_compare, /* tp_compare */
244 (reprfunc)meth_repr, /* tp_repr */
245 0, /* tp_as_number */
246 0, /* tp_as_sequence */
247 0, /* tp_as_mapping */
248 (hashfunc)meth_hash, /* tp_hash */
249 PyCFunction_Call, /* tp_call */
250 0, /* tp_str */
251 PyObject_GenericGetAttr, /* tp_getattro */
252 0, /* tp_setattro */
253 0, /* tp_as_buffer */
254 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
255 0, /* tp_doc */
256 (traverseproc)meth_traverse, /* tp_traverse */
257 0, /* tp_clear */
258 0, /* tp_richcompare */
259 0, /* tp_weaklistoffset */
260 0, /* tp_iter */
261 0, /* tp_iternext */
262 0, /* tp_methods */
263 meth_members, /* tp_members */
264 meth_getsets, /* tp_getset */
265 0, /* tp_base */
266 0, /* tp_dict */
269 /* List all methods in a chain -- helper for findmethodinchain */
271 static PyObject *
272 listmethodchain(PyMethodChain *chain)
274 PyMethodChain *c;
275 PyMethodDef *ml;
276 int i, n;
277 PyObject *v;
279 n = 0;
280 for (c = chain; c != NULL; c = c->link) {
281 for (ml = c->methods; ml->ml_name != NULL; ml++)
282 n++;
284 v = PyList_New(n);
285 if (v == NULL)
286 return NULL;
287 i = 0;
288 for (c = chain; c != NULL; c = c->link) {
289 for (ml = c->methods; ml->ml_name != NULL; ml++) {
290 PyList_SetItem(v, i, PyString_FromString(ml->ml_name));
291 i++;
294 if (PyErr_Occurred()) {
295 Py_DECREF(v);
296 return NULL;
298 PyList_Sort(v);
299 return v;
302 /* Find a method in a method chain */
304 PyObject *
305 Py_FindMethodInChain(PyMethodChain *chain, PyObject *self, const char *name)
307 if (name[0] == '_' && name[1] == '_') {
308 if (strcmp(name, "__methods__") == 0)
309 return listmethodchain(chain);
310 if (strcmp(name, "__doc__") == 0) {
311 const char *doc = self->ob_type->tp_doc;
312 if (doc != NULL)
313 return PyString_FromString(doc);
316 while (chain != NULL) {
317 PyMethodDef *ml = chain->methods;
318 for (; ml->ml_name != NULL; ml++) {
319 if (name[0] == ml->ml_name[0] &&
320 strcmp(name+1, ml->ml_name+1) == 0)
321 /* XXX */
322 return PyCFunction_New(ml, self);
324 chain = chain->link;
326 PyErr_SetString(PyExc_AttributeError, name);
327 return NULL;
330 /* Find a method in a single method list */
332 PyObject *
333 Py_FindMethod(PyMethodDef *methods, PyObject *self, const char *name)
335 PyMethodChain chain;
336 chain.methods = methods;
337 chain.link = NULL;
338 return Py_FindMethodInChain(&chain, self, name);
341 /* Clear out the free list */
343 void
344 PyCFunction_Fini(void)
346 while (free_list) {
347 PyCFunctionObject *v = free_list;
348 free_list = (PyCFunctionObject *)(v->m_self);
349 PyObject_GC_Del(v);
353 /* PyCFunction_New() is now just a macro that calls PyCFunction_NewEx(),
354 but it's part of the API so we need to keep a function around that
355 existing C extensions can call.
358 #undef PyCFunction_New
359 PyAPI_FUNC(PyObject *) PyCFunction_New(PyMethodDef *, PyObject *);
361 PyObject *
362 PyCFunction_New(PyMethodDef *ml, PyObject *self)
364 return PyCFunction_NewEx(ml, self, NULL);