Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot override class variable -- using Final and ClassVar #15616

Closed
christianbundy opened this issue Jul 6, 2023 · 2 comments
Closed

Cannot override class variable -- using Final and ClassVar #15616

christianbundy opened this issue Jul 6, 2023 · 2 comments
Labels
bug mypy got something wrong topic-final PEP 591 topic-inheritance Inheritance and incompatible overrides

Comments

@christianbundy
Copy link
Contributor

Bug Report

PEP 591 indicates:

Type checkers should infer a final attribute that is initialized in a class body as being a class variable. Variables should not be annotated with both ClassVar and Final.

But in practice, Mypy displays a type error when you use Final on a subclass where the parent class used a ClassVar.

To Reproduce

from typing import ClassVar, Final, ClassVar, Literal


class Animal:
    description: ClassVar[str] = "hard to generalize"
    
    
class Dog(Animal):
    description: Final[str] = "very good"

https://mypy-play.net/?mypy=latest&python=3.11&gist=69298f23e25b94da7dadc694769db16d

Expected Behavior

No error.

Actual Behavior

Cannot override class variable (previously declared on base class "Animal") with instance variable  [misc]

You may be tempted to work around this with:

class Dog(Animal):
    description: Final[ClassVar[str]] = "very good"

But then Mypy outputs:

Variable should not be annotated with both ClassVar and Final  [misc]

Your Environment

  • Mypy version used: 1.4.1
  • Mypy command-line flags: None
  • Mypy configuration options from mypy.ini (and other config files): None
  • Python version used: 3.11
@christianbundy christianbundy added the bug mypy got something wrong label Jul 6, 2023
@AlexWaygood AlexWaygood added the topic-final PEP 591 label Jul 6, 2023
@AlexWaygood
Copy link
Member

AlexWaygood commented Jul 6, 2023

I think mypy's behaviour is correct here. Your base class has an attribute description that's settable on the class object itself. But your subclass has an attribute description that's read-only in all situations. That seems like an incompatible override that violates the Liskov Substitution Principle.

Remember that Final does not just mean "the name cannot be overridden in subclasses"; it also means "the name cannot be reassigned to in the same scope".

@AlexWaygood AlexWaygood added the topic-inheritance Inheritance and incompatible overrides label Jul 6, 2023
@AlexWaygood AlexWaygood closed this as not planned Won't fix, can't repro, duplicate, stale Jul 7, 2023
@christianbundy
Copy link
Contributor Author

Makes sense to me, thanks a lot for the explanation!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong topic-final PEP 591 topic-inheritance Inheritance and incompatible overrides
Projects
None yet
Development

No branches or pull requests

2 participants