From a9ee618f3a941098b24156eb499db5684fcfc261 Mon Sep 17 00:00:00 2001 From: Charlie Denton Date: Sun, 9 Apr 2023 19:51:16 +0100 Subject: [PATCH] Fix disappearing errors when re-running dmypy check (#14835) This adds a commit which fixes issue https://github.com/python/mypy/issues/9655 wherein some types of error would be lost when a file was re-processed by dmypy. Regression tests are also included. This also fixes another error where sometimes files would not be re-processed by dmypy if the only error in the file was either "unused type ignore" or "ignore without code". --------- Co-authored-by: AlexWaygood --- mypy/errors.py | 4 ++ mypy/server/update.py | 6 +++ test-data/unit/daemon.test | 89 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+) diff --git a/mypy/errors.py b/mypy/errors.py index 9a704ef3aea6..757f31ba1f6b 100644 --- a/mypy/errors.py +++ b/mypy/errors.py @@ -668,6 +668,8 @@ def generate_unused_ignore_errors(self, file: str) -> None: False, False, False, + origin=(self.file, [line]), + target=self.target_module, ) self._add_error_info(file, info) @@ -720,6 +722,8 @@ def generate_ignore_without_code_errors( False, False, False, + origin=(self.file, [line]), + target=self.target_module, ) self._add_error_info(file, info) diff --git a/mypy/server/update.py b/mypy/server/update.py index 00b823c99dfd..e909840d2757 100644 --- a/mypy/server/update.py +++ b/mypy/server/update.py @@ -667,6 +667,8 @@ def restore(ids: list[str]) -> None: state.type_check_first_pass() state.type_check_second_pass() state.detect_possibly_undefined_vars() + state.generate_unused_ignore_notes() + state.generate_ignore_without_code_notes() t2 = time.time() state.finish_passes() t3 = time.time() @@ -1027,6 +1029,10 @@ def key(node: FineGrainedDeferredNode) -> int: if graph[module_id].type_checker().check_second_pass(): more = True + graph[module_id].detect_possibly_undefined_vars() + graph[module_id].generate_unused_ignore_notes() + graph[module_id].generate_ignore_without_code_notes() + if manager.options.export_types: manager.all_types.update(graph[module_id].type_map()) diff --git a/test-data/unit/daemon.test b/test-data/unit/daemon.test index 7586c8763d33..869f60b4e1fd 100644 --- a/test-data/unit/daemon.test +++ b/test-data/unit/daemon.test @@ -522,3 +522,92 @@ class A: x: int class B: x: int + +[case testUnusedTypeIgnorePreservedOnRerun] +-- Regression test for https://github.com/python/mypy/issues/9655 +$ dmypy start -- --warn-unused-ignores --no-error-summary +Daemon started +$ dmypy check -- bar.py +bar.py:2: error: Unused "type: ignore" comment +== Return code: 1 +$ dmypy check -- bar.py +bar.py:2: error: Unused "type: ignore" comment +== Return code: 1 + +[file foo/__init__.py] +[file foo/empty.py] +[file bar.py] +from foo.empty import * +a = 1 # type: ignore + +[case testTypeIgnoreWithoutCodePreservedOnRerun] +-- Regression test for https://github.com/python/mypy/issues/9655 +$ dmypy start -- --enable-error-code ignore-without-code --no-error-summary +Daemon started +$ dmypy check -- bar.py +bar.py:2: error: "type: ignore" comment without error code [ignore-without-code] +== Return code: 1 +$ dmypy check -- bar.py +bar.py:2: error: "type: ignore" comment without error code [ignore-without-code] +== Return code: 1 + +[file foo/__init__.py] +[file foo/empty.py] +[file bar.py] +from foo.empty import * +a = 1 # type: ignore + +[case testUnusedTypeIgnorePreservedAfterChange] +-- Regression test for https://github.com/python/mypy/issues/9655 +$ dmypy start -- --warn-unused-ignores --no-error-summary +Daemon started +$ dmypy check -- bar.py +bar.py:2: error: Unused "type: ignore" comment +== Return code: 1 +$ {python} -c "print('\n')" >> bar.py +$ dmypy check -- bar.py +bar.py:2: error: Unused "type: ignore" comment +== Return code: 1 + +[file foo/__init__.py] +[file foo/empty.py] +[file bar.py] +from foo.empty import * +a = 1 # type: ignore + +[case testTypeIgnoreWithoutCodePreservedAfterChange] +-- Regression test for https://github.com/python/mypy/issues/9655 +$ dmypy start -- --enable-error-code ignore-without-code --no-error-summary +Daemon started +$ dmypy check -- bar.py +bar.py:2: error: "type: ignore" comment without error code [ignore-without-code] +== Return code: 1 +$ {python} -c "print('\n')" >> bar.py +$ dmypy check -- bar.py +bar.py:2: error: "type: ignore" comment without error code [ignore-without-code] +== Return code: 1 + +[file foo/__init__.py] +[file foo/empty.py] +[file bar.py] +from foo.empty import * +a = 1 # type: ignore + +[case testPossiblyUndefinedVarsPreservedAfterUpdate] +-- Regression test for https://github.com/python/mypy/issues/9655 +$ dmypy start -- --enable-error-code possibly-undefined --no-error-summary +Daemon started +$ dmypy check -- bar.py +bar.py:4: error: Name "a" may be undefined [possibly-undefined] +== Return code: 1 +$ dmypy check -- bar.py +bar.py:4: error: Name "a" may be undefined [possibly-undefined] +== Return code: 1 + +[file foo/__init__.py] +[file foo/empty.py] +[file bar.py] +from foo.empty import * +if False: + a = 1 +a