← Back to index
protocols_recursive.py
True Positive
False Positive
False Negative
Optional (detected)
Warning or Info
TP: 0
FP: 1
FN: 0
Optional: 0 / 0
1
"""
2
Tests
the
handling
of
recursive
protocols
.
3
"""
4
5
# Specification: https://typing.readthedocs.io/en/latest/spec/protocol.html#recursive-protocols
6
7
8
from
typing
import
Generic
,
Iterable
,
Never
,
Protocol
,
Self
,
TypeVar
,
assert_type
9
10
T
=
TypeVar
(
"T"
)
11
T_co
=
TypeVar
(
"T_co"
,
covariant
=
True
)
12
T_contra
=
TypeVar
(
"T_contra"
,
contravariant
=
True
)
13
14
15
class
Traversable
(
Protocol
):
16
def
leaves
(
self
)
->
Iterable
[
"Traversable"
]:
17
...
18
19
20
class
SimpleTree
:
21
def
leaves
(
self
)
->
list
[
"SimpleTree"
]:
22
return
[]
23
24
25
root
:
Traversable
=
SimpleTree
()
# OK
26
27
28
class
Tree
(
Generic
[
T
]):
29
def
leaves
(
self
)
->
list
[
"Tree[T]"
]:
30
return
[]
31
32
33
def
walk
(
graph
:
Traversable
)
->
None
:
34
pass
35
36
37
tree
:
Tree
[
float
]
=
Tree
()
38
walk
(
tree
)
# OK
39
40
41
class
ProtoA
(
Protocol
[
T_co
,
T_contra
]):
42
def
method1
(
self
)
->
"ProtoA[T_co, T_contra]"
:
43
...
44
45
@classmethod
46
def
method2
(
cls
,
value
:
T_contra
)
->
None
:
47
...
48
49
50
class
ProtoB
(
Protocol
[
T_co
,
T_contra
]):
51
def
method3
(
self
)
->
ProtoA
[
T_co
,
T_contra
]:
52
...
53
54
55
class
ImplA
:
56
def
method1
(
self
)
->
Self
:
57
return
self
58
59
@classmethod
60
def
method2
(
cls
,
value
:
int
)
->
None
:
61
pass
62
63
64
class
ImplB
:
65
def
method3
(
self
)
->
ImplA
:
66
return
ImplA
()
67
68
def
method1
(
self
)
->
Self
:
69
return
self
70
71
@classmethod
72
def
method2
(
cls
:
type
[
ProtoB
[
object
,
T
]],
value
:
list
[
T
])
->
None
:
73
pass
74
75
76
def
func1
(
x
:
ProtoA
[
Never
,
T
])
->
T
:
77
raise
NotImplementedError
78
79
80
v1
=
func1
(
ImplB
())
81
assert_type
(
v1
,
list
[
int
])
Unexpected error [type-assertion-failure] Type `list[int]` does not match asserted type `Unknown`