summaryrefslogtreecommitdiff
path: root/Objects/methodobject.c
diff options
context:
space:
mode:
authorAndrew Svetlov <andrew.svetlov@gmail.com>2015-04-27 17:49:16 +0300
committerAndrew Svetlov <andrew.svetlov@gmail.com>2015-04-27 17:49:16 +0300
commit13a15fdf72ae04057bc65d050c55096d7ea718d6 (patch)
tree9cf3386d6b0e5875e85b908eb8dc5458eec21060 /Objects/methodobject.c
parent2da0dc782446a9622abd55df5e05d1a1bbb4b3ab (diff)
parent7c7a65ced6e0522fb386dba270ad10fd3892a5f0 (diff)
downloadcpython-13a15fdf72ae04057bc65d050c55096d7ea718d6.tar.gz
Merge 3.4
Diffstat (limited to 'Objects/methodobject.c')
-rw-r--r--Objects/methodobject.c107
1 files changed, 57 insertions, 50 deletions
diff --git a/Objects/methodobject.c b/Objects/methodobject.c
index 9b6e5e42eb..1817722940 100644
--- a/Objects/methodobject.c
+++ b/Objects/methodobject.c
@@ -37,6 +37,7 @@ PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)
if (op == NULL)
return NULL;
}
+ op->m_weakreflist = NULL;
op->m_ml = ml;
Py_XINCREF(self);
op->m_self = self;
@@ -77,68 +78,71 @@ PyCFunction_GetFlags(PyObject *op)
}
PyObject *
-PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw)
+PyCFunction_Call(PyObject *func, PyObject *args, PyObject *kwds)
{
-#define CHECK_RESULT(res) assert(res != NULL || PyErr_Occurred())
-
PyCFunctionObject* f = (PyCFunctionObject*)func;
PyCFunction meth = PyCFunction_GET_FUNCTION(func);
PyObject *self = PyCFunction_GET_SELF(func);
- PyObject *res;
+ PyObject *arg, *res;
Py_ssize_t size;
+ int flags;
- switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) {
- case METH_VARARGS:
- if (kw == NULL || PyDict_Size(kw) == 0) {
- res = (*meth)(self, arg);
- CHECK_RESULT(res);
- return res;
- }
- break;
- case METH_VARARGS | METH_KEYWORDS:
- res = (*(PyCFunctionWithKeywords)meth)(self, arg, kw);
- CHECK_RESULT(res);
- return res;
- case METH_NOARGS:
- if (kw == NULL || PyDict_Size(kw) == 0) {
- size = PyTuple_GET_SIZE(arg);
- if (size == 0) {
- res = (*meth)(self, NULL);
- CHECK_RESULT(res);
- return res;
- }
- PyErr_Format(PyExc_TypeError,
- "%.200s() takes no arguments (%zd given)",
- f->m_ml->ml_name, size);
+ /* PyCFunction_Call() must not be called with an exception set,
+ because it may clear it (directly or indirectly) and so the
+ caller looses its exception */
+ assert(!PyErr_Occurred());
+
+ flags = PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST);
+
+ if (flags == (METH_VARARGS | METH_KEYWORDS)) {
+ res = (*(PyCFunctionWithKeywords)meth)(self, args, kwds);
+ }
+ else {
+ if (kwds != NULL && PyDict_Size(kwds) != 0) {
+ PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
+ f->m_ml->ml_name);
return NULL;
}
- break;
- case METH_O:
- if (kw == NULL || PyDict_Size(kw) == 0) {
- size = PyTuple_GET_SIZE(arg);
- if (size == 1) {
- res = (*meth)(self, PyTuple_GET_ITEM(arg, 0));
- CHECK_RESULT(res);
- return res;
+
+ switch (flags) {
+ case METH_VARARGS:
+ res = (*meth)(self, args);
+ break;
+
+ case METH_NOARGS:
+ size = PyTuple_GET_SIZE(args);
+ if (size != 0) {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s() takes no arguments (%zd given)",
+ f->m_ml->ml_name, size);
+ return NULL;
}
- PyErr_Format(PyExc_TypeError,
- "%.200s() takes exactly one argument (%zd given)",
- f->m_ml->ml_name, size);
+
+ res = (*meth)(self, NULL);
+ break;
+
+ case METH_O:
+ size = PyTuple_GET_SIZE(args);
+ if (size != 1) {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s() takes exactly one argument (%zd given)",
+ f->m_ml->ml_name, size);
+ return NULL;
+ }
+
+ arg = PyTuple_GET_ITEM(args, 0);
+ res = (*meth)(self, arg);
+ break;
+
+ default:
+ PyErr_SetString(PyExc_SystemError,
+ "Bad call flags in PyCFunction_Call. "
+ "METH_OLDARGS is no longer supported!");
return NULL;
}
- break;
- default:
- PyErr_SetString(PyExc_SystemError, "Bad call flags in "
- "PyCFunction_Call. METH_OLDARGS is no "
- "longer supported!");
-
- return NULL;
}
- PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
- f->m_ml->ml_name);
- return NULL;
-#undef CHECK_RESULT
+ return _Py_CheckFunctionResult(func, res, NULL);
}
/* Methods (the standard built-in methods, that is) */
@@ -147,6 +151,9 @@ static void
meth_dealloc(PyCFunctionObject *m)
{
_PyObject_GC_UNTRACK(m);
+ if (m->m_weakreflist != NULL) {
+ PyObject_ClearWeakRefs((PyObject*) m);
+ }
Py_XDECREF(m->m_self);
Py_XDECREF(m->m_module);
if (numfree < PyCFunction_MAXFREELIST) {
@@ -352,7 +359,7 @@ PyTypeObject PyCFunction_Type = {
(traverseproc)meth_traverse, /* tp_traverse */
0, /* tp_clear */
meth_richcompare, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
+ offsetof(PyCFunctionObject, m_weakreflist), /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
meth_methods, /* tp_methods */