← Back to index

protocols_merging.py

True Positive
False Positive
False Negative
Optional (detected)
Warning or Info
TP: 5
FP: 0
FN: 1
Optional: 0 / 0
1"""
2Tests merging and extending of protocols.
3"""
4
5# Specification: https://typing.readthedocs.io/en/latest/spec/protocol.html#merging-and-extending-protocols
6
7from abc import abstractmethod
8from typing import Protocol
9from collections.abc import Sized
12class SizedAndClosable1(Sized, Protocol):
13 def close(self) -> None:
14 ...
17class SizedAndClosable2(Protocol):
18 def __len__(self) -> int:
19 ...
21 def close(self) -> None:
22 ...
25class SizedAndClosable3(SizedAndClosable1): # Note: not a protocol
26 def __len__(self) -> int:
27 return 0
29 def close(self) -> None:
30 pass
33class SCConcrete1:
34 def __len__(self) -> int:
35 return 0
37 def close(self) -> None:
38 pass
41class SCConcrete2:
42 def close(self) -> None:
43 pass
46s1: SizedAndClosable1 = SCConcrete1() # OK
47s2: SizedAndClosable2 = SCConcrete1() # OK
48s3: SizedAndClosable1 = SizedAndClosable3() # OK
49s4: SizedAndClosable2 = SizedAndClosable3() # OK
50s5: Sized = SCConcrete1() # OK
52s6: SizedAndClosable1 = SCConcrete2() # E: doesn't implement `__len__`
[invalid-assignment] Object of type `SCConcrete2` is not assignable to `SizedAndClosable1`
53s7: SizedAndClosable2 = SCConcrete2() # E: doesn't implement `__len__`
[invalid-assignment] Object of type `SCConcrete2` is not assignable to `SizedAndClosable2`
54s8: SizedAndClosable3 = SCConcrete2() # E: SizedAndClosable3 is not a protocol
[invalid-assignment] Object of type `SCConcrete2` is not assignable to `SizedAndClosable3`
57def func1(s1: SizedAndClosable1, s2: SizedAndClosable2):
58 # > The two definitions of SizedAndClosable are equivalent.
59 v1: SizedAndClosable2 = s1
60 v2: SizedAndClosable1 = s2
63# > If Protocol is included in the base class list, all the other base classes
64# > must be protocols.
67class BadProto(SizedAndClosable3, Protocol): # E: SizedAndClosable3 is not a protocol
[invalid-protocol] Protocol class `BadProto` cannot inherit from non-protocol class `SizedAndClosable3`
68 ...
71# > Without this base, the class is “downgraded” to a regular ABC that
72# > cannot be used with structural subtyping.
73class SizedAndClosable4(SizedAndClosable1):
74 def __len__(self) -> int:
75 return 0
77 @abstractmethod
78 def close(self) -> None:
79 raise NotImplementedError
82x = SizedAndClosable4() # E: cannot instantiate abstract class
Expected a ty diagnostic for this line
83y: SizedAndClosable4 = SCConcrete1() # E
[invalid-assignment] Object of type `SCConcrete1` is not assignable to `SizedAndClosable4`