python / cpython

The Python programming language
https://www.python.org
Other
63.17k stars 30.25k forks source link

`inspect.signature(map)` works in Python 3.13, but gives a signature that looks like only one arg is required #120526

Closed AdamWill closed 4 months ago

AdamWill commented 4 months ago

Bug report

Bug description:

>>> list(inspect.signature(map).parameters.values())[0].kind
<_ParameterKind.POSITIONAL_ONLY: 0>
>>> list(inspect.signature(map).parameters.values())[1].kind
<_ParameterKind.VAR_POSITIONAL: 2>

Up to Python 3.12, inspect.signature(map) just doesn't work, it raises ValueError. In 3.13, it works, but the signature you get seems like kind of a lie. The toolz library has this code to work out how many arguments a function requires:

    return sum(1 for p in sigspec.parameters.values()
               if p.default is p.empty
               and p.kind in (p.POSITIONAL_OR_KEYWORD, p.POSITIONAL_ONLY))

where sigspec is the result of inspect.signature(function). That code seems sensible to me. But it gives the wrong answer for map, because the signature returned by inspect.signature(map) says the "kind" of the second arg (iterables) is VAR_POSITIONAL, which the docs say "corresponds to a args parameter in a Python function definition". That does make it seem optional, because of course if you define a function like `myfunc(args), it does not require any arguments. But really, formap`, you have to provide at least one iterable, or you get the error "map() must have at least two arguments." from https://github.com/python/cpython/blob/b2e71ff4f8fa5b7d8117dd8125137aee3d01f015/Python/bltinmodule.c#L1322C12-L1322C53 .

It kinda seems to me like maybe the signature of map should show three args, the first one POSITIONAL_ONLY, the second (iterable) POSITIONAL_OR_KEYWORD, and the third (*iterables) VAR_POSITIONAL? This is how it looks in the docs.

toolz can work around this by special-casing map one way or another, but it seemed worth at least reporting upstream.

CPython versions tested on:

3.12, 3.13

Operating systems tested on:

Linux

Linked PRs

AlexWaygood commented 4 months ago

@serhiy-storchaka, I think you added lots of signatures for builtins in py313?

sobolevn commented 4 months ago

map(function, iterable, /, *iterables) looks more correct for this case.

AdamWill commented 4 months ago

I am sending a PR to fix it, yep.

serhiy-storchaka commented 4 months ago

Indeed. Thank you for correction @AdamWill.