Skip to content

Commit

Permalink
Fix disappearing errors when re-running dmypy check (#14835)
Browse files Browse the repository at this point in the history
This adds a commit which fixes issue
#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".

<!-- If this pull request fixes an issue, add "Fixes #NNN" with the
issue number. -->


<!--
Checklist:
- Read the [Contributing
Guidelines](https://github.com/python/mypy/blob/master/CONTRIBUTING.md)
- Add tests for all changed behaviour.
- If you can't add a test, please explain why and how you verified your
changes work.
- Make sure CI passes.
- Please do not force push to the PR once it has been reviewed.
-->

---------

Co-authored-by: AlexWaygood <alex.waygood@gmail.com>
  • Loading branch information
meshy and AlexWaygood authored Apr 9, 2023
1 parent e21ddbf commit a9ee618
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 0 deletions.
4 changes: 4 additions & 0 deletions mypy/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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)

Expand Down
6 changes: 6 additions & 0 deletions mypy/server/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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())

Expand Down
89 changes: 89 additions & 0 deletions test-data/unit/daemon.test
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit a9ee618

Please sign in to comment.