2Tests the handling of forward references in type annotations.
5# > When a type hint contains names that have not been defined yet, that
6# > definition may be expressed as a string literal, to be resolved later.
10from typing import assert_type
14 p1: "ClassA", p2: "list[ClassA]", p3: list["ClassA"], p4: list["int | ClassA"]
16 assert_type(p1, ClassA)
17 assert_type(p2, list[ClassA])
18 assert_type(p3, list[ClassA])
19 assert_type(p4, list[ClassA | int])
22bad1: ClassA # E?: Runtime error prior to 3.14: requires quotes
[unresolved-reference] Name `ClassA` used when not defined
23bad2: list[ClassA] # E?: Runtime error prior to 3.14: requires quotes
[unresolved-reference] Name `ClassA` used when not defined
24bad3: "ClassA" | int # E: Runtime error
Expected a ty diagnostic for this line
25bad4: int | "ClassA" # E: Runtime error
Expected a ty diagnostic for this line
32# > The string literal should contain a valid Python expression
33# > should be a valid code object).
38# The following should all generate errors because they are not legal type
39# expressions, despite being enclosed in quotes.
40def invalid_annotations(
41 p1: "eval(''.join(map(chr, [105, 110, 116])))", # E
[invalid-type-form] Function calls are not allowed in type expressions
[invalid-type-form] List literals are not allowed in this context in a type expression: Did you mean `tuple[int, str]`?
[invalid-type-form] Tuple literals are not allowed in this context in a type expression: Did you mean `tuple[int, str]`?
44 p4: "[int for i in range(1)]", # E
[invalid-type-form] List comprehensions are not allowed in type expressions
[invalid-type-form] Dict literals are not allowed in type expressions
46 p6: "(lambda : int)()", # E
[invalid-type-form] Function calls are not allowed in type expressions
[invalid-type-form] Invalid subscript of object of type `list[Unknown | <class 'int'>]` in type expression
[invalid-type-form] Int literals are not allowed in this context in a type expression
48 p8: "int if 1 < 3 else str", # E
[invalid-type-form] `if` expressions are not allowed in type expressions
[invalid-type-form] Variable of type `Literal[1]` is not allowed in a type expression
[invalid-type-form] Boolean literals are not allowed in this context in a type expression
[invalid-type-form] Int literals are not allowed in this context in a type expression
[invalid-type-form] Unary operations are not allowed in type expressions
53 p13: "int or str", # E
[invalid-type-form] Boolean operations are not allowed in type expressions
[fstring-type-annotation] Type expressions cannot use f-strings
[invalid-type-form] Module `types` is not valid in a type expression
60# > It should evaluate without errors once the module has been fully loaded.
61# > The local and global namespace in which it is evaluated should be the same
62# > namespaces in which default arguments to the same function would be evaluated.
66 def method1(self) -> ClassB: # E?: Runtime error prior to 3.14
[unresolved-reference] Name `ClassB` used when not defined
69 def method2(self) -> "ClassB": # OK
80 ClassF: "ClassF" # E: circular reference
[unresolved-reference] Name `ClassF` used when not defined
Unexpected error
[invalid-type-form] Variable of type `Literal[""]` is not allowed in a type expression
84 def int(self) -> None: # OK
Unexpected error
[invalid-type-form] Function `int` is not valid in a type expression
89 y: int = 0 # E: Refers to local int, which isn't a legal type expression
[invalid-type-form] Function `int` is not valid in a type expression
91 def __init__(self) -> None:
92 self.ClassC = ClassC()
95assert_type(ClassD.str, str)
Unexpected error
[type-assertion-failure] Type `str` does not match asserted type `Unknown`
96assert_type(ClassD.x, int)
Unexpected error
[type-assertion-failure] Type `int` does not match asserted type `Unknown`
99# > If a triple quote is used, the string should be parsed as though it is implicitly
100# > surrounded by parentheses. This allows newline characters to be
101# > used within the string literal.