From 5b0cd60dc0c8d83067c4ed95fe50dfe0145c379b Mon Sep 17 00:00:00 2001 From: dennis Date: Thu, 6 Aug 2026 15:41:24 -0700 Subject: [PATCH 1/2] Fix dmypy traversal of missing graph dependencies Co-Authored-By: Claude Opus 5 (1M context) --- mypy/dmypy_server.py | 8 ++++++-- test-data/unit/daemon.test | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/mypy/dmypy_server.py b/mypy/dmypy_server.py index 066fbf9bed2d6..fe16536fa403d 100644 --- a/mypy/dmypy_server.py +++ b/mypy/dmypy_server.py @@ -769,7 +769,7 @@ def find_reachable_changed_modules( state = graph[nxt.module] ancestors = state.ancestors or [] for dep in state.dependencies + ancestors: - if dep not in seen: + if dep not in seen and dep in graph: seen.add(dep) worklist.append(BuildSource(graph[dep].path, graph[dep].id, followed=True)) return changed, new_files @@ -779,7 +779,11 @@ def direct_imports( ) -> list[BuildSource]: """Return the direct imports of module not included in seen.""" state = graph[module[0]] - return [BuildSource(graph[dep].path, dep, followed=True) for dep in state.dependencies] + return [ + BuildSource(graph[dep].path, dep, followed=True) + for dep in state.dependencies + if dep in graph + ] def find_added_suppressed( self, graph: mypy.build.Graph, seen: set[str], search_paths: SearchPaths diff --git a/test-data/unit/daemon.test b/test-data/unit/daemon.test index 448af5d080029..29046fcbd5a8c 100644 --- a/test-data/unit/daemon.test +++ b/test-data/unit/daemon.test @@ -802,3 +802,37 @@ Found 1 error in 1 file (checked 1 source file) [file test.py] from xml.etree.ElementTree import Element 1 + 'a' + +[case testDaemonRecheckMissingGraphDependency] +$ dmypy start +Daemon started +$ dmypy check src/ +src/pkg/example.py:2: error: Name "x" already defined on line 1 [no-redef] +Found 1 error in 1 file (checked 2 source files) +== Return code: 1 +$ dmypy recheck +src/pkg/example.py:2: error: Incompatible import of "x" (imported name has type "int", local name has type "str") [assignment] +Found 1 error in 1 file (checked 53 source files) +== Return code: 1 +$ dmypy recheck +src/pkg/example.py:2: error: Incompatible import of "x" (imported name has type "int", local name has type "str") [assignment] +Found 1 error in 1 file (checked 53 source files) +== Return code: 1 +[file mypy.ini] +\[mypy] +follow_imports = normal +mypy_path = src +files = src/pkg/ +exclude = (?x)( + \./.* + | tests + ) +\[mypy-pkg.tests.*] +follow_imports = skip +[file src/pkg/__init__.py] +[file src/pkg/example.py] +x = "1" +from pkg.tests.test_something import x +[file src/pkg/tests/__init__.py] +[file src/pkg/tests/test_something.py] +x = 1 From 7e0ac76c25aed1779c26908a67abddfa61832ed0 Mon Sep 17 00:00:00 2001 From: dennis Date: Thu, 6 Aug 2026 15:53:42 -0700 Subject: [PATCH 2/2] Avoid typeshed-dependent file count in daemon regression test The "checked N source files" summary line varies with the bundled typeshed version, which would make the test fail spuriously after a typeshed sync. Start the daemon with --no-error-summary so the test asserts only on the diagnostics that the fix actually affects. Co-Authored-By: Claude Opus 5 (1M context) --- test-data/unit/daemon.test | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test-data/unit/daemon.test b/test-data/unit/daemon.test index 29046fcbd5a8c..5fb4eaca55d88 100644 --- a/test-data/unit/daemon.test +++ b/test-data/unit/daemon.test @@ -804,19 +804,18 @@ from xml.etree.ElementTree import Element 1 + 'a' [case testDaemonRecheckMissingGraphDependency] -$ dmypy start +-- Dropping pkg.tests from the graph leaves a stale ancestors edge behind, which +-- a later recheck used to dereference unconditionally (KeyError: 'pkg.tests'). +$ dmypy start -- --no-error-summary Daemon started $ dmypy check src/ src/pkg/example.py:2: error: Name "x" already defined on line 1 [no-redef] -Found 1 error in 1 file (checked 2 source files) == Return code: 1 $ dmypy recheck src/pkg/example.py:2: error: Incompatible import of "x" (imported name has type "int", local name has type "str") [assignment] -Found 1 error in 1 file (checked 53 source files) == Return code: 1 $ dmypy recheck src/pkg/example.py:2: error: Incompatible import of "x" (imported name has type "int", local name has type "str") [assignment] -Found 1 error in 1 file (checked 53 source files) == Return code: 1 [file mypy.ini] \[mypy]