New submission from STINNER Victor <vstin...@redhat.com>:
_PyMethodDescr_FastCallKeywords() is an optimization in ceval.c to call methods. Problem: it introduces a wrong bug. >>> import io >>> help(io.FileIO.write) Help on method_descriptor: write(self, b, /) Write buffer b to file, return number of bytes written. >>> f=io.FileIO("/dev/null", "wb") >>> io.FileIO.write(f, b"data") # ok 4 >>> io.FileIO.write(self=f, b=b"data") # ??? Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: descriptor 'write' of '_io.FileIO' object needs an argument io.FileIO.write is a "method_descriptor" builtin object. It's called from ceval.c call_function() using _PyMethodDescr_FastCallKeywords() which starts with: /* Make sure that the first argument is acceptable as 'self' */ if (nargs < 1) { PyErr_Format(PyExc_TypeError, "descriptor '%V' of '%.100s' " "object needs an argument", descr_name((PyDescrObject *)descr), "?", PyDescr_TYPE(descr)->tp_name); return NULL; } self = args[0]; ... The bug is not a regression caused by the optimization. It exists in Python 3.6 which doesn't have the optimization: $ python3.6 Python 3.6.8+ (heads/3.6:b241af861b, Mar 11 2019, 08:55:59) >>> import io >>> f=io.FileIO("/dev/null", "wb") >>> io.FileIO.write(f, b"data") # ok 4 >>> io.FileIO.write(self=f, b=b"data") # ??? Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: descriptor 'write' of '_io.FileIO' object needs an argument Extract of Python 3.6 methoddescr_call(): /* Make sure that the first argument is acceptable as 'self' */ assert(PyTuple_Check(args)); argc = PyTuple_GET_SIZE(args); if (argc < 1) { PyErr_Format(PyExc_TypeError, "descriptor '%V' of '%.100s' " "object needs an argument", descr_name((PyDescrObject *)descr), "?", PyDescr_TYPE(descr)->tp_name); return NULL; } self = PyTuple_GET_ITEM(args, 0); Python 2.7 raises the same exception, but the docstring is different: $ python2 Python 2.7.15 (default, Oct 15 2018, 15:26:09) >>> import io >>> f=io.FileIO("/dev/null", "wb") >>> io.FileIO.write(f, b"data") 4L >>> io.FileIO.write(self=f, b=b"data") TypeError: descriptor 'write' of '_io.FileIO' object needs an argument >>> help(io.FileIO.write) write(...) write(b) -> int. Write array of bytes b, return number written. -- At this point, it's unclear to me if it's a bug... of a feature :-) It seems like self is a positional-only argument, but the error message isn't helpful. ---------- messages: 338886 nosy: pablogsal, vstinner priority: normal severity: normal status: open title: method_descriptor surprising error message when self is passed a keyword argument versions: Python 3.7, Python 3.8 _______________________________________ Python tracker <rep...@bugs.python.org> <https://bugs.python.org/issue36437> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com