2Tests the typing.ClassVar special form.
5# Specification: https://typing.readthedocs.io/en/latest/spec/class-compat.html#classvar
22from typing import ClassVar as CV
29Ts = TypeVarTuple("Ts")
31# This is currently commented out because it causes mypy to crash.
32# class ClassA(Generic[T, P, Unpack[Ts]]):
35class ClassA(Generic[T, P]):
36 # > ClassVar accepts only a single argument that should be a valid type
38 bad1: ClassVar[int, str] = cast(Any, 0) # E: too many arguments
[invalid-type-form] Type qualifier `typing.ClassVar` expected exactly 1 argument, got 2
39 bad2: CV[3] = cast(Any, 0) # E: invalid type
[invalid-type-form] Int literals are not allowed in this context in a type expression
40 bad3: CV[var] = cast(Any, 0) # E: invalid type
[unresolved-reference] Name `var` used when not defined
42 # > Note that a ClassVar parameter cannot include any type variables,
43 # > regardless of the level of nesting.
45 bad4: ClassVar[T] = cast(Any, 0) # E: cannot use TypeVar
[invalid-type-form] `ClassVar` cannot contain type variables
46 bad5: ClassVar[list[T]] = cast(Any, 0) # E: cannot use TypeVar
[invalid-type-form] `ClassVar` cannot contain type variables
47 bad6: ClassVar[Callable[P, Any]] = cast(Any, 0) # E: cannot use ParamSpec
[invalid-type-form] `ClassVar` cannot contain type variables
49 # This is currently commented out because it causes mypy to crash.
50 # bad7: ClassVar[tuple[*Ts]] # E: cannot use TypeVarTuple
52 bad8: ClassVar[list[str]] = {} # E: type violation in initialization
[invalid-assignment] Object of type `dict[Unknown, Unknown]` is not assignable to `list[str]`
54 bad9: Final[ClassVar[int]] = 3 # E: ClassVar cannot be nested with Final
Expected a ty diagnostic for this line
55 bad10: list[ClassVar[int]] = [] # E: ClassVar cannot be nested
[invalid-type-form] Type qualifier `typing.ClassVar` is not allowed in type expressions (only in annotation expressions)
58 good2: ClassVar[list[str]] = []
59 good3: ClassVar[Any] = 1
60 # > If an assigned value is available, the type should be inferred as some type
61 # > to which this value is assignable.
62 # Here, type checkers could infer good4 as `float` or `Any`, for example.
64 # > If the `ClassVar` qualifier is used without any assigned value, the type
65 # > should be inferred as `Any`:
66 good5: ClassVar # E?: Type checkers may error on uninitialized ClassVar
67 good6: Annotated[ClassVar[list[int]], ""] = []
69 def method1(self, a: ClassVar[int]): # E: ClassVar not allowed here
[invalid-type-form] `ClassVar` is not allowed in function parameter annotations
70 x: ClassVar[str] = "" # E: ClassVar not allowed here
[invalid-type-form] `ClassVar` annotations are only allowed in class-body scopes
71 self.xx: ClassVar[str] = "" # E: ClassVar not allowed here
[invalid-type-form] `ClassVar` annotations are not allowed for non-name targets
73 def method2(self) -> ClassVar[int]: # E: ClassVar not allowed here
[invalid-type-form] `ClassVar` is not allowed in function return type annotations
77bad11: ClassVar[int] = 3 # E: ClassVar not allowed here
[invalid-type-form] `ClassVar` annotations are only allowed in class-body scopes
78bad12: TypeAlias = ClassVar[str] # E: ClassVar not allowed here
Expected a ty diagnostic for this line
81assert_type(ClassA.good1, int)
82assert_type(ClassA.good2, list[str])
83assert_type(ClassA.good3, Any)
84assert_type(ClassA.good5, Any)
88 captain: str = "Picard" # Instance variable with default
89 damage: int # Instance variable without default
90 stats: ClassVar[dict[str, int]] = {} # Class variable
92 def __init__(self, damage: int) -> None:
97 captain: str = "Picard"
99 stats: ClassVar[dict[str, int]] = {}
101 def __init__(self, damage: int, captain: str | None = None):
104 self.captain = captain
107 Starship.stats["hits"] = Starship.stats.get("hits", 0) + 1
110enterprise_d = Starship(3000)
111enterprise_d.stats = {} # E: cannot access via instance
[invalid-attribute-access] Cannot assign to ClassVar `stats` from an instance of type `Starship`
112Starship.stats = {} # OK
115# > As a matter of convenience (and convention), instance variables can be
116# > annotated in __init__ or other methods, rather than in the class.
119class Box(Generic[T]):
120 def __init__(self, content) -> None:
121 self.content: T = content
124# Tests for ClassVar in Protocol
127class ProtoA(Protocol):
136 def __init__(self) -> None:
140a: ProtoA = ProtoAImpl() # E: y is not a ClassVar
[invalid-assignment] Object of type `ProtoAImpl` is not assignable to `ProtoA`
143class ProtoB(Protocol):
149 def method1(cls) -> None:
153 def method2() -> None:
157class ProtoBImpl(ProtoB):
162b_x: int = ProtoBImpl.x
163b_y: int = ProtoBImpl.y
164b_z: int = ProtoBImpl.z
166b_m1 = ProtoBImpl.method1
167b_m2 = ProtoBImpl.method2