Open
Description
A subclass of Protocol is also an ABC:
import abc
from typing import Protocol
class P(Protocol):
@abc.abstractmethod
def f(self) -> None: pass
class C(P):
pass
C() # TypeError: Can't instantiate abstract class C with abstract method f
However, mypy doesn't detect a metaclass conflict here:
from typing import Protocol
class Meta(type): pass
# Metaclass conflict at runtime, but no mypy error
class P(Protocol, metaclass=Meta): pass
At runtime this will generate a metaclass conflict:
Traceback (most recent call last):
File "/Users/jukka/src/mypy/t/t5.py", line 6, in <module>
class P(Protocol, metaclass=Meta): pass
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
The actual metaclass is typing._ProtocolMeta
:
>>> type(typing.Protocol)
<class 'typing._ProtocolMeta'>
Mypy should infer typing._ProtocolMeta
as the metaclass of protocol classes. Maybe a custom metaclass should also be rejected, at least if it isn't a subclass of typing._ProtocolMeta
.
More discussion here: python/typeshed#9058