Skip to content

Infer correct metaclass for protocols #13979

Description

@JukkaL

A subclass of Protocol is also an ABC:

importabcfromtypingimportProtocolclassP(Protocol):
@abc.abstractmethoddeff(self) ->None: passclassC(P):
passC() # TypeError: Can't instantiate abstract class C with abstract method f

However, mypy doesn't detect a metaclass conflict here:

fromtypingimportProtocolclassMeta(type): pass# Metaclass conflict at runtime, but no mypy errorclassP(Protocol, metaclass=Meta): pass

At runtime this will generate a metaclass conflict:

Traceback (mostrecentcalllast):
File"/Users/jukka/src/mypy/t/t5.py", line6, in<module>classP(Protocol, metaclass=Meta): passTypeError: metaclassconflict: themetaclassofaderivedclassmustbea (non-strict) subclassofthemetaclassesofallitsbases

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions