Skip to content

inspect.Signature.bind_partial() incorrectly succeeds for missing required positional arguments when called with no arguments vs. unpacked empty iterables on Python 3.13.2t #134299

Not planned
@brianfreud

Description

@brianfreud

Bug report

Bug description:

Type: Behavior

Component: inspect

Versions: Python 3.13.2t (Python 3.13.2 experimental free-threading build (main, Mar 4 2025, 00:41:57) [GCC 13.3.0])

Description:

The inspect.Signature.bind_partial() method exhibits inconsistent behavior when binding arguments to a signature that includes required positional arguments.

Specifically, for a function like def func(pos_arg_required, *, kw_only_arg="default"):, the following occurs:

  1. sig.bind_partial() (called with no arguments): Incorrectly succeeds and returns an empty BoundArguments.arguments dictionary. In some observed cases, it raises TypeError: too many positional arguments, which is also incorrect. The expected behavior is a TypeError for the missing pos_arg_required.
  2. sig.bind_partial(*tuple(), **dict()) (called with unpacked empty tuple and dict): Incorrectly succeeds and returns an empty BoundArguments.arguments dictionary. Expected behavior is a TypeError for the missing pos_arg_required.
  3. sig.bind() (called with no arguments): Correctly fails with TypeError: missing a required argument: 'pos_arg_required'.
  4. sig.bind(*tuple(), **dict()) (called with unpacked empty tuple and dict): Correctly fails with TypeError: missing a required argument: 'pos_arg_required'.

This inconsistent behavior of bind_partial() depending on the call style (no arguments vs. unpacked empty iterables) for the same signature and effective lack of arguments is unexpected and problematic for code relying on bind_partial to validate partial argument sets.

Steps to Reproduce:

import inspect

def func_to_test(pos_arg_required, *, kw_only_arg="default_kw_val"):
    pass

sig = inspect.signature(func_to_test)
print(f"Signature: {sig}")

print("\nTesting sig.bind_partial():")
try:
    ba1 = sig.bind_partial()
    print(f"  SUCCEEDED: {ba1.arguments}") # Problem: This succeeds in the reported environment
except Exception as e:
    print(f"  FAILED: {type(e).__name__}: {e}")

print("\nTesting sig.bind_partial(*tuple(), **dict()):")
empty_tuple = tuple()
empty_dict = dict()
try:
    ba2 = sig.bind_partial(*empty_tuple, **empty_dict)
    print(f"  SUCCEEDED: {ba2.arguments}") # Problem: This succeeds in the reported environment
except Exception as e:
    print(f"  FAILED: {type(e).__name__}: {e}")

Expected Result (based on standard Python behavior):

Signature: (pos_arg_required, *, kw_only_arg='default_kw_val')

Testing sig.bind_partial():
  FAILED: TypeError: missing a required argument: 'pos_arg_required'

Testing sig.bind_partial(*tuple(), **dict()):
  FAILED: TypeError: missing a required argument: 'pos_arg_required'

Actual Result (in the user's environment Python 3.13.2t with PYTHON_GIL=0):

Signature: (pos_arg_required, *, kw_only_arg='default_kw_val')

Testing sig.bind_partial():
  SUCCEEDED: {} / Or sometimes TypeError: too many positional arguments

Testing sig.bind_partial(*tuple(), **dict()):
  SUCCEEDED: {}

Impact:
This makes it difficult to reliably use bind_partial to check if a subset of arguments can be bound without providing all required arguments, as its failure mode for missing required positional arguments is inconsistent when called with no arguments vs. unpacked empty iterables. Code that relies on the expected TypeError from bind_partial may behave incorrectly.

CPython versions tested on:

3.13

Operating systems tested on:

Linux

Activity

changed the title [-]inspect.Signature.bind_partial() incorrectly succeeds for missing required positional arguments when called with no arguments vs. unpacked empty iterables on Python 3.13.2t (GIL-disabled build)[/-] [+]inspect.Signature.bind_partial() incorrectly succeeds for missing required positional arguments when called with no arguments vs. unpacked empty iterables on Python 3.13.2t[/+] on May 20, 2025
self-assigned this
on May 20, 2025
serhiy-storchaka

serhiy-storchaka commented on May 31, 2025

@serhiy-storchaka
Member

This works as intended.

https://docs.python.org/3/library/inspect.html#inspect.Signature.bind_partial

Works the same way as Signature.bind(), but allows the omission of some required arguments (mimics functools.partial() behavior.) Returns BoundArguments, or raises a TypeError if the passed arguments do not match the signature.

Use Signature.bind() if you need to disallow the omission of required arguments.

added and removed
pendingThe issue will be closed if no feedback is provided
on Jun 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

invalidstdlibPython modules in the Lib dirtype-bugAn unexpected behavior, bug, or error

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

    inspect.Signature.bind_partial() incorrectly succeeds for missing required positional arguments when called with no arguments vs. unpacked empty iterables on Python 3.13.2t · Issue #134299 · python/cpython

    Follow Lee on X/Twitter - Father, Husband, Serial builder creating AI, crypto, games & web tools. We are friends :) AI Will Come To Life!

    Check out: eBank.nz (Art Generator) | Netwrck.com (AI Tools) | Text-Generator.io (AI API) | BitBank.nz (Crypto AI) | ReadingTime (Kids Reading) | RewordGame | BigMultiplayerChess | WebFiddle | How.nz | Helix AI Assistant