Fixed bug that results in a false negative when a Final class variable is assigned a value in the class body and reassigned a value in the __init__ method. This addresses #8013. (#8015)

This commit is contained in:
Eric Traut 2024-05-28 20:42:09 -07:00 committed by GitHub
parent 59eabcb60f
commit ece525e960
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 16 additions and 2 deletions

View File

@ -116,6 +116,7 @@ import {
FunctionDeclaration,
ModuleLoaderActions,
SpecialBuiltInClassDeclaration,
VariableDeclaration,
} from './declaration';
import {
ResolvedAliasInfo,
@ -5872,7 +5873,12 @@ export function createTypeEvaluator(
// If a Final instance variable is declared in the class body but is
// being assigned within an __init__ method, it's allowed.
const enclosingFunctionNode = ParseTreeUtils.getEnclosingFunction(errorNode);
if (!enclosingFunctionNode || enclosingFunctionNode.name.value !== '__init__') {
if (
!enclosingFunctionNode ||
enclosingFunctionNode.name.value !== '__init__' ||
(finalVarTypeDecl as VariableDeclaration).inferredTypeSource !== undefined ||
isInstantiableClass(classType)
) {
diag?.addMessage(LocMessage.finalReassigned().format({ name: memberName }));
isDescriptorError = true;
}

View File

@ -121,6 +121,8 @@ b: list[Final[int]] = []
class ClassA:
member1: Final = 3
member2: Final
member4: Final
member5: Final = 3
def __init__(self):
# This should generate an error.
@ -130,6 +132,12 @@ class ClassA:
self.member3: Final = "hi"
# This should generate an error.
ClassA.member4 = "hi"
# This should generate an error.
ClassA.member5 = 3
def other(self):
# This should generate an error.
self.member1 = 5

View File

@ -32,7 +32,7 @@ test('Final2', () => {
test('Final3', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['final3.py']);
TestUtils.validateResults(analysisResults, 33);
TestUtils.validateResults(analysisResults, 35);
});
test('Final4', () => {