Skip to content

Commit 1ba23f1

Browse files
authored
Traverse module ancestors when traversing reachable graph nodes during dmypy update (#18906)
Fixes #18396. Fixes #17652. Hopefully fixes #15486 (but not enough info to reproduce the original problem). See discussion in #18396. This PR forces collecting all ancestors of all modules during dep graph traversal in incremental update. Ancestors are included in `load_graph`, which means not traversing them during update results in some modules being erroneously treated as deleted: https://github.com/python/mypy/blob/a4e79ea19506948fd43bf5c14bbf8e2a0ad7158a/mypy/build.py#L3141-L3146
1 parent 54975a0 commit 1ba23f1

File tree

2 files changed

+29
-3
lines changed

2 files changed

+29
-3
lines changed

mypy/dmypy_server.py

+11-3
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,9 @@ def fine_grained_increment_follow_imports(
620620
t1 = time.time()
621621
manager.log(f"fine-grained increment: find_changed: {t1 - t0:.3f}s")
622622

623+
# Track all modules encountered so far. New entries for all dependencies
624+
# are added below by other module finding methods below. All dependencies
625+
# in graph but not in `seen` are considered deleted at the end of this method.
623626
seen = {source.module for source in sources}
624627

625628
# Find changed modules reachable from roots (or in roots) already in graph.
@@ -736,7 +739,9 @@ def find_reachable_changed_modules(
736739
Args:
737740
roots: modules where to start search from
738741
graph: module graph to use for the search
739-
seen: modules we've seen before that won't be visited (mutated here!!)
742+
seen: modules we've seen before that won't be visited (mutated here!!).
743+
Needed to accumulate all modules encountered during update and remove
744+
everything that no longer exists.
740745
changed_paths: which paths have changed (stop search here and return any found)
741746
742747
Return (encountered reachable changed modules,
@@ -756,7 +761,8 @@ def find_reachable_changed_modules(
756761
changed.append((nxt.module, nxt.path))
757762
elif nxt.module in graph:
758763
state = graph[nxt.module]
759-
for dep in state.dependencies:
764+
ancestors = state.ancestors or []
765+
for dep in state.dependencies + ancestors:
760766
if dep not in seen:
761767
seen.add(dep)
762768
worklist.append(BuildSource(graph[dep].path, graph[dep].id, followed=True))
@@ -775,7 +781,9 @@ def find_added_suppressed(
775781
"""Find suppressed modules that have been added (and not included in seen).
776782
777783
Args:
778-
seen: reachable modules we've seen before (mutated here!!)
784+
seen: reachable modules we've seen before (mutated here!!).
785+
Needed to accumulate all modules encountered during update and remove
786+
everything that no longer exists.
779787
780788
Return suppressed, added modules.
781789
"""

test-data/unit/daemon.test

+18
Original file line numberDiff line numberDiff line change
@@ -647,3 +647,21 @@ b: str
647647
from demo.test import a
648648
[file demo/test.py]
649649
a: int
650+
651+
[case testDaemonImportAncestors]
652+
$ dmypy run test.py
653+
Daemon started
654+
test.py:2: error: Unsupported operand types for + ("int" and "str") [operator]
655+
Found 1 error in 1 file (checked 1 source file)
656+
== Return code: 1
657+
$ dmypy run test.py
658+
test.py:2: error: Unsupported operand types for + ("int" and "str") [operator]
659+
Found 1 error in 1 file (checked 1 source file)
660+
== Return code: 1
661+
$ dmypy run test.py
662+
test.py:2: error: Unsupported operand types for + ("int" and "str") [operator]
663+
Found 1 error in 1 file (checked 1 source file)
664+
== Return code: 1
665+
[file test.py]
666+
from xml.etree.ElementTree import Element
667+
1 + 'a'

0 commit comments

Comments
 (0)