Skip to content

inspect.getcallargs does not raise TypeError for pos-only passed as keywords#107831

@sobolevn

Description

@sobolevn

Consider this example:

>>>defa(p, /, a, b=2, *, f): ... ... >>>importinspect>>>inspect.getcallargs(a, p=1, a=2, b=3, f=4){'p': 1, 'a': 2, 'b': 3, 'f': 4}

Compare it with the runtime:

>>>defa(p, /, a, b=2, *, f): ... ... >>>a(p=1, a=2, b=3, f=4) Traceback (mostrecentcalllast): File"<stdin>", line1, in<module>TypeError: a() gotsomepositional-onlyargumentspassedaskeywordarguments: 'p'

And with inspect.signature.bind:

>>>inspect.signature(a).bind(p=1, a=2, b=3, f=4) Traceback (mostrecentcalllast): File"<stdin>", line1, in<module>File"/Users/sobolev/Desktop/cpython/Lib/inspect.py", line3294, inbindreturnself._bind(args, kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^File"/Users/sobolev/Desktop/cpython/Lib/inspect.py", line3186, in_bindraiseTypeError(msg) fromNoneTypeError: 'p'parameterispositionalonly, butwaspassedasakeyword

The issue itself is not easy to fix, because inside getcallargs uses getfullargspec, which does not differentiate pos-only from pos-or-keyword:

cpython/Lib/inspect.py

Lines 1582 to 1583 in 39ef93e

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or error

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions