Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork3.1k
Description
Bug Report
[Python 3.13]mypy does not accept nestingClassVar andFinal in class body
Theofficial docs of thetyping module say:
Changed in version 3.13:
ClassVarcan now be nested inFinaland vice versa.
Thetyping specs on qualifiers are more specific:
Finalmay be wrapped only by other type qualifiers (e.g.ClassVarorAnnotation).
In particular, nestingClassVar andFinal 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 ofdataclasses, wherex: Final[int] = 3creates a dataclass field and instance-level final
attributexwith default value3;x: ClassVar[Final[int]] = 3is
necessary to create a final class variable with value3. In
non-dataclasses, combiningClassVarandFinalis redundant, and type
checkers may choose to warn or error on the redundancy.
To Reproduce
In both classes below thefoo statement is not accepted bymypy:
fromdataclassesimportdataclassfromtypingimportClassVar,Final@dataclassclassBar:foo:ClassVar[Final[int]]=0@dataclassclassBaz:foo:Final[ClassVar[int]]=0
Note that the docs only mentionClassVar[Final[int]] and notFinal[ClassVar[int]]. In fact, the latter is not considered a class variable by the currentdataclasses implementation:
>>>Bar(foo=1)# foo is a class variableTraceback (mostrecentcalllast):File"<python-input-2>",line1,in<module>Bar(foo=1)~~~^^^^^^^TypeError:Bar.__init__()gotanunexpectedkeywordargument'foo'>>>Baz(foo=1)# foo is an instance variableBaz(foo=1)
Expected Behavior
[Python 3.13]mypy should acceptClassVar[Final[<type>]] in the body of a dataclass
The formClassVar[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 whenClassVar andFinal 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 formFinal[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 formClassVar[Final[int]] results in:error: Final can be only used as an outermost qualifier in a variable annotation [valid-type]
The formFinal[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 inpython/typing#1669
Related discussion is found inpython/cpython#89547
The difference betweenClassVar[Final[int]] andFinal[ClassVar[int]] was noticed inmicrosoft/pyright#8676 (comment)
This issue is about Python 3.13 so could be added to#17264
This issue is related to#12061