2Tests the typing.Final special form.
5from typing import ClassVar, Final, Literal, NamedTuple, assert_type
7# Specification: https://typing.readthedocs.io/en/latest/spec/qualifiers.html#id1
12assert_type(ID2, Literal[1])
14# > If the right hand side is omitted, there must be an explicit type argument to Final.
16BAD1: Final # E: missing assignment
[final-without-value] `Final` symbol `BAD1` is not assigned a value
18BAD2: Final[str, int] = "" # E: only one type argument allowed
[invalid-type-form] Type qualifier `typing.Final` expected exactly 1 argument, got 2
20# > There can be at most one final declaration per module or class for a given
23# > As self.id: Final = 1 (also optionally with a type in square brackets).
24# > This is allowed only in __init__ methods, so that the final instance
25# > attribute is assigned only once when an instance is created.
31 # > In class bodies and stub files you can omit the right hand side and just
32 # > write ID: Final[float]. If the right hand side is omitted, there must be
33 # > an explicit type argument to Final.
34 ID2: Final # E: missing initialization
[final-without-value] `Final` symbol `ID2` is not assigned a value
36 # > A final attribute declared in a class body without an initializer must
37 # > be initialized in the __init__ method (except in stub files):
38 ID3: Final[int] # E: missing initialization
[final-without-value] `Final` symbol `ID3` is not assigned a value
40 ID4: Final[int] # OK because initialized in __init__
48 def __init__(self, cond: bool) -> None:
50 self.id2: Final[int] = 1
54 self.ID5 = 0 # E: Already initialized
[invalid-assignment] Cannot assign to final attribute `ID5` in `__init__` because it already has a value at class level
61 def method1(self) -> None:
62 self.id3: Final = 1 # E: not allowed outside of __init__ method.
Expected a ty diagnostic for this line
63 self.id4: Final[int] = 1 # E: not allowed outside of __init__ method.
Expected a ty diagnostic for this line
65 self.ID7 = 0 # E: cannot modify Final value
[invalid-assignment] Cannot assign to final attribute `ID7` on type `Self@method1`
67 self.ID7 += 1 # E: cannot modify Final value
Expected a ty diagnostic for this line
71RATE = 300 # E: Cannot redefine Final value
[invalid-assignment] Reassignment of `Final` symbol `RATE` is not allowed: Symbol later reassigned here
73# > There can’t be separate class-level and instance-level constants
74# > with the same name.
81ClassB.DEFAULT_ID = 0 # E: Cannot redefined value
[invalid-assignment] Cannot assign to final attribute `DEFAULT_ID` on type `<class 'ClassB'>`
84# > A type checker should prevent final attributes from being overridden in a subclass:
88 BORDER_WIDTH: Final = 2.5
93class ClassCChild(ClassC):
94 BORDER_WIDTH = 2.5 # E: Cannot override Final value
[override-of-final-variable] Cannot override final variable `BORDER_WIDTH` from superclass `ClassC`
99# > Type checkers should infer a final attribute that is initialized in a class
100# > body as being a class variable. Variables should not be annotated with both
101# > ClassVar and Final. (Except in a dataclass; see dataclasses_final.py.)
107 VALUE2: ClassVar[Final] = 1 # E: Final cannot be used with ClassVar
Expected a ty diagnostic for this line
108 VALUE3: Final[ClassVar] = 1 # E: Final cannot be used with ClassVar
Expected a ty diagnostic for this line
114# > Final may only be used as the outermost type in assignments or variable
115# > annotations. Using it in any other position is an error. In particular,
116# > Final can’t be used in annotations for function arguments.
118x: list[Final[int]] = [] # E
[invalid-type-form] Type qualifier `typing.Final` is not allowed in type expressions (only in annotation expressions)
121def func1(x: Final[list[int]]) -> None: # E
[invalid-type-form] `Final` is not allowed in function parameter annotations
125# > Type checkers should treat uses of a final name that was initialized with
126# > a literal as if it was replaced by the literal. For example, the following
127# > should be allowed:
131N = NamedTuple("N", [(X, int), (Y, int)])
[missing-argument] No arguments provided for required parameters `x`, `y`
[unknown-argument] Argument `a` does not match any known parameter
[invalid-argument-type] Argument is incorrect: Expected `int`, found `Literal[""]`
[invalid-argument-type] Argument is incorrect: Expected `int`, found `Literal[""]`
141 ID1 = 2 # E: cannot modify Final value
[invalid-assignment] Reassignment of `Final` symbol `ID1` is not allowed: Reassignment of `Final` symbol
145 x += 1 # E: cannot modify Final value
[invalid-assignment] Reassignment of `Final` symbol `x` is not allowed: Symbol later reassigned here
147 a = (x := 4) # E: cannot modify Final value
[invalid-assignment] Reassignment of `Final` symbol `x` is not allowed: Symbol later reassigned here
149 for x in [1, 2, 3]: # E: cannot modify Final value
[invalid-assignment] Reassignment of `Final` symbol `x` is not allowed: Symbol later reassigned here
152 with open("FileName") as x: # E: cannot modify Final value
[invalid-assignment] Reassignment of `Final` symbol `x` is not allowed: Symbol later reassigned here
155 (a, x) = (1, 2) # E: cannot modify Final value
[invalid-assignment] Reassignment of `Final` symbol `x` is not allowed: Symbol later reassigned here
158# > If a module declares a ``Final`` variable and another module imports that
159# > variable in an import statement by name or wildcard, the imported symbol
160# > inherits the ``Final`` type qualifier. Any attempt to assign a different value
161# > to this symbol should be flagged as an error by a type checker.
164from _qualifiers_final_annotation_1 import TEN
166TEN = 9 # E: Cannot redefine Final value
[invalid-assignment] Reassignment of `Final` symbol `TEN` is not allowed: Reassignment of `Final` symbol
168from _qualifiers_final_annotation_2 import *
170PI = 3.14159 # E: Cannot redefine Final value
[invalid-assignment] Reassignment of `Final` symbol `PI` is not allowed: Reassignment of `Final` symbol