Fixed a bug in the __post_init__ validation logic that resulted in a false positive when a dataclass with an InitVar derives from another dataclass with an InitVar.

This commit is contained in:
Eric Traut 2022-03-10 23:51:53 -07:00
parent d4718f5c8a
commit 915928f572
2 changed files with 33 additions and 4 deletions

View File

@ -3471,13 +3471,24 @@ export class Checker extends ParseTreeWalker {
return;
}
// If the class derives from Any, we can't reliably apply the check.
if (ClassType.derivesFromAnyOrUnknown(classType)) {
return;
}
// Collect the list of init-only variables in the order they were declared.
const initOnlySymbolMap = new Map<string, Symbol>();
classType.details.fields.forEach((symbol, name) => {
if (symbol.isInitVar()) {
initOnlySymbolMap.set(name, symbol);
for (let i = classType.details.mro.length - 1; i >= 0; i--) {
const mroClass = classType.details.mro[i];
if (isClass(mroClass) && ClassType.isDataClass(mroClass)) {
mroClass.details.fields.forEach((symbol, name) => {
if (symbol.isInitVar()) {
initOnlySymbolMap.set(name, symbol);
}
});
}
});
}
const postInitType = this._evaluator.getTypeOfMember(postInitMember);
if (

View File

@ -41,3 +41,21 @@ class D:
# This should generate an error because the type is incompatible.
def __post_init__(self, iterable: Iterable[str]) -> None:
...
@dataclass
class E:
_name: InitVar[str] = field()
name: str = field(init=False)
def __post_init__(self, _name: str):
...
@dataclass
class F(E):
_age: InitVar[int] = field()
age: int = field(init=False)
def __post_init__(self, _name: str, _age: int):
...