Skip to content
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

Fix inspect.signature() of operator.{attrgetter,itemgetter,methodcaller} instances #118285

Open
dgilland opened this issue Apr 25, 2024 · 2 comments
Labels
stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@dgilland
Copy link

dgilland commented Apr 25, 2024

Bug report

Bug description:

On Python 3.12.3 and 3.11.9, it looks like the inspect.Signature object for operator's attrgetter, itemgetter, and methodcaller classes doesn't match their __call__ method signature:

>>> import inspect
>>> import operator
>>> inspect.signature(operator.attrgetter("spam"))
<Signature (*args, **kwargs)>
>>> inspect.signature(operator.itemgetter("spam"))
<Signature (*args, **kwargs)>
>>> inspect.signature(operator.methodcaller("spam"))
<Signature (*args, **kwargs)>

but their __call__ methods only accept a single argument:

# attrgetter / itemgetter
    def __call__(self, obj):
        return self._call(obj)

# methodcaller
    def __call__(self, obj):
        return getattr(obj, self._name)(*self._args, **self._kwargs)

CPython versions tested on:

3.11, 3.12

Operating systems tested on:

macOS

Linked PRs

@dgilland dgilland added the type-bug An unexpected behavior, bug, or error label Apr 25, 2024
@terryjreedy terryjreedy changed the title inspect signature of operator.{attrgetter,itemgetter,methodcaller} doesn't match __call__ definition Fix inspect.signature() of operator.{attrgetter,itemgetter,methodcaller} instances Apr 25, 2024
@terryjreedy terryjreedy added interpreter-core (Objects, Python, Grammar, and Parser dirs) stdlib Python modules in the Lib dir labels Apr 26, 2024
@terryjreedy
Copy link
Member

The signatures of the getter/caller classes are the signature of their .__init__ methods, and inspect.signature returns these properly. The signature of callable instances should, it seems, match that of the .__call__ methods, but, as you tested, it does not. However, while the operator callables (functions and these 3 classes) are all initially defined in python, they are all replaced with C implementations, when possible, with try: from _operator import *. After this, itemgetter.__call__, for instance, is a 'wrapper_descriptor' and itemgetter(s).__call__ is a 'method_wrapper'. Perhaps the C code for the call methods was never revised to use argument-clinic.

serhiy-storchaka added a commit to serhiy-storchaka/cpython that referenced this issue Apr 26, 2024
…thodcaller} instances

* Allow to specify the signature of custom callable instances of extension
  type by the __text_signature__ attribute.
* Specify signatures of operator.attrgetter, operator.itemgetter, and
  operator.methodcaller instances.
@serhiy-storchaka serhiy-storchaka removed the interpreter-core (Objects, Python, Grammar, and Parser dirs) label Apr 26, 2024
serhiy-storchaka added a commit that referenced this issue Apr 29, 2024
…ller} instances (GH-118316)

* Allow to specify the signature of custom callable instances of extension
  type by the __text_signature__ attribute.
* Specify signatures of operator.attrgetter, operator.itemgetter, and
  operator.methodcaller instances.
@serhiy-storchaka
Copy link
Member

Actually, the operator module was initially implemented in C. The Python implementation was added later, partially as a fallback for alternative Python implementations (although Jython, PyPy, and other already had their own implementations), partially as experiment (which failed in my opinion).

Now inspect.signature() returns <Signature (*args, **kwargs)> for custom callable objects implemented in C instead of raising a ValueError. It was perhaps not intentional change, but it may be too later to change this again, some code can already rely on this. At least not in 3.11 (which is in the security fixes mode) or 3.12.

In any case, I added a simple way to specify signature for callables implemented in C and implemented it for the operator callables. Whether make inspect.signature() raising a ValueError by default is an open question.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

3 participants