-
Notifications
You must be signed in to change notification settings - Fork 297
Expand file tree
/
Copy pathliterals_interactions.py
More file actions
143 lines (97 loc) · 4.09 KB
/
literals_interactions.py
File metadata and controls
143 lines (97 loc) · 4.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
"""
Tests interactions between Literal types and other typing features.
"""
# Specification: https://typing.readthedocs.io/en/latest/spec/literal.html#interactions-with-other-types-and-features
from enum import Enum
from typing import IO, Any, Final, Generic, Literal, TypeVar, LiteralString, assert_type, overload
def func1(v: tuple[int, str, list[bool]], a: Literal[0], b: Literal[5], c: Literal[-5]):
assert_type(v[a], int)
assert_type(v[2], list[bool])
v[b] # E: index out of range
v[c] # E: index out of range
v[4] # E: index out of range
v[-4] # E: index out of range
_PathType = str | bytes | int
@overload
def open(
path: _PathType,
mode: Literal["r", "w", "a", "x", "r+", "w+", "a+", "x+"],
) -> IO[str]:
...
@overload
def open(
path: _PathType,
mode: Literal["rb", "wb", "ab", "xb", "r+b", "w+b", "a+b", "x+b"],
) -> IO[bytes]:
...
@overload
def open(path: _PathType, mode: str) -> IO[Any]:
...
def open(path: _PathType, mode: Any) -> Any:
raise NotImplementedError
assert_type(open("path", "r"), IO[str])
assert_type(open("path", "wb"), IO[bytes])
assert_type(open("path", "other"), IO[Any])
A = TypeVar("A", bound=int)
B = TypeVar("B", bound=int)
C = TypeVar("C", bound=int)
class Matrix(Generic[A, B]):
def __add__(self, other: "Matrix[A, B]") -> "Matrix[A, B]":
raise NotImplementedError
def __matmul__(self, other: "Matrix[B, C]") -> "Matrix[A, C]":
raise NotImplementedError
def transpose(self) -> "Matrix[B, A]":
raise NotImplementedError
def func2(a: Matrix[Literal[2], Literal[3]], b: Matrix[Literal[3], Literal[7]]):
c = a @ b
assert_type(c, Matrix[Literal[2], Literal[7]])
T = TypeVar("T", Literal["a"], Literal["b"], Literal["c"])
S = TypeVar("S", bound=Literal["foo"])
class Status(Enum):
SUCCESS = 0
INVALID_DATA = 1
FATAL_ERROR = 2
def parse_status1(s: str | Status) -> None:
if s is Status.SUCCESS:
assert_type(s, Literal[Status.SUCCESS])
elif s is Status.INVALID_DATA:
assert_type(s, Literal[Status.INVALID_DATA])
elif s is Status.FATAL_ERROR:
assert_type(s, Literal[Status.FATAL_ERROR])
else:
assert_type(s, str)
# > Type checkers may optionally perform additional analysis for both
# > enum and non-enum Literal types beyond what is described in the section above.
#
# > For example, it may be useful to perform narrowing based on things
# > like containment or equality checks:
def expects_bad_status(status: Literal["MALFORMED", "ABORTED"]):
...
def expects_pending_status(status: Literal["PENDING"]):
...
def parse_status2(status: LiteralString) -> None:
if status == "MALFORMED":
expects_bad_status(status) # E? narrowing the type here is sound, but optional per the spec
elif status == "ABORTED":
expects_bad_status(status) # E? narrowing the type here is sound, but optional per the spec
if status in ("MALFORMED", "ABORTED"):
expects_bad_status(status) # E? narrowing the type here is sound, but optional per the spec
if status == "PENDING":
expects_pending_status(status) # E? narrowing the type here is sound, but optional per the spec
# Narrowing `str` to `Literal` strings is unsound given the possiblity of
# user-defined `str` subclasses that could have custom equality semantics,
# but is explicitly listed by the spec as optional analysis that type checkers
# may perform.
def parse_status3(status: str) -> None:
if status == "MALFORMED":
expects_bad_status(status) # E? narrowing the type here is unsound, but allowed per the spec
elif status == "ABORTED":
expects_bad_status(status) # E? narrowing the type here is unsound, but allowed per the spec
if status in ("MALFORMED", "ABORTED"):
expects_bad_status(status) # E? narrowing the type here is unsound, but allowed per the spec
if status == "PENDING":
expects_pending_status(status) # E? narrowing the type here is unsound, but allowed per the spec
final_val1: Final = 3
assert_type(final_val1, Literal[3])
final_val2: Final = True
assert_type(final_val2, Literal[True])