]> granicus.if.org Git - python/commitdiff
bpo-29548: Recommend PyObject_Call APIs over PyEval_Call APIs. (GH-75)
authorINADA Naoki <methane@users.noreply.github.com>
Tue, 14 Mar 2017 09:00:59 +0000 (18:00 +0900)
committerGitHub <noreply@github.com>
Tue, 14 Mar 2017 09:00:59 +0000 (18:00 +0900)
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.

Include/ceval.h
Objects/call.c

index e4be595469fc29f5d32678c27259264c97254d81..8760fe50b70d6ae057b434e6b931818adba4092b 100644 (file)
@@ -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,
index a4af816e30994ee26cd3a8944c10f3680cabfc71..f1b14080ffa2e6eba3f51585fe4d8adcbd68f10d 100644 (file)
@@ -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_start(vargs, format);
-
-    args = Py_VaBuildValue(format, vargs);
-    va_end(vargs);
-
-    if (args == NULL)
-        return NULL;
+    va_list va;
+    PyObject *result;
 
-    res = PyEval_CallObject(callable, args);
-    Py_DECREF(args);
+    va_start(va, format);
+    result = _PyObject_CallFunctionVa(callable, format, va, 0);
+    va_end(va);
 
-    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;
-
-    meth = PyObject_GetAttrString(obj, name);
-    if (meth == NULL)
-        return NULL;
-
-    va_start(vargs, format);
+    va_list va;
+    PyObject *callable, *retval;
 
-    args = Py_VaBuildValue(format, vargs);
-    va_end(vargs);
+    if (obj == NULL || name == NULL) {
+        return null_error();
+    }
 
-    if (args == NULL) {
-        Py_DECREF(meth);
+    callable = PyObject_GetAttrString(obj, name);
+    if (callable == NULL)
         return NULL;
-    }
 
-    res = PyEval_CallObject(meth, args);
-    Py_DECREF(meth);
-    Py_DECREF(args);
+    va_start(va, format);
+    retval = callmethod(callable, format, va, 0);
+    va_end(va);
 
-    return res;
+    Py_DECREF(callable);
+    return retval;
 }