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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
brianfreud opened this issue May 20, 2025 · 1 comment
Assignees
Labels
invalid stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@brianfreud
Copy link

brianfreud commented May 20, 2025

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

@brianfreud brianfreud added the type-bug An unexpected behavior, bug, or error label May 20, 2025
@picnixz picnixz added the stdlib Python modules in the Lib dir label May 20, 2025
@picnixz picnixz 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 May 20, 2025
@sobolevn sobolevn self-assigned this May 20, 2025
@serhiy-storchaka
Copy link
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.

@serhiy-storchaka serhiy-storchaka added the pending The issue will be closed if no feedback is provided label May 31, 2025
@serhiy-storchaka serhiy-storchaka closed this as not planned Won't fix, can't repro, duplicate, stale Jun 10, 2025
@serhiy-storchaka serhiy-storchaka added invalid and removed pending The issue will be closed if no feedback is provided labels Jun 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
invalid stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

4 participants