2Tests the handling of the @runtime_checkable decorator for protocols.
5# Specification: https://typing.readthedocs.io/en/latest/spec/protocol.html#runtime-checkable-decorator-and-narrowing-types-by-isinstance
7# > A protocol can be used as a second argument in isinstance() and
8# > issubclass() only if it is explicitly opt-in by @runtime_checkable decorator.
10from typing import Any, Protocol, runtime_checkable
13class Proto1(Protocol):
18class Proto2(Protocol):
23 if isinstance(a, Proto1): # E: not runtime_checkable
[isinstance-against-protocol] Class `Proto1` cannot be used as the second argument to `isinstance`: This call will raise `TypeError` at runtime
26 if isinstance(a, Proto2): # OK
30# > isinstance() can be used with both data and non-data protocols, while
31# > issubclass() can be used only with non-data protocols.
35class DataProtocol(Protocol):
38 def method1(self) -> int:
43class NonDataProtocol(Protocol):
44 def method1(self) -> int:
49 if isinstance(a, DataProtocol): # OK
52 if isinstance(a, NonDataProtocol): # OK
55 if issubclass(a, DataProtocol): # E
[isinstance-against-protocol] `DataProtocol` cannot be used as the second argument to `issubclass` as it is a protocol with non-method members
58 if issubclass(a, NonDataProtocol): # OK
61 if issubclass(a, (NonDataProtocol, DataProtocol)): # E
Expected a ty diagnostic for this line
65# > Type checkers should reject an isinstance() or issubclass() call if there
66# > is an unsafe overlap between the type of the first argument and the protocol.
70class Proto3(Protocol):
71 def method1(self, a: int) -> int:
76 def method1(self, a: str) -> None:
85 if isinstance(Concrete3A(), Proto2): # OK
88 if isinstance(Concrete3A(), Proto3): # E: unsafe overlap
Expected a ty diagnostic for this line
92 Concrete3B(), (Proto3, NonDataProtocol) # E: unsafe overlap
Expected a ty diagnostic for this line
96 if issubclass(Concrete3A, (Proto3, NonDataProtocol)): # E: unsafe overlap
Expected a ty diagnostic for this line