Assignment to Final attribute incorrectly flagged in conditional assignment within __init__
Nessuno ha ancora preso questa issue.
- Lingua principale
- Python
- Stelle
- 20.6k
- Fork
- 3.3k
- Metriche di merge delle PR
- Metriche PR in attesa
Descrizione
Bug Report
Documentation on typing.Final says (emphasis mine):
Final names cannot be reassigned in any scope. Final names declared in class scopes cannot be overridden in subclasses.
The problem comes in a class's init, if the final member is conditionally assigned to different values (e.g. assignments in an if/else expression, if the assignment to the member occurs in both blocks). In the if/else case, mypy flags the assignment in the else block.
To Reproduce
from typing import Final
class Foo:
attr: Final[str]
def __init__(self, flag: bool) -> None:
if flag:
self.attr = "bar"
else:
self.attr = "baz" # mypy flags with: error: Cannot assign to final attribute "attr" [misc]
Expected Behavior
I would expect mypy to not flag this code at all. For either possible value of flag, there is only a single assignment, so no reassignment occurs.
Actual Behavior
Mypy flags line 11 with: error: Cannot assign to final attribute "attr" [misc]
Your Environment
- Mypy version used: mypy 1.19.1 (compiled: yes)
- Mypy command-line flags: none; just the path to the repro test script
- Mypy configuration options from
mypy.ini(and other config files):
[tool.mypy]
python_version = "3.13"
# set mypy_path and explicit_package_bases, otherwise mypy gets confused about package names
# due to the use of namespace packages.
mypy_path = "src"
explicit_package_bases = true
pretty = true
disallow_any_unimported = true
disallow_any_expr = false
disallow_any_explicit = false
disallow_any_generics = true
disallow_subclassing_any = true
disallow_untyped_calls = true
disallow_untyped_defs = true
disallow_incomplete_defs = true
disallow_untyped_decorators = true
implicit_optional = true
strict_optional = true
warn_redundant_casts = true
warn_unused_ignores = true
warn_no_return = true
warn_return_any = true
warn_unreachable = true
warn_unused_configs = true
exclude = ["dist/.*/.*\\.py$"]
- Python version used: 3.13.7
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Direzione di ricerca
Inizia con il riproduttore Python fornito ed eseguilo con mypy 1.19.1 per confermare la diagnostica sull'assegnazione nel ramo else. Traccia la gestione degli attributi Final durante l'assegnazione condizionale e aggiungi una copertura di regressione per l'esempio; il lavoro è completato quando entrambi i rami superano il controllo dei tipi senza l'errore di riassegnazione.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- python
- Ambito
- devtools
- Tipo di issue
- Bug
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Stato di attività
- Ferma
- Chiarezza
- Specificata chiaramente
- Idoneità per principianti
- 48/100