INADA Naoki added the comment:

Thanks, Lemburg to pointing it out.
Here is detail of the difference.

## PyEval_CallFunction(), PyEval_CallMethod()

They are very similar to PyObject_CallFunction() and PyObject_CallMethod().  
difference are:

* PyEval_Call...() doesn't respect Py_SSIZE_T_CLEAN
* PyObject_Call... has following special case.  PyEval_CallFunction(callable, 
"i", (int)i) will raise TypeError("keyword list must be a tuple") and 
PyObject_CallFunction(callable, "i", (int)i) calls `callable(i)`

    if (nargs == 1 && PyTuple_Check(stack[0])) {
        /* Special cases for backward compatibility:
           - PyObject_CallFunction(func, "O", tuple) calls func(*tuple)
           - PyObject_CallFunction(func, "(OOO)", arg1, arg2, arg3) calls
             func(*(arg1, arg2, arg3)): func(arg1, arg2, arg3) */
        PyObject *args = stack[0];
        result = _PyObject_FastCall(callable,
                                    &PyTuple_GET_ITEM(args, 0),
                                    PyTuple_GET_SIZE(args));
    }

PyEval_CallFunction is not called from Python source tree.
PyEval_CallMethod has only one caller in tree and format string is "(Oi)".  It 
can be replaced with PyObject_CallMethod safely.


## PyEval_CallObject(), PyEval_CallObjectWithKeywords()

PyEval_CallObject() is a just macro calling PyEval_CallObjectWithKeywords() 
(call it COWK later).
PyEval_CallObject() is identical to PyObject_CallObject().  Only difference is 
it's a macro or function.

COWK is similar to PyObject_Call(), but COWK raise TypeError when args is not a 
tuple or kwds is not a dictionary and PyObject_Call() uses assert.

There are only two caller of PyEval_CallObjectWithKeywords() other than 
PyEval_CallObject and PyObject_CallObject.
One is tp_call of weakcallableproxy.  Type of kwargs is checked before calling 
tp_call.
Another is in threading (boot->keyw).  The threading module checks it's a dict.
So replacing them to PyObject_CallObject() is safe.

----

While they are complex API, there are few (or no) callers in Python tree.
It's too hard to maintain.  Actually, I found regression of COWK in Python 3.6.

https://github.com/python/cpython/commit/155ea65e5c88d250a752ee5321860ef11ede4085

It calls _PyObject_FastCallDict() when args is NULL.  If kwargs is not dict, it 
can crash instead of raising TypeError.

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue29548>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to