Skip to content

Signature.bind allows certain positional-only parameters as keywords #130164

Description

@dfremont

Bug report

Bug description:

Prior to 3.13, the following code correctly raised a TypeError (I've tested 3.8-3.12, but see the last paragraph below):

def fun(x, /, **kwargs):
    pass

import inspect
sig = inspect.signature(fun)
sig.bind(x=1)

In 3.13, the binding succeeds even though the positional-only parameter was passed as a keyword argument (of course, fun(x=1) fails with a TypeError).

As far as I can tell this bug hasn't been previously reported, although issue #107831 reports inspect.getcallargs as having the same problem (prior to 3.13, unlike this bug).

I'm guessing the bug was introduced by #103404. If I try a version of 3.12 containing that patch (rather than the older versions I had installed previously), e.g. 3.12.9, it also exhibits the bug. It's possible that fixing the case where the positional-only parameter has a default value accidentally broke this case. Mentioning @jacobtylerwalls as the author of that PR in case they would like to take a look. Thanks!

CPython versions tested on:

3.13

Operating systems tested on:

macOS

Linked PRs

Activity

  1. added
    stdlibStandard Library Python modules in the Lib/ directory
    on Feb 15, 2025
  2. jacobtylerwalls commented on Feb 16, 2025

    @jacobtylerwalls
    Contributor

    Thanks, bisected to #103404 and testing a fix. Affects 3.12.4+

  3. picnixz commented on Feb 16, 2025

    @picnixz
    Member

    Just to be clear, the issue is not that

    In 3.13, the binding succeeds even though the positional-only parameter was passed as a keyword argument

    Indeed, consider

    def fun(x, /, **kwargs): pass
    
    fun(1, x=2)

    So

    import inspect
    sig = inspect.signature(fun)
    sig.bind(x=1)

    means that you're binding it with a keyword argument x but it doesn't affect the positional-only parameter x itself. However, bind actually expects to specify all required arguments, in which case here the positional x is missing. So it's not because the positional-only parameter was passed as a keyword, it's more that we're actually thinking it was correctly specified.

  4. added
    3.13only security fixes
    3.14bugs and security fixes
    type-bugAn unexpected behavior, bug, or error
    stdlibStandard Library Python modules in the Lib/ directory
    and removed
    type-bugAn unexpected behavior, bug, or error
    stdlibStandard Library Python modules in the Lib/ directory
    on Feb 16, 2025
  5. picnixz commented on Feb 16, 2025

    @picnixz
    Member

    A fix for that could be to first check if we have a **kwargs in the signature. If we do, we need to first check if another argument should be bound before we fill the kwargs mapping. If a positional-only cannot be filled (for instance, x should first be checked as a non-keyword argument, if it's not possible to bind it, as in this case, we treat it as a kwarg), we store it as a keyword argument. Once we processed everything, we need to check if a positional-only is still missing because it wasn't treated in the first pass.

    EDIT: ok my paragraph is unclear but TL;DR we probably need a second pass to check that the arguments were properly bound (namely, a positional-only argument should only be bound from the *args of bind and not from anything **kwargs)

  6. added a commit that references this issue on Feb 16, 2025
  7. added a commit that references this issue on Feb 18, 2025
  8. added a commit that references this issue on Feb 18, 2025
  9. serhiy-storchaka commented on Feb 18, 2025

    @serhiy-storchaka
    Member

    Thank you for your report @dfremont and thank you for your quick fix @jacobtylerwalls.

  10. added a commit that references this issue on Apr 8, 2025
  11. added a commit that references this issue on Apr 8, 2025
  12. added a commit that references this issue on Apr 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.12only security fixes3.13only security fixes3.14bugs and security fixesstdlibStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions