`inspect.getcallargs` does not raise `TypeError` for pos-only passed as keywords
Consider this example:
>>> def a(p, /, a, b=2, *, f): ... ... >>> import inspect >>> inspect.getcallargs(a, p=1, a=2, b=3, f=4) {'p': 1, 'a': 2, 'b': 3, 'f': 4}
Compare it with the runtime:
>>> def a(p, /, a, b=2, *, f): ... ... >>> a(p=1, a=2, b=3, f=4) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: a() got some positional-only arguments passed as keyword arguments: 'p'
And with inspect.signature.bind:
>>> inspect.signature(a).bind(p=1, a=2, b=3, f=4) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/Users/sobolev/Desktop/cpython/Lib/inspect.py", line 3294, in bind return self._bind(args, kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/sobolev/Desktop/cpython/Lib/inspect.py", line 3186, in _bind raise TypeError(msg) from None TypeError: 'p' parameter is positional only, but was passed as a keyword
The issue itself is not easy to fix, because inside getcallargs uses getfullargspec, which does not differentiate pos-only from pos-or-keyword:
| spec = getfullargspec(func) | |
| args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = spec |
So, we cannot know that p is pos-only.
Note that inspect.getcallargs is deprecated in the docs.
So, I propose deprecating getcallargs with a DeprecationWarning in 3.13.