mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 05:44:56 +00:00
[ty] Disallow assignment to Final
class attributes (#19457)
## Summary Emit errors for the following assignments: ```py class C: CLASS_LEVEL_CONSTANT: Final[int] = 1 C.CLASS_LEVEL_CONSTANT = 2 C().CLASS_LEVEL_CONSTANT = 2 ``` ## Test Plan Updated and new MD tests
This commit is contained in:
parent
f063c0e874
commit
b6579eaf04
3 changed files with 63 additions and 20 deletions
|
@ -498,7 +498,7 @@ class C:
|
|||
reveal_type(C.__init__) # revealed: (self: C, instance_variable_no_default: int, instance_variable: int = Literal[1]) -> None
|
||||
|
||||
c = C(1)
|
||||
# TODO: this should be an error
|
||||
# error: [invalid-assignment] "Cannot assign to final attribute `instance_variable` on type `C`"
|
||||
c.instance_variable = 2
|
||||
```
|
||||
|
||||
|
|
|
@ -170,26 +170,37 @@ Assignments to attributes qualified with `Final` are also not allowed:
|
|||
```py
|
||||
from typing import Final
|
||||
|
||||
class C:
|
||||
FINAL_A: Final[int] = 1
|
||||
FINAL_B: Final = 1
|
||||
class Meta(type):
|
||||
META_FINAL_A: Final[int] = 1
|
||||
META_FINAL_B: Final = 1
|
||||
|
||||
class C(metaclass=Meta):
|
||||
CLASS_FINAL_A: Final[int] = 1
|
||||
CLASS_FINAL_B: Final = 1
|
||||
|
||||
def __init__(self):
|
||||
self.FINAL_C: Final[int] = 1
|
||||
self.FINAL_D: Final = 1
|
||||
self.INSTANCE_FINAL_A: Final[int] = 1
|
||||
self.INSTANCE_FINAL_B: Final = 1
|
||||
|
||||
# TODO: these should be errors (that mention `Final`)
|
||||
C.FINAL_A = 2
|
||||
# error: [invalid-assignment] "Object of type `Literal[2]` is not assignable to attribute `FINAL_B` of type `Literal[1]`"
|
||||
C.FINAL_B = 2
|
||||
# error: [invalid-assignment] "Cannot assign to final attribute `META_FINAL_A` on type `<class 'C'>`"
|
||||
C.META_FINAL_A = 2
|
||||
# error: [invalid-assignment] "Cannot assign to final attribute `META_FINAL_B` on type `<class 'C'>`"
|
||||
C.META_FINAL_B = 2
|
||||
|
||||
# error: [invalid-assignment] "Cannot assign to final attribute `CLASS_FINAL_A` on type `<class 'C'>`"
|
||||
C.CLASS_FINAL_A = 2
|
||||
# error: [invalid-assignment] "Cannot assign to final attribute `CLASS_FINAL_B` on type `<class 'C'>`"
|
||||
C.CLASS_FINAL_B = 2
|
||||
|
||||
# TODO: these should be errors (that mention `Final`)
|
||||
c = C()
|
||||
c.FINAL_A = 2
|
||||
# error: [invalid-assignment] "Object of type `Literal[2]` is not assignable to attribute `FINAL_B` of type `Literal[1]`"
|
||||
c.FINAL_B = 2
|
||||
c.FINAL_C = 2
|
||||
c.FINAL_D = 2
|
||||
# error: [invalid-assignment] "Cannot assign to final attribute `CLASS_FINAL_A` on type `C`"
|
||||
c.CLASS_FINAL_A = 2
|
||||
# error: [invalid-assignment] "Cannot assign to final attribute `CLASS_FINAL_B` on type `C`"
|
||||
c.CLASS_FINAL_B = 2
|
||||
# TODO: this should be an error
|
||||
c.INSTANCE_FINAL_A = 2
|
||||
# TODO: this should be an error
|
||||
c.INSTANCE_FINAL_B = 2
|
||||
```
|
||||
|
||||
## Mutability
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue