From 4fdc78a7b874111ba1bd8a557975b41b89db49a5 Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Sun, 2 Nov 2025 22:23:00 -0800 Subject: [PATCH 1/2] Fix errors for raise NotImplemented --- mypy/checker.py | 17 ++++++++++++----- test-data/unit/check-statements.test | 2 +- test-data/unit/fixtures/notimplemented.pyi | 13 ++++++++++--- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 63e128f78310..39885dfb7555 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -4959,10 +4959,10 @@ def check_return_stmt(self, s: ReturnStmt) -> None: ) # Treat NotImplemented as having type Any, consistent with its # definition in typeshed prior to python/typeshed#4222. - if ( - isinstance(typ, Instance) - and typ.type.fullname == "builtins._NotImplementedType" - ): + if isinstance(typ, Instance) and typ.type.fullname in { + "builtins._NotImplementedType", + "types.NotImplementedType", + }: typ = AnyType(TypeOfAny.special_form) if defn.is_async_generator: @@ -5121,7 +5121,14 @@ def type_check_raise(self, e: Expression, s: RaiseStmt, optional: bool = False) # https://github.com/python/mypy/issues/11089 self.expr_checker.check_call(typ, [], [], e) - if isinstance(typ, Instance) and typ.type.fullname == "builtins._NotImplementedType": + if ( + isinstance(typ, Instance) + and typ.type.fullname in {"builtins._NotImplementedType", "types.NotImplementedType"} + ) or ( + isinstance(e, CallExpr) + and isinstance(e.callee, RefExpr) + and e.callee.fullname in {"builtins.NotImplemented"} + ): self.fail( message_registry.INVALID_EXCEPTION.with_additional_msg( '; did you mean "NotImplementedError"?' diff --git a/test-data/unit/check-statements.test b/test-data/unit/check-statements.test index 9ab68b32472d..d50a62a8dad6 100644 --- a/test-data/unit/check-statements.test +++ b/test-data/unit/check-statements.test @@ -523,7 +523,7 @@ if object(): if object(): raise NotImplemented # E: Exception must be derived from BaseException; did you mean "NotImplementedError"? if object(): - raise NotImplemented() # E: NotImplemented? not callable + raise NotImplemented() # E: Exception must be derived from BaseException; did you mean "NotImplementedError"? [builtins fixtures/notimplemented.pyi] [case testTryFinallyStatement] diff --git a/test-data/unit/fixtures/notimplemented.pyi b/test-data/unit/fixtures/notimplemented.pyi index 92edf84a7fd1..c9e58f099477 100644 --- a/test-data/unit/fixtures/notimplemented.pyi +++ b/test-data/unit/fixtures/notimplemented.pyi @@ -10,9 +10,16 @@ class bool: pass class int: pass class str: pass class dict: pass +class tuple: pass +class ellipsis: pass -class _NotImplementedType(Any): - __call__: NotImplemented # type: ignore -NotImplemented: _NotImplementedType +import sys + +if sys.version_info >= (3, 10): # type: ignore + from types import NotImplementedType + NotImplemented: NotImplementedType +else: + class _NotImplementedType(Any): ... + NotImplemented: _NotImplementedType class BaseException: pass From 1d8482b51f1c885dbdf600d52f3a7ff8a2c564d2 Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Mon, 3 Nov 2025 18:26:57 -0800 Subject: [PATCH 2/2] . --- mypy/checker.py | 6 ++---- mypy/types.py | 2 ++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 39885dfb7555..1e0a1f311852 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -197,6 +197,7 @@ from mypy.types import ( ANY_STRATEGY, MYPYC_NATIVE_INT_NAMES, + NOT_IMPLEMENTED_TYPE_NAMES, OVERLOAD_NAMES, AnyType, BoolTypeQuery, @@ -4959,10 +4960,7 @@ def check_return_stmt(self, s: ReturnStmt) -> None: ) # Treat NotImplemented as having type Any, consistent with its # definition in typeshed prior to python/typeshed#4222. - if isinstance(typ, Instance) and typ.type.fullname in { - "builtins._NotImplementedType", - "types.NotImplementedType", - }: + if isinstance(typ, Instance) and typ.type.fullname in NOT_IMPLEMENTED_TYPE_NAMES: typ = AnyType(TypeOfAny.special_form) if defn.is_async_generator: diff --git a/mypy/types.py b/mypy/types.py index 426d560c2bf7..df854325a64b 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -188,6 +188,8 @@ ELLIPSIS_TYPE_NAMES: Final = ("builtins.ellipsis", "types.EllipsisType") +NOT_IMPLEMENTED_TYPE_NAMES: Final = ("builtins._NotImplementedType", "types.NotImplementedType") + # A placeholder used for Bogus[...] parameters _dummy: Final[Any] = object()