From fdc7914b2001b57fda72b33adb725989dc63fe8a Mon Sep 17 00:00:00 2001 From: Ilya Priven Date: Sat, 9 Sep 2023 18:25:40 -0400 Subject: [PATCH 1/4] Fix __post_init__() internal error --- mypy/checker.py | 2 ++ mypy/nodes.py | 1 - mypy/plugins/dataclasses.py | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index fa7c645873d0..79bdea851312 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1076,6 +1076,8 @@ def check_func_item( if name == "__exit__": self.check__exit__return_type(defn) + # TODO: the following logic should move to the dataclasses plugin + # https://github.com/python/mypy/issues/15515 if name == "__post_init__": if dataclasses_plugin.is_processed_dataclass(defn.info): dataclasses_plugin.check_post_init(self, defn, defn.info) diff --git a/mypy/nodes.py b/mypy/nodes.py index d29e99ccace7..6556cd910b46 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -515,7 +515,6 @@ def __init__(self) -> None: # Original, not semantically analyzed type (used for reprocessing) self.unanalyzed_type: mypy.types.ProperType | None = None # If method, reference to TypeInfo - # TODO: Type should be Optional[TypeInfo] self.info = FUNC_NO_INFO self.is_property = False self.is_class = False diff --git a/mypy/plugins/dataclasses.py b/mypy/plugins/dataclasses.py index 8b34c28b6832..4dda7b3eadb6 100644 --- a/mypy/plugins/dataclasses.py +++ b/mypy/plugins/dataclasses.py @@ -1070,8 +1070,8 @@ def replace_function_sig_callback(ctx: FunctionSigContext) -> CallableType: ) -def is_processed_dataclass(info: TypeInfo | None) -> bool: - return info is not None and "dataclass" in info.metadata +def is_processed_dataclass(info: TypeInfo) -> bool: + return info and "dataclass" in info.metadata def check_post_init(api: TypeChecker, defn: FuncItem, info: TypeInfo) -> None: From d9645cee3c7d85cd1ff5c0a6c7b20add90ccfd5d Mon Sep 17 00:00:00 2001 From: Ilya Priven Date: Sat, 9 Sep 2023 18:35:37 -0400 Subject: [PATCH 2/4] add test --- test-data/unit/check-dataclasses.test | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test index 8a50e7124d05..35df84658259 100644 --- a/test-data/unit/check-dataclasses.test +++ b/test-data/unit/check-dataclasses.test @@ -2280,6 +2280,10 @@ reveal_type(a2) # N: Revealed type is "__main__.A[builtins.int]" [builtins fixtures/tuple.pyi] +[case testPostInitNotMethod] +def __post_init__() -> None: + pass + [case testPostInitCorrectSignature] from typing import Any, Generic, TypeVar, Callable, Self from dataclasses import dataclass, InitVar From c205c1c57e805734957ecca95238f4339e37ca19 Mon Sep 17 00:00:00 2001 From: Ilya Priven Date: Sat, 9 Sep 2023 19:01:01 -0400 Subject: [PATCH 3/4] fix typing --- mypy/checker.py | 4 +++- mypy/plugins/dataclasses.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 79bdea851312..81b48f49979a 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -2884,7 +2884,9 @@ def check_assignment( typ = self.expr_checker.accept(rvalue) self.check_match_args(inferred, typ, lvalue) if name == "__post_init__": - if dataclasses_plugin.is_processed_dataclass(self.scope.active_class()): + if ( + active_class := self.scope.active_class() + ) and dataclasses_plugin.is_processed_dataclass(active_class): self.fail(message_registry.DATACLASS_POST_INIT_MUST_BE_A_FUNCTION, rvalue) # Defer PartialType's super type checking. diff --git a/mypy/plugins/dataclasses.py b/mypy/plugins/dataclasses.py index 4dda7b3eadb6..99f079705c3f 100644 --- a/mypy/plugins/dataclasses.py +++ b/mypy/plugins/dataclasses.py @@ -1071,7 +1071,7 @@ def replace_function_sig_callback(ctx: FunctionSigContext) -> CallableType: def is_processed_dataclass(info: TypeInfo) -> bool: - return info and "dataclass" in info.metadata + return bool(info) and "dataclass" in info.metadata def check_post_init(api: TypeChecker, defn: FuncItem, info: TypeInfo) -> None: From 90faa6091ffd4706269ed38d1ce10cc7a3c69244 Mon Sep 17 00:00:00 2001 From: Ilya Priven Date: Sat, 9 Sep 2023 19:01:56 -0400 Subject: [PATCH 4/4] fix typing --- mypy/checker.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 81b48f49979a..5a74f019dcf4 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -2884,9 +2884,8 @@ def check_assignment( typ = self.expr_checker.accept(rvalue) self.check_match_args(inferred, typ, lvalue) if name == "__post_init__": - if ( - active_class := self.scope.active_class() - ) and dataclasses_plugin.is_processed_dataclass(active_class): + active_class = self.scope.active_class() + if active_class and dataclasses_plugin.is_processed_dataclass(active_class): self.fail(message_registry.DATACLASS_POST_INIT_MUST_BE_A_FUNCTION, rvalue) # Defer PartialType's super type checking.