[Python-checkins] CVS: python/dist/src/Objects abstract.c,2.60.2.1,2.60.2.2 classobject.c,2.127.2.1,2.127.2.2 funcobject.c,2.37,2.37.4.1 methodobject.c,2.33.8.3,2.33.8.4 object.c,2.124.4.6,2.124.4.7
Guido van Rossum
gvanrossum@users.sourceforge.net
Sat, 05 May 2001 04:37:31 -0700
Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv7122/Objects
Modified Files:
Tag: descr-branch
abstract.c classobject.c funcobject.c methodobject.c object.c
Log Message:
Reorganization of object calling.
The call_object() function, originally in ceval.c, begins a new life
as the official API PyObject_Call(). It is also much simplified: all
it does is call the tp_call slot, or raise an exception if that's
NULL.
The subsidiary functions (call_eval_code2(), call_cfunction(),
call_instance(), and call_method()) have all been moved to the file
implementing their particular object type, renamed according to the
local convention, and added to the type's tp_call slot. Note that
call_eval_code2() became function_call(); the tp_slot for class
objects now simply points to PyInstance_New(), which already has the
correct signature.
Because of these moves, there are some more new APIs that expose
helpers in ceval.c that are now needed outside: PyEval_GetFuncName(),
PyEval_GetFuncDesc(), PyEval_EvalCodeEx() (formerly get_func_name(),
get_func_desc(), and eval_code2().
Index: abstract.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/abstract.c,v
retrieving revision 2.60.2.1
retrieving revision 2.60.2.2
diff -C2 -r2.60.2.1 -r2.60.2.2
*** abstract.c 2001/05/04 16:52:44 2.60.2.1
--- abstract.c 2001/05/05 11:37:29 2.60.2.2
***************
*** 1537,1540 ****
--- 1537,1558 ----
PyObject *
+ PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw)
+ {
+ ternaryfunc call;
+
+ if ((call = func->ob_type->tp_call) != NULL) {
+ PyObject *result = (*call)(func, arg, kw);
+ if (result == NULL && !PyErr_Occurred())
+ PyErr_SetString(
+ PyExc_SystemError,
+ "NULL result without error in PyObject_Call");
+ return result;
+ }
+ PyErr_Format(PyExc_TypeError, "object is not callable: %s",
+ PyString_AS_STRING(PyObject_Repr(func)));
+ return NULL;
+ }
+
+ PyObject *
PyObject_CallFunction(PyObject *callable, char *format, ...)
{
Index: classobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/classobject.c,v
retrieving revision 2.127.2.1
retrieving revision 2.127.2.2
diff -C2 -r2.127.2.1 -r2.127.2.2
*** classobject.c 2001/04/30 14:37:19 2.127.2.1
--- classobject.c 2001/05/05 11:37:29 2.127.2.2
***************
*** 397,401 ****
0, /* tp_as_mapping */
0, /* tp_hash */
! 0, /* tp_call */
(reprfunc)class_str, /* tp_str */
(getattrofunc)class_getattr, /* tp_getattro */
--- 397,401 ----
0, /* tp_as_mapping */
0, /* tp_hash */
! PyInstance_New, /* tp_call */
(reprfunc)class_str, /* tp_str */
(getattrofunc)class_getattr, /* tp_getattro */
***************
*** 1792,1795 ****
--- 1792,1812 ----
}
+ static PyObject *
+ instance_call(PyObject *func, PyObject *arg, PyObject *kw)
+ {
+ PyObject *res, *call = PyObject_GetAttrString(func, "__call__");
+ if (call == NULL) {
+ PyInstanceObject *inst = (PyInstanceObject*) func;
+ PyErr_Clear();
+ PyErr_Format(PyExc_AttributeError,
+ "%.200s instance has no __call__ method",
+ PyString_AsString(inst->in_class->cl_name));
+ return NULL;
+ }
+ res = PyObject_Call(call, arg, kw);
+ Py_DECREF(call);
+ return res;
+ }
+
static PyNumberMethods instance_as_number = {
***************
*** 1846,1850 ****
&instance_as_mapping, /* tp_as_mapping */
(hashfunc)instance_hash, /* tp_hash */
! 0, /* tp_call */
(reprfunc)instance_str, /* tp_str */
(getattrofunc)instance_getattr, /* tp_getattro */
--- 1863,1867 ----
&instance_as_mapping, /* tp_as_mapping */
(hashfunc)instance_hash, /* tp_hash */
! instance_call, /* tp_call */
(reprfunc)instance_str, /* tp_str */
(getattrofunc)instance_getattr, /* tp_getattro */
***************
*** 2083,2086 ****
--- 2100,2154 ----
}
+ static PyObject *
+ instancemethod_call(PyObject *func, PyObject *arg, PyObject *kw)
+ {
+ PyObject *self = PyMethod_GET_SELF(func);
+ PyObject *class = PyMethod_GET_CLASS(func);
+ PyObject *result;
+
+ func = PyMethod_GET_FUNCTION(func);
+ if (self == NULL) {
+ /* Unbound methods must be called with an instance of
+ the class (or a derived class) as first argument */
+ int ok;
+ if (PyTuple_Size(arg) >= 1)
+ self = PyTuple_GET_ITEM(arg, 0);
+ if (self == NULL)
+ ok = 0;
+ else {
+ ok = PyObject_IsInstance(self, class);
+ if (ok < 0)
+ return NULL;
+ }
+ if (!ok) {
+ PyErr_Format(PyExc_TypeError,
+ "unbound method %s%s must be "
+ "called with instance as first argument",
+ PyEval_GetFuncName(func),
+ PyEval_GetFuncDesc(func));
+ return NULL;
+ }
+ Py_INCREF(arg);
+ }
+ else {
+ int argcount = PyTuple_Size(arg);
+ PyObject *newarg = PyTuple_New(argcount + 1);
+ int i;
+ if (newarg == NULL)
+ return NULL;
+ Py_INCREF(self);
+ PyTuple_SET_ITEM(newarg, 0, self);
+ for (i = 0; i < argcount; i++) {
+ PyObject *v = PyTuple_GET_ITEM(arg, i);
+ Py_XINCREF(v);
+ PyTuple_SET_ITEM(newarg, i+1, v);
+ }
+ arg = newarg;
+ }
+ result = PyObject_Call((PyObject *)func, arg, kw);
+ Py_DECREF(arg);
+ return result;
+ }
+
PyTypeObject PyMethod_Type = {
PyObject_HEAD_INIT(&PyType_Type)
***************
*** 2099,2108 ****
0, /* tp_as_mapping */
(hashfunc)instancemethod_hash, /* tp_hash */
! 0, /* tp_call */
0, /* tp_str */
(getattrofunc)instancemethod_getattro, /* tp_getattro */
(setattrofunc)instancemethod_setattro, /* tp_setattro */
0, /* tp_as_buffer */
! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC | Py_TPFLAGS_HAVE_WEAKREFS,
0, /* tp_doc */
(traverseproc)instancemethod_traverse, /* tp_traverse */
--- 2167,2176 ----
0, /* tp_as_mapping */
(hashfunc)instancemethod_hash, /* tp_hash */
! instancemethod_call, /* tp_call */
0, /* tp_str */
(getattrofunc)instancemethod_getattro, /* tp_getattro */
(setattrofunc)instancemethod_setattro, /* tp_setattro */
0, /* tp_as_buffer */
! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC,
0, /* tp_doc */
(traverseproc)instancemethod_traverse, /* tp_traverse */
Index: funcobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/funcobject.c,v
retrieving revision 2.37
retrieving revision 2.37.4.1
diff -C2 -r2.37 -r2.37.4.1
*** funcobject.c 2001/03/23 04:19:27 2.37
--- funcobject.c 2001/05/05 11:37:29 2.37.4.1
***************
*** 4,7 ****
--- 4,8 ----
#include "Python.h"
#include "compile.h"
+ #include "eval.h"
#include "structmember.h"
***************
*** 315,318 ****
--- 316,370 ----
}
+ static PyObject *
+ function_call(PyObject *func, PyObject *arg, PyObject *kw)
+ {
+ PyObject *result;
+ PyObject *argdefs;
+ PyObject **d, **k;
+ int nk, nd;
+
+ argdefs = PyFunction_GET_DEFAULTS(func);
+ if (argdefs != NULL && PyTuple_Check(argdefs)) {
+ d = &PyTuple_GET_ITEM((PyTupleObject *)argdefs, 0);
+ nd = PyTuple_Size(argdefs);
+ }
+ else {
+ d = NULL;
+ nd = 0;
+ }
+
+ if (kw != NULL && PyDict_Check(kw)) {
+ int pos, i;
+ nk = PyDict_Size(kw);
+ k = PyMem_NEW(PyObject *, 2*nk);
+ if (k == NULL) {
+ PyErr_NoMemory();
+ Py_DECREF(arg);
+ return NULL;
+ }
+ pos = i = 0;
+ while (PyDict_Next(kw, &pos, &k[i], &k[i+1]))
+ i += 2;
+ nk = i/2;
+ /* XXX This is broken if the caller deletes dict items! */
+ }
+ else {
+ k = NULL;
+ nk = 0;
+ }
+
+ result = PyEval_EvalCodeEx(
+ (PyCodeObject *)PyFunction_GET_CODE(func),
+ PyFunction_GET_GLOBALS(func), (PyObject *)NULL,
+ &PyTuple_GET_ITEM(arg, 0), PyTuple_Size(arg),
+ k, nk, d, nd,
+ PyFunction_GET_CLOSURE(func));
+
+ if (k != NULL)
+ PyMem_DEL(k);
+
+ return result;
+ }
+
PyTypeObject PyFunction_Type = {
PyObject_HEAD_INIT(&PyType_Type)
***************
*** 331,340 ****
0, /*tp_as_mapping*/
0, /*tp_hash*/
! 0, /*tp_call*/
0, /*tp_str*/
(getattrofunc)func_getattro, /*tp_getattro*/
(setattrofunc)func_setattro, /*tp_setattro*/
0, /* tp_as_buffer */
! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC | Py_TPFLAGS_HAVE_WEAKREFS,
0, /* tp_doc */
(traverseproc)func_traverse, /* tp_traverse */
--- 383,392 ----
0, /*tp_as_mapping*/
0, /*tp_hash*/
! function_call, /*tp_call*/
0, /*tp_str*/
(getattrofunc)func_getattro, /*tp_getattro*/
(setattrofunc)func_setattro, /*tp_setattro*/
0, /* tp_as_buffer */
! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC,
0, /* tp_doc */
(traverseproc)func_traverse, /* tp_traverse */
Index: methodobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/methodobject.c,v
retrieving revision 2.33.8.3
retrieving revision 2.33.8.4
diff -C2 -r2.33.8.3 -r2.33.8.4
*** methodobject.c 2001/04/27 18:04:51 2.33.8.3
--- methodobject.c 2001/05/05 11:37:29 2.33.8.4
***************
*** 153,156 ****
--- 153,191 ----
}
+ static PyObject *
+ meth_call(PyObject *func, PyObject *arg, PyObject *kw)
+ {
+ PyCFunctionObject* f = (PyCFunctionObject*)func;
+ PyCFunction meth = PyCFunction_GET_FUNCTION(func);
+ PyObject *self = PyCFunction_GET_SELF(func);
+ int flags = PyCFunction_GET_FLAGS(func);
+
+ if (flags & METH_KEYWORDS) {
+ return (*(PyCFunctionWithKeywords)meth)(self, arg, kw);
+ }
+ if (kw != NULL && PyDict_Size(kw) != 0) {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s() takes no keyword arguments",
+ f->m_ml->ml_name);
+ return NULL;
+ }
+ if (flags & METH_VARARGS) {
+ return (*meth)(self, arg);
+ }
+ if (!(flags & METH_VARARGS)) {
+ /* the really old style */
+ int size = PyTuple_GET_SIZE(arg);
+ if (size == 1)
+ arg = PyTuple_GET_ITEM(arg, 0);
+ else if (size == 0)
+ arg = NULL;
+ return (*meth)(self, arg);
+ }
+ /* should never get here ??? */
+ PyErr_BadInternalCall();
+ return NULL;
+ }
+
+
PyTypeObject PyCFunction_Type = {
PyObject_HEAD_INIT(&PyType_Type)
***************
*** 169,173 ****
0, /* tp_as_mapping */
(hashfunc)meth_hash, /* tp_hash */
! 0, /* tp_call */
0, /* tp_str */
PyGeneric_GetAttr, /* tp_getattro */
--- 204,208 ----
0, /* tp_as_mapping */
(hashfunc)meth_hash, /* tp_hash */
! meth_call, /* tp_call */
0, /* tp_str */
PyGeneric_GetAttr, /* tp_getattro */
Index: object.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/object.c,v
retrieving revision 2.124.4.6
retrieving revision 2.124.4.7
diff -C2 -r2.124.4.6 -r2.124.4.7
*** object.c 2001/05/04 16:50:22 2.124.4.6
--- object.c 2001/05/05 11:37:29 2.124.4.7
***************
*** 1209,1218 ****
if (x == NULL)
return 0;
- if (x->ob_type->tp_call != NULL ||
- PyFunction_Check(x) ||
- PyMethod_Check(x) ||
- PyCFunction_Check(x) ||
- PyClass_Check(x))
- return 1;
if (PyInstance_Check(x)) {
PyObject *call = PyObject_GetAttrString(x, "__call__");
--- 1209,1212 ----
***************
*** 1225,1230 ****
Py_DECREF(call);
return 1;
}
- return 0;
}
--- 1219,1226 ----
Py_DECREF(call);
return 1;
+ }
+ else {
+ return x->ob_type->tp_call != NULL;
}
}