diff --git a/mypy/plugins/dataclasses.py b/mypy/plugins/dataclasses.py index d87c1c0674f9..f897552a33d9 100644 --- a/mypy/plugins/dataclasses.py +++ b/mypy/plugins/dataclasses.py @@ -83,7 +83,12 @@ def transform(self) -> None: # Some definitions are not ready, defer() should be already called. return for attr in attributes: - if info[attr.name].type is None: + node = info.get(attr.name) + if node is None: + # Nodes of superclass InitVars not used in __init__ cannot be reached. + assert attr.is_init_var and not attr.is_in_init + continue + if node.type is None: ctx.api.defer() return decorator_arguments = { @@ -184,7 +189,11 @@ def reset_init_only_vars(self, info: TypeInfo, attributes: List[DataclassAttribu """Remove init-only vars from the class and reset init var declarations.""" for attr in attributes: if attr.is_init_var: - del info.names[attr.name] + if attr.name in info.names: + del info.names[attr.name] + else: + # Nodes of superclass InitVars not used in __init__ cannot be reached. + assert attr.is_init_var and not attr.is_in_init for stmt in info.defn.defs.body: if isinstance(stmt, AssignmentStmt) and stmt.unanalyzed_type: lvalue = stmt.lvalues[0] diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test index 5cb0c3cee52d..95ed85f22d8f 100644 --- a/test-data/unit/check-dataclasses.test +++ b/test-data/unit/check-dataclasses.test @@ -555,6 +555,22 @@ app.database_name # E: "Application" has no attribute "database_name" class Yes: ... [builtins fixtures/list.pyi] +[case testDataclassesNoInitInitVarInheritance] +from dataclasses import dataclass, field, InitVar + +@dataclass +class Super: + foo: InitVar = field(init=False) + +@dataclass +class Sub(Super): + bar: int + +sub = Sub(5) +sub.foo # E: "Sub" has no attribute "foo" +sub.bar +[builtins fixtures/bool.pyi] + [case testDataclassFactory] from typing import Type, TypeVar from dataclasses import dataclass