Bug Report
[Python 3.13] mypy does not accept nesting ClassVar and Final in class body
The official docs of the typing module say:
Changed in version 3.13: ClassVar can now be nested in Final and vice versa.
The typing specs on qualifiers are more specific:
Final may be wrapped only by other type qualifiers (e.g. ClassVar or
Annotation).
In particular, nesting ClassVar and Final is a special case for dataclasses:
Type checkers should infer a final attribute that is initialized in a class
body as being a class variable, except in the case of dataclasses, where
x: Final[int] = 3 creates a dataclass field and instance-level final
attribute x with default value 3; x: ClassVar[Final[int]] = 3 is
necessary to create a final class variable with value 3. In
non-dataclasses, combining ClassVar and Final is redundant, and type
checkers may choose to warn or error on the redundancy.
To Reproduce
In both classes below the foo statement is not accepted by mypy:
from dataclasses import dataclass
from typing import ClassVar, Final
@dataclass
class Bar:
foo: ClassVar[Final[int]] = 0
@dataclass
class Baz:
foo: Final[ClassVar[int]] = 0
Note that the docs only mention ClassVar[Final[int]] and not Final[ClassVar[int]]. In fact, the latter is not considered a class variable by the current dataclasses implementation:
>>> Bar(foo=1) # foo is a class variable
Traceback (most recent call last):
File "<python-input-2>", line 1, in <module>
Bar(foo=1)
~~~^^^^^^^
TypeError: Bar.__init__() got an unexpected keyword argument 'foo'
>>> Baz(foo=1) # foo is an instance variable
Baz(foo=1)
Expected Behavior
[Python 3.13] mypy should accept ClassVar[Final[<type>]] in the body of a dataclass
The form ClassVar[Final[int]] conforms with the official typing specs and behaves as expected. I think it should be accepted as part of Python 3.13 support.
The typing specs allow for a warning or error when ClassVar and Final are nested outside of a dataclass body. I think this should result in an error since it is redundant, perhaps only in strict mode.
For the form Final[ClassVar[int]] I am not sure. It could either result in an error or simply be parsed as a final instance variable.
Actual Behavior
The form ClassVar[Final[int]] results in:
error: Final can be only used as an outermost qualifier in a variable annotation [valid-type]
The form Final[ClassVar[int]] results in:
error: Variable should not be annotated with both ClassVar and Final [misc]
The behavior is the same with or without the @dataclass decorator.
Your Environment
- Mypy version used: 1.13.0
- Mypy command-line flags:
- Mypy configuration options from
mypy.ini (and other config files): strict = true
- Python version used: 3.13.0
Notes
The typing specs were changed in python/typing#1669
Related discussion is found in python/cpython#89547
The difference between ClassVar[Final[int]] and Final[ClassVar[int]] was noticed in microsoft/pyright#8676 (comment)
This issue is about Python 3.13 so could be added to #17264
This issue is related to #12061
Bug Report
[Python 3.13]
mypydoes not accept nestingClassVarandFinalin class bodyThe official docs of the
typingmodule say:The typing specs on qualifiers are more specific:
In particular, nesting
ClassVarandFinalis a special case for dataclasses:To Reproduce
In both classes below the
foostatement is not accepted bymypy:Note that the docs only mention
ClassVar[Final[int]]and notFinal[ClassVar[int]]. In fact, the latter is not considered a class variable by the currentdataclassesimplementation:Expected Behavior
[Python 3.13]
mypyshould acceptClassVar[Final[<type>]]in the body of a dataclassThe form
ClassVar[Final[int]]conforms with the official typing specs and behaves as expected. I think it should be accepted as part of Python 3.13 support.The typing specs allow for a warning or error when
ClassVarandFinalare nested outside of a dataclass body. I think this should result in an error since it is redundant, perhaps only in strict mode.For the form
Final[ClassVar[int]]I am not sure. It could either result in an error or simply be parsed as a final instance variable.Actual Behavior
The form
ClassVar[Final[int]]results in:error: Final can be only used as an outermost qualifier in a variable annotation [valid-type]The form
Final[ClassVar[int]]results in:error: Variable should not be annotated with both ClassVar and Final [misc]The behavior is the same with or without the
@dataclassdecorator.Your Environment
mypy.ini(and other config files):strict = trueNotes
The typing specs were changed in python/typing#1669
Related discussion is found in python/cpython#89547
The difference between
ClassVar[Final[int]]andFinal[ClassVar[int]]was noticed in microsoft/pyright#8676 (comment)This issue is about Python 3.13 so could be added to #17264
This issue is related to #12061