(false positive) Using `@final` decorator on a `Protocol` class results in an error in most cases
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 20.6k
- Forks
- 3.3k
- PR merge metrics
- PR metrics pending
Description
Bug Report
Applying the @final decorator on a class that inherits from Protocol results in an error when the class implements abstract attributes (attributes, methods, properties). Protocols often implement abstract attributes or methods.
The original reasoning behind the error is that, for normal classes, the abstract attributes could never be implemented if the class is final.
But this reasoning doesn't really extend to Protocol since they support virtual subclasses.
There are at least a few potentially valid use cases for declaring a Protocol as final.
In my use case, a few of my concrete implementations are unable to subclass the Protocol because of issues with property overriding. Since this Protocol is very tiny and has no default implementations anyway, it makes sense to enforce that none of the concrete implementations subclass from it, for consistency and a bit more freedom, as in certain cases it isn't possible to and in my opinion there aren't many benefits.
To Reproduce
from typing import Protocol, final
@final
class Inter(Protocol):
x: int
def y(self) -> int:
...
@property
def z(self) -> int:
...
https://gist.github.com/mypy-play/95be80b2ef05cc43ed77677df133d9d5
Error
main.py:4: error: Final class __main__.Inter has abstract attributes "x", "y", "z" [misc]
mypy thinks that abstract implementations in a final class is useless, as per #8316.
For Protocols however, the virtual subclasses may implement the abstract attributes without needing to subclass the Protocol.
Your Environment
- Mypy version used: 1.10.0
- Mypy command-line flags: none
- Mypy configuration options from
mypy.ini(and other config files): default - Python version used: 3.12
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the provided Python reproducer and compare the diagnostic for a final Protocol with abstract attributes against the behavior for ordinary final classes. Done means a final Protocol with abstract attributes does not produce the reported false-positive error, while the existing final-class check remains correct.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100