bpo-29548: Recommend PyObject_Call APIs over PyEval_Call APIs. (GH-75)
PyEval_Call* APIs are not documented and they doesn't respect PY_SSIZE_T_CLEAN. So add comment block which recommends PyObject_Call* APIs to ceval.h. This commit also changes PyEval_CallMethod and PyEval_CallFunction implementation same to PyObject_CallMethod and PyObject_CallFunction to reduce future maintenance cost. Optimization to avoid temporary tuple are copied too. PyEval_CallFunction(callable, "i", (int)i) now calls callable(i) instead of raising TypeError. But accepting this edge case is backward compatible.
This commit is contained in:
parent
7e2a54cdd9
commit
aa289a59ff
|
@ -7,6 +7,12 @@ extern "C" {
|
|||
|
||||
/* Interface to random parts in ceval.c */
|
||||
|
||||
/* PyEval_CallObjectWithKeywords(), PyEval_CallObject(), PyEval_CallFunction
|
||||
* and PyEval_CallMethod are kept for backward compatibility: PyObject_Call(),
|
||||
* PyObject_CallFunction() and PyObject_CallMethod() are recommended to call
|
||||
* a callable object.
|
||||
*/
|
||||
|
||||
PyAPI_FUNC(PyObject *) PyEval_CallObjectWithKeywords(
|
||||
PyObject *callable,
|
||||
PyObject *args,
|
||||
|
|
|
@ -940,25 +940,20 @@ PyObject_CallFunction(PyObject *callable, const char *format, ...)
|
|||
}
|
||||
|
||||
|
||||
/* PyEval_CallFunction is exact copy of PyObject_CallFunction.
|
||||
* This function is kept for backward compatibility.
|
||||
*/
|
||||
PyObject *
|
||||
PyEval_CallFunction(PyObject *callable, const char *format, ...)
|
||||
{
|
||||
va_list vargs;
|
||||
PyObject *args;
|
||||
PyObject *res;
|
||||
va_list va;
|
||||
PyObject *result;
|
||||
|
||||
va_start(vargs, format);
|
||||
va_start(va, format);
|
||||
result = _PyObject_CallFunctionVa(callable, format, va, 0);
|
||||
va_end(va);
|
||||
|
||||
args = Py_VaBuildValue(format, vargs);
|
||||
va_end(vargs);
|
||||
|
||||
if (args == NULL)
|
||||
return NULL;
|
||||
|
||||
res = PyEval_CallObject(callable, args);
|
||||
Py_DECREF(args);
|
||||
|
||||
return res;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1015,33 +1010,29 @@ PyObject_CallMethod(PyObject *obj, const char *name, const char *format, ...)
|
|||
}
|
||||
|
||||
|
||||
/* PyEval_CallMethod is exact copy of PyObject_CallMethod.
|
||||
* This function is kept for backward compatibility.
|
||||
*/
|
||||
PyObject *
|
||||
PyEval_CallMethod(PyObject *obj, const char *name, const char *format, ...)
|
||||
{
|
||||
va_list vargs;
|
||||
PyObject *meth;
|
||||
PyObject *args;
|
||||
PyObject *res;
|
||||
va_list va;
|
||||
PyObject *callable, *retval;
|
||||
|
||||
meth = PyObject_GetAttrString(obj, name);
|
||||
if (meth == NULL)
|
||||
return NULL;
|
||||
|
||||
va_start(vargs, format);
|
||||
|
||||
args = Py_VaBuildValue(format, vargs);
|
||||
va_end(vargs);
|
||||
|
||||
if (args == NULL) {
|
||||
Py_DECREF(meth);
|
||||
return NULL;
|
||||
if (obj == NULL || name == NULL) {
|
||||
return null_error();
|
||||
}
|
||||
|
||||
res = PyEval_CallObject(meth, args);
|
||||
Py_DECREF(meth);
|
||||
Py_DECREF(args);
|
||||
callable = PyObject_GetAttrString(obj, name);
|
||||
if (callable == NULL)
|
||||
return NULL;
|
||||
|
||||
return res;
|
||||
va_start(va, format);
|
||||
retval = callmethod(callable, format, va, 0);
|
||||
va_end(va);
|
||||
|
||||
Py_DECREF(callable);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue