I've been wondering whether it would make sense to have a function in `inspect` 
that returns the signature of a type, rather than the signature of a specific 
callable object.

I'm not attached to any name for such a function, two ideas are 
`inspect.signature_of` or `inspect.signature_of_type`.

## Context: the behavior of `inspect.signature`

The existing `inspect.signature` function specified in PEP 362 [0] returns the 
call signature of a particular object, in other words given
```
class Dog:
    def __init__(self, color: str):
        self.color = color
    def __call__(self, command: str):
        print(command)
```
we will get
```
>>> import inspect
>>> inspect.signature(Dog)
<Signature (color: str)>
>>> inspect.signature(Dog("brown"))
<Signature (command: str)>
```

## Outline of the idea

In some cases it might be nice to be able to access the signature of an 
instance of `Dog` given the type `Dog`, without actually needing to instantiate 
it. 

Moreover, there are some cases where it isn't even possible to get a callable 
object, but it still might be nice to have access to an `inspect.Signature` 
object:
- protocols cannot be instantiated. This is particularly relevant to getting 
Signatures because of callback protocols [1] 
- typing.Callable types describe a signature, but again can't be instantiated

If if we had a function to operate on types, it would treat normal classes as 
if calling `inspect.signature` on the `__call__` method of an instance.

For callable types we'd want to do something similar, although this brings up 
some issues: 
- the existing Signature requires parameter names, but a `typing.Callable` 
doesn't have any.
  - One option would be to invent names `__0`, `__1,` etc. Otherwise we'd have 
to make the name optional.
- it's not obvious how to support PEP 612 ParamSpecs, and even less obvious how 
to support PEP 646 in full generality

I have some code snippets running through how simple cases might work, as well 
as the edge cases I've thought of thus far:
https://gist.github.com/stroxler/4760cbc5e49df2295cd0b524328b1c73

I'm undecided about whether the edge cases are an indication that this idea 
isn't worth considering.
It's worth noting that most of the edge cases involve PEP 612 / 646 generics 
which are pretty rare.

## Why did I start thinking about this?

In discussions of PEP 677 [2], a few folks suggested using `inspect.Signature` 
as inspiration for the runtime API (which we did).

This got me thinking that it might be nice for code that uses runtime types, 
regardless of what we decide about PEP 677, to have an API that makes accessing 
signature information from a type easier.

I don't personally have much need for this, but
- when I chatted with Carl Meyer from the static python team at Meta he thought 
it could be handy
- I could imagine it being useful for tools like ML frameworks, which I've 
worked on in the past, that interpret type annotations to auto-generate logic

--

[0] PEP 362 Function Signatures https://www.python.org/dev/peps/pep-0362/
[1] Callback protocols 
https://mypy.readthedocs.io/en/stable/protocols.html#callback-protocols
[2] PEP 677 Callable Type Syntax  https://www.python.org/dev/peps/pep-0677/
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/47NLKQZYYQL6LKA7BQWGFT4UZJOIAR4M/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to