mirror of
				https://github.com/astral-sh/ruff.git
				synced 2025-10-31 12:05:57 +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
	
	 David Peter
						David Peter