2 /* Method object implementation */
5 #include "structmember.h"
7 /* Free list for method objects to safe malloc/free overhead
8 * The m_self element is used to chain the objects.
10 static PyCFunctionObject
*free_list
= NULL
;
11 static int numfree
= 0;
12 #ifndef PyCFunction_MAXFREELIST
13 #define PyCFunction_MAXFREELIST 256
17 PyCFunction_NewEx(PyMethodDef
*ml
, PyObject
*self
, PyObject
*module
)
19 PyCFunctionObject
*op
;
22 free_list
= (PyCFunctionObject
*)(op
->m_self
);
23 PyObject_INIT(op
, &PyCFunction_Type
);
27 op
= PyObject_GC_New(PyCFunctionObject
, &PyCFunction_Type
);
35 op
->m_module
= module
;
36 _PyObject_GC_TRACK(op
);
37 return (PyObject
*)op
;
41 PyCFunction_GetFunction(PyObject
*op
)
43 if (!PyCFunction_Check(op
)) {
44 PyErr_BadInternalCall();
47 return ((PyCFunctionObject
*)op
) -> m_ml
-> ml_meth
;
51 PyCFunction_GetSelf(PyObject
*op
)
53 if (!PyCFunction_Check(op
)) {
54 PyErr_BadInternalCall();
57 return ((PyCFunctionObject
*)op
) -> m_self
;
61 PyCFunction_GetFlags(PyObject
*op
)
63 if (!PyCFunction_Check(op
)) {
64 PyErr_BadInternalCall();
67 return ((PyCFunctionObject
*)op
) -> m_ml
-> ml_flags
;
71 PyCFunction_Call(PyObject
*func
, PyObject
*arg
, PyObject
*kw
)
73 PyCFunctionObject
* f
= (PyCFunctionObject
*)func
;
74 PyCFunction meth
= PyCFunction_GET_FUNCTION(func
);
75 PyObject
*self
= PyCFunction_GET_SELF(func
);
78 switch (PyCFunction_GET_FLAGS(func
) & ~(METH_CLASS
| METH_STATIC
| METH_COEXIST
)) {
80 if (kw
== NULL
|| PyDict_Size(kw
) == 0)
81 return (*meth
)(self
, arg
);
83 case METH_VARARGS
| METH_KEYWORDS
:
84 case METH_OLDARGS
| METH_KEYWORDS
:
85 return (*(PyCFunctionWithKeywords
)meth
)(self
, arg
, kw
);
87 if (kw
== NULL
|| PyDict_Size(kw
) == 0) {
88 size
= PyTuple_GET_SIZE(arg
);
90 return (*meth
)(self
, NULL
);
91 PyErr_Format(PyExc_TypeError
,
92 "%.200s() takes no arguments (%zd given)",
93 f
->m_ml
->ml_name
, size
);
98 if (kw
== NULL
|| PyDict_Size(kw
) == 0) {
99 size
= PyTuple_GET_SIZE(arg
);
101 return (*meth
)(self
, PyTuple_GET_ITEM(arg
, 0));
102 PyErr_Format(PyExc_TypeError
,
103 "%.200s() takes exactly one argument (%zd given)",
104 f
->m_ml
->ml_name
, size
);
109 /* the really old style */
110 if (kw
== NULL
|| PyDict_Size(kw
) == 0) {
111 size
= PyTuple_GET_SIZE(arg
);
113 arg
= PyTuple_GET_ITEM(arg
, 0);
116 return (*meth
)(self
, arg
);
120 PyErr_BadInternalCall();
123 PyErr_Format(PyExc_TypeError
, "%.200s() takes no keyword arguments",
128 /* Methods (the standard built-in methods, that is) */
131 meth_dealloc(PyCFunctionObject
*m
)
133 _PyObject_GC_UNTRACK(m
);
134 Py_XDECREF(m
->m_self
);
135 Py_XDECREF(m
->m_module
);
136 if (numfree
< PyCFunction_MAXFREELIST
) {
137 m
->m_self
= (PyObject
*)free_list
;
147 meth_get__doc__(PyCFunctionObject
*m
, void *closure
)
149 const char *doc
= m
->m_ml
->ml_doc
;
152 return PyString_FromString(doc
);
158 meth_get__name__(PyCFunctionObject
*m
, void *closure
)
160 return PyString_FromString(m
->m_ml
->ml_name
);
164 meth_traverse(PyCFunctionObject
*m
, visitproc visit
, void *arg
)
167 Py_VISIT(m
->m_module
);
172 meth_get__self__(PyCFunctionObject
*m
, void *closure
)
175 if (PyEval_GetRestricted()) {
176 PyErr_SetString(PyExc_RuntimeError
,
177 "method.__self__ not accessible in restricted mode");
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
},
194 #define OFF(x) offsetof(PyCFunctionObject, x)
196 static PyMemberDef meth_members
[] = {
197 {"__module__", T_OBJECT
, OFF(m_module
), PY_WRITE_RESTRICTED
},
202 meth_repr(PyCFunctionObject
*m
)
204 if (m
->m_self
== NULL
)
205 return PyString_FromFormat("<built-in function %s>",
207 return PyString_FromFormat("<built-in method %s of %s object at %p>",
209 m
->m_self
->ob_type
->tp_name
,
214 meth_compare(PyCFunctionObject
*a
, PyCFunctionObject
*b
)
216 if (a
->m_self
!= b
->m_self
)
217 return (a
->m_self
< b
->m_self
) ? -1 : 1;
218 if (a
->m_ml
->ml_meth
== b
->m_ml
->ml_meth
)
220 if (strcmp(a
->m_ml
->ml_name
, b
->m_ml
->ml_name
) < 0)
227 meth_richcompare(PyObject
*self
, PyObject
*other
, int op
)
229 PyCFunctionObject
*a
, *b
;
233 if ((op
!= Py_EQ
&& op
!= Py_NE
) ||
234 !PyCFunction_Check(self
) ||
235 !PyCFunction_Check(other
))
237 /* Py3K warning if types are not equal and comparison isn't == or != */
238 if (PyErr_WarnPy3k("builtin_function_or_method inequality "
239 "comparisons not supported in 3.x", 1) < 0) {
243 Py_INCREF(Py_NotImplemented
);
244 return Py_NotImplemented
;
246 a
= (PyCFunctionObject
*)self
;
247 b
= (PyCFunctionObject
*)other
;
248 eq
= a
->m_self
== b
->m_self
;
250 eq
= a
->m_ml
->ml_meth
== b
->m_ml
->ml_meth
;
252 res
= eq
? Py_True
: Py_False
;
254 res
= eq
? Py_False
: Py_True
;
260 meth_hash(PyCFunctionObject
*a
)
263 if (a
->m_self
== NULL
)
266 x
= PyObject_Hash(a
->m_self
);
270 y
= _Py_HashPointer((void*)(a
->m_ml
->ml_meth
));
280 PyTypeObject PyCFunction_Type
= {
281 PyVarObject_HEAD_INIT(&PyType_Type
, 0)
282 "builtin_function_or_method",
283 sizeof(PyCFunctionObject
),
285 (destructor
)meth_dealloc
, /* tp_dealloc */
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 */
297 PyObject_GenericGetAttr
, /* tp_getattro */
299 0, /* tp_as_buffer */
300 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_GC
,/* tp_flags */
302 (traverseproc
)meth_traverse
, /* tp_traverse */
304 meth_richcompare
, /* tp_richcompare */
305 0, /* tp_weaklistoffset */
309 meth_members
, /* tp_members */
310 meth_getsets
, /* tp_getset */
315 /* List all methods in a chain -- helper for findmethodinchain */
318 listmethodchain(PyMethodChain
*chain
)
326 for (c
= chain
; c
!= NULL
; c
= c
->link
) {
327 for (ml
= c
->methods
; ml
->ml_name
!= NULL
; ml
++)
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
));
340 if (PyErr_Occurred()) {
348 /* Find a method in a method chain */
351 Py_FindMethodInChain(PyMethodChain
*chain
, PyObject
*self
, const char *name
)
353 if (name
[0] == '_' && name
[1] == '_') {
354 if (strcmp(name
, "__methods__") == 0) {
355 if (PyErr_WarnPy3k("__methods__ not supported in 3.x",
358 return listmethodchain(chain
);
360 if (strcmp(name
, "__doc__") == 0) {
361 const char *doc
= self
->ob_type
->tp_doc
;
363 return PyString_FromString(doc
);
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)
372 return PyCFunction_New(ml
, self
);
376 PyErr_SetString(PyExc_AttributeError
, name
);
380 /* Find a method in a single method list */
383 Py_FindMethod(PyMethodDef
*methods
, PyObject
*self
, const char *name
)
386 chain
.methods
= methods
;
388 return Py_FindMethodInChain(&chain
, self
, name
);
391 /* Clear out the free list */
394 PyCFunction_ClearFreeList(void)
396 int freelist_size
= numfree
;
399 PyCFunctionObject
*v
= free_list
;
400 free_list
= (PyCFunctionObject
*)(v
->m_self
);
404 assert(numfree
== 0);
405 return freelist_size
;
409 PyCFunction_Fini(void)
411 (void)PyCFunction_ClearFreeList();
414 /* PyCFunction_New() is now just a macro that calls PyCFunction_NewEx(),
415 but it's part of the API so we need to keep a function around that
416 existing C extensions can call.
419 #undef PyCFunction_New
420 PyAPI_FUNC(PyObject
*) PyCFunction_New(PyMethodDef
*, PyObject
*);
423 PyCFunction_New(PyMethodDef
*ml
, PyObject
*self
)
425 return PyCFunction_NewEx(ml
, self
, NULL
);