Skip to content

gh-79644: Fix create_autospec signature handling for functools partial and partialmethod#153580

Open
claudiubelu wants to merge 1 commit into
python:mainfrom
claudiubelu:fix-gh79644-partial-signatures
Open

gh-79644: Fix create_autospec signature handling for functools partial and partialmethod#153580
claudiubelu wants to merge 1 commit into
python:mainfrom
claudiubelu:fix-gh79644-partial-signatures

Conversation

@claudiubelu

Copy link
Copy Markdown

Fixes both cases reported in gh-79644 (#79644):

  1. functools.partial: _get_signature_object() fell through to inspecting func.__call__ for anything that wasn't a plain function / method. For a functools.partial, that resolves to the C slot wrapper's own generic (*args, **kwargs) signature rather than the partial's effective, post-partial-application one. inspect.signature() already has first-class support for computing a functools.partial's effective signature directly; skip the func.__call__ detour and let it do so.

  2. functools.partialmethod: _must_skip() special-cases staticmethod / classmethod / plain functions to decide whether self should be dropped from an autospecced method's signature, but had no branch for functools.partialmethod. The raw partialmethod object stored in klass.__dict__ matched none of those cases and fell through to the "not a method" branch, always returning False regardless of is_type. The resolved attribute used to build the child mock's signature (obtained via getattr(), which goes through the descriptor protocol) is a plain function whose signature still includes self when accessed unbound at the class level, so without this fix self's position was checked against the partialmethod's own pre-bound argument instead of being skipped.

…partial and partialmethod

Fixes both cases reported in pythongh-79644:

1. functools.partial: _get_signature_object() fell through to inspecting
   func.__call__ for anything that wasn't a plain function / method. For
   a functools.partial, that resolves to the C slot wrapper's own generic
   "(*args, **kwargs)" signature rather than the partial's effective,
   post-partial-application one. inspect.signature() already has
   first-class support for computing a functools.partial's effective
   signature directly; skip the func.__call__ detour and let it do so.

2. functools.partialmethod: _must_skip() special-cases
   staticmethod / classmethod / plain functions to decide whether `self`
   should be dropped from an autospecced method's signature, but had no
   branch for functools.partialmethod. The raw partialmethod object
   stored in klass.__dict__ matched none of those cases and fell through
   to the "not a method" branch, always returning False regardless of
   `is_type`. The resolved attribute used to build the child mock's
   signature (obtained via getattr(), which goes through the descriptor
   protocol) is a plain function whose signature still includes `self`
   when accessed unbound at the class level, so without this fix self's
   position was checked against the partialmethod's own pre-bound
   argument instead of being skipped.

Signed-off-by: Claudiu Belu <cbelu@cloudbasesolutions.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant