From 5baea2e5708ea98cb956de5a3dde4a00a79e7c3d Mon Sep 17 00:00:00 2001 From: wyattscarpenter Date: Tue, 11 Nov 2025 16:46:04 -0800 Subject: [PATCH 1/4] Make NoneType annotation error a new code Change the code of "NoneType should not be used as a type, please use None instead" error to be a new code, so that people who don't like this rule can disable it easily. I haven't made this a subcode of valid-type because NoneType is actually a valid type; it's just dispreferred. I have added the documentation for the new code, but haven't added any new tests (the old test still runs fine). Fixes https://github.com/python/mypy/issues/20218 --- docs/source/error_code_list.rst | 21 +++++++++++++++++++++ mypy/errorcodes.py | 1 + mypy/typeanal.py | 2 +- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/docs/source/error_code_list.rst b/docs/source/error_code_list.rst index d4e2c83323ac..b38e8009994c 100644 --- a/docs/source/error_code_list.rst +++ b/docs/source/error_code_list.rst @@ -215,6 +215,27 @@ You can use :py:class:`~collections.abc.Callable` as the type for callable objec for x in objs: f(x) +.. _code-nonetype-type: + +Check that NoneType is not used as a type (annotation) [nonetype-type] +---------------------------------------------------------------------- + +The preferred way to annotate the type of `None` is `None`. +`NoneType` is equivalent, but mypy won't allow it by default. + +.. code-block:: python + from types import NoneType + def f(x: None) -> None: + reveal_type(x) # note: Revealed type is "None" + + # error: NoneType should not be used as a type, please use None instead [nonetype-type] + def g(x: NoneType) -> None: + reveal_type(x) # note: Revealed type is "None" + + # error: NoneType should not be used as a type, please use None instead [nonetype-type] + x1: NoneType = None + x2: None = None #OK + .. _code-metaclass: Check the validity of a class's metaclass [metaclass] diff --git a/mypy/errorcodes.py b/mypy/errorcodes.py index 785b6166b18b..cac8f0cd8731 100644 --- a/mypy/errorcodes.py +++ b/mypy/errorcodes.py @@ -60,6 +60,7 @@ def __hash__(self) -> int: "call-overload", "Check that an overload variant matches arguments", "General" ) VALID_TYPE: Final = ErrorCode("valid-type", "Check that type (annotation) is valid", "General") +NONETYPE_TYPE: Final = ErrorCode("nonetype-type", "Check that type (annotation) is not NoneType", "General") VAR_ANNOTATED: Final = ErrorCode( "var-annotated", "Require variable annotation if type can't be inferred", "General" ) diff --git a/mypy/typeanal.py b/mypy/typeanal.py index 06fa847c5434..b96e0ac9ec82 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -920,7 +920,7 @@ def analyze_type_with_type_info( self.fail( "NoneType should not be used as a type, please use None instead", ctx, - code=codes.VALID_TYPE, + code=codes.NONETYPE_TYPE, ) return NoneType(ctx.line, ctx.column) From 431e33f02dff47ddc43ad7df9048bb06c4f6e626 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 11 Nov 2025 23:54:40 +0000 Subject: [PATCH 2/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mypy/errorcodes.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mypy/errorcodes.py b/mypy/errorcodes.py index cac8f0cd8731..3fadd7bc07e7 100644 --- a/mypy/errorcodes.py +++ b/mypy/errorcodes.py @@ -60,7 +60,9 @@ def __hash__(self) -> int: "call-overload", "Check that an overload variant matches arguments", "General" ) VALID_TYPE: Final = ErrorCode("valid-type", "Check that type (annotation) is valid", "General") -NONETYPE_TYPE: Final = ErrorCode("nonetype-type", "Check that type (annotation) is not NoneType", "General") +NONETYPE_TYPE: Final = ErrorCode( + "nonetype-type", "Check that type (annotation) is not NoneType", "General" +) VAR_ANNOTATED: Final = ErrorCode( "var-annotated", "Require variable annotation if type can't be inferred", "General" ) From d290dee353d0d46e2bcf73e17ceb1c4ed84ead09 Mon Sep 17 00:00:00 2001 From: wyattscarpenter Date: Tue, 11 Nov 2025 19:00:01 -0500 Subject: [PATCH 3/4] Conform to another crazy rst formatting pickiness --- docs/source/error_code_list.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/error_code_list.rst b/docs/source/error_code_list.rst index b38e8009994c..9d6cd4c2db34 100644 --- a/docs/source/error_code_list.rst +++ b/docs/source/error_code_list.rst @@ -224,6 +224,7 @@ The preferred way to annotate the type of `None` is `None`. `NoneType` is equivalent, but mypy won't allow it by default. .. code-block:: python + from types import NoneType def f(x: None) -> None: reveal_type(x) # note: Revealed type is "None" From ddc5c46c076211114ff1edb56f6716273f668ac9 Mon Sep 17 00:00:00 2001 From: wyattscarpenter Date: Tue, 11 Nov 2025 19:22:38 -0700 Subject: [PATCH 4/4] space in OK comment Co-authored-by: A5rocks --- docs/source/error_code_list.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/error_code_list.rst b/docs/source/error_code_list.rst index 9d6cd4c2db34..1aec6cf7dbde 100644 --- a/docs/source/error_code_list.rst +++ b/docs/source/error_code_list.rst @@ -235,7 +235,7 @@ The preferred way to annotate the type of `None` is `None`. # error: NoneType should not be used as a type, please use None instead [nonetype-type] x1: NoneType = None - x2: None = None #OK + x2: None = None # OK .. _code-metaclass: