← Back to index

protocols_explicit.py

True Positive
False Positive
False Negative
Optional (detected)
Warning or Info
TP: 1
FP: 0
FN: 5
Optional: 0 / 0
1"""
2Tests the handling of explicit protocol classes.
3"""
4
5# Specification: https://typing.readthedocs.io/en/latest/spec/protocol.html#explicitly-declaring-implementation
6
7from abc import ABC, abstractmethod
8from typing import ClassVar, Protocol
9
11class PColor(Protocol):
12 @abstractmethod
13 def draw(self) -> str:
14 ...
16 def complex_method(self) -> int:
17 return 1
20class NiceColor(PColor):
21 def draw(self) -> str:
22 return "deep blue"
25class BadColor(PColor):
26 def draw(self) -> str:
27 return super().draw() # E: no default implementation
Expected a ty diagnostic for this line
30class ImplicitColor: # Note no 'PColor' base here
31 def draw(self) -> str:
32 return "probably gray"
34 def complex_method(self) -> int:
35 return 0
38v1: PColor = NiceColor() # OK
39v2: PColor = ImplicitColor() # OK
42class RGB(Protocol):
43 rgb: tuple[int, int, int]
44 other: int
46 @abstractmethod
47 def intensity(self) -> int:
48 return 1
50 def transparency(self) -> int:
51 ...
54class Point(RGB):
55 def __init__(self, red: int, green: int, blue: str) -> None:
56 self.rgb = red, green, blue # E: 'blue' must be 'int'
[invalid-assignment] Object of type `tuple[int, int, str]` is not assignable to attribute `rgb` of type `tuple[int, int, int]`
57 self.other = 0
60p = Point(0, 0, "") # E: Cannot instantiate abstract class
Expected a ty diagnostic for this line
63class Proto1(Protocol):
64 cm1: ClassVar[int]
65 cm2: ClassVar[int] = 0
67 im1: int
68 im2: int = 2
69 im3: int
71 def __init__(self):
72 self.im3 = 3
75class Proto2(Protocol):
76 cm10: int
79class Proto3(Proto2, Protocol):
80 cm11: int
83class Concrete1(Proto1):
84 def __init__(self):
85 self.im1 = 1
86 self.im3 = 3
89c1 = Concrete1() # E: cannot instantiate abstract class
Expected a ty diagnostic for this line
92class Concrete2(Proto1):
93 cm1 = 3
94 im1 = 0
97c2 = Concrete2()
100class Concrete3(Proto1, Proto3):
101 cm1 = 3
103 def __init__(self):
104 self.im1 = 0
105 self.cm10 = 10
106 self.cm11 = 11
109c3 = Concrete3()
112class Concrete4(Proto1, Proto3):
113 cm1 = 3
114 cm10 = 3
116 def __init__(self):
117 self.im1 = 3
118 self.im10 = 10
119 self.cm11 = 3
122c4 = Concrete4()
125class Proto5(Protocol):
126 def method1(self) -> int:
127 ...
130class Concrete5(Proto5):
131 pass
134c5 = Concrete5() # E: cannot instantiate abstract class
Expected a ty diagnostic for this line
137class Proto6(Protocol):
138 x: int
141class Mixin:
142 x = 3
145class Concrete6(Mixin, Proto6):
146 pass
149class Proto7(Protocol):
150 @abstractmethod
151 def method1(self):
152 ...
155class Mixin7(Proto7, ABC):
156 def method1(self) -> None:
157 pass
160class Concrete7A(Proto7):
161 pass
164c7a = Concrete7A() # E: cannot instantiate abstract class
Expected a ty diagnostic for this line
167class Concrete7B(Mixin7, Proto7):
168 pass
171c7b = Concrete7B()