A similar proposal, just FYI https://github.com/python/mypy/issues/7894


On Fri, May 21, 2021 at 11:41 PM James Perretta <perretta.james@gmail.com> wrote:
Hi everyone,

One of the rejected ideas in PEP 544 is being able to define a Protocol that inherits from a normal class (https://www.python.org/dev/peps/pep-0544/#protocols-subclassing-normal-classes). I've been thinking about a potential new feature that could accomplish more or less the same thing without running into the transitivity issue described in PEP 544. I'm sure there are some considerations I've missed, but I'd love to hear what you all think.

In short, we'd introduce a +`.from()` method to typing.Protocol that takes in a class and returns a new Protocol with the same interface as that class.
```
from typing import Protocol

class SomeClass:
    def some_method(self) -> None:
        pass

class SomeClassProtocol(Protocol.from(SomeClass)):
    def another_method(self) -> None:
        ...
```

Static type checkers would in this case determine that SomeClassProtocol is a Protocol with two methods (some_method and another_method). If SomeClass and SomeClassProtocol both define a method with the same name, the one defined in SomeClassProtocol would take precedence.

The next thing to think about would be:
- Should the result of Protocol.from(SomeClass) only include SomeClass's methods, or should it include methods and attributes?
  - By default, I think it should probably include methods and attributes. There could possibly be an optional argument to Protocol.from() that toggles whether attributes are included, something like: `Protocol.fom(SomeClass, include_attrs=False)`
- Should it include only "public" members, or should it also include `_` and `__` prefixed names?
  - My inclination would be that it should only include public members.

Some other things to consider that I'm still thinking about:
- What would SomeClassProtocol look like at runtime? I suppose Protocol.from(SomeClass) could introspect SomeClass at runtime and essentially build a protocol class that shares has SomeClass's interface?
- Would this play nicely with generics? (I think/hope so?)

One general use case (there are certainly others that I'm not thinking of at the moment) for this is when annotating "self" for a mixin class (https://mypy.readthedocs.io/en/stable/more_types.html#mixin-classes). It's at best cumbersome to have to write a protocol that matches an existing class and keep them in sync, and it's even more problematic if the protocol needs to match a class from another library.

If this idea seems useful enough to move forward, I'd be happy to help write a PEP for it and work on a mypy implementation (this would be my first time writing a PEP or contributing to mypy). Looking forward to hearing your thoughts!

Thanks,
James
_______________________________________________
Typing-sig mailing list -- typing-sig@python.org
To unsubscribe send an email to typing-sig-leave@python.org
https://mail.python.org/mailman3/lists/typing-sig.python.org/
Member address: epsilonmichael@gmail.com