Add `OrdinaryCallable` mixin that provides the descriptor protocol implementation of an ordinary callable

Often, when callable classes are implemented, the descriptors are forgotten. Consider some decorator:

class X:
    def __init__(self, f):
        self.f = f
        
    def __call__(self, *args, **kwargs):
        print(self.f(*args, **kwargs))

This works fine when applied to a function:

@X
def g(blah):
    print(blah)

g(1)  # prints 1

But if you apply it to a method, you get

class Z:
    @X
    def f(self, blah):
        print(blah)

z = Z()
z.f(1)  # TypeError: Z.f() missing 1 required positional argument: 'blah'

To make it easier to implement decorators that work on both functions and methods, I suggest adding the mixin functools.OrdinaryCallable:

class OrdinaryCallable(Generic[P, R_co]):
    @abc.abstractmethod
    def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R_co:
        raise NotImplementedError

    @overload
    def __get__(self, instance: None, owner: Any = None) -> OrdinaryCallable[P, R_co]:
        ...
    @overload
    def __get__(self, instance: U, owner: Any = None
                ) -> Callable[..., R_co]:  # No perfect type annotation is possible here yet, but see https://github.com/python/typing/issues/1372
        ...
    def __get__(self, instance: Any, owner: Any = None) -> Callable[..., R_co]:
        if instance is None:
            return self
        return partial(self, instance)

This provides both the (hopefully correct) behavior and the correct type annotation for an ordinary callable function/method.

As far as I know, type checkers don’t use the descriptor protocol yet, but these annotations would come in handy if they were to start using it. Even if they continue to special-case method lookup, then having such a base class in the standard library would allow them to treat classes that incorporate this mixin the same way they treat ordinary callables.

Of significantly lesser benefit as mixins, but of similar utility as type annotation providers might be StaticMethod and ClassMethod base classes (described here Add PartialApplication · Issue #1372 · python/typing · GitHub). But I’m not proposing those yet.

I suspect there are existing third-party libraries that offer this along with much more support for writing decorators (e.g., ways to avoid nesting wrapper function definitions). I tried my hand at it myself once, many years ago, before getting distracted (I kept coming up with more vague ideas, but couldn’t distill them all into clear requirements/specifications; and then the next shiny idea came along).

This isn’t just for writing decorators. It’s for writing any callable that needs to act like a regular function along with the type annotations.

The main problem with third party libraries is that type checkers won’t use the annotations on the descriptor protocol and won’t special case the behaviour of the class. Also, most people don’t want to pull in a third party library for 15 lines of code.