Skip to content

Commit 5ef0902

Browse files
authored
Fix the exportjson tool (.ff cache to .json conversion) (#21628)
It was broken by lazy cache deserialization, and the tests didn't catch it since the fixup state was persisted within the test. Both fix the exportjson tool and make the test more realistic.
1 parent 8d621ad commit 5ef0902

3 files changed

Lines changed: 23 additions & 2 deletions

File tree

mypy/exportjson.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,12 @@ def convert_symbol_table_node(self: SymbolTableNode, cfg: Config) -> Json:
128128
data["plugin_generated"] = True
129129
if self.cross_ref:
130130
data["cross_ref"] = self.cross_ref
131-
elif self.node is not None:
132-
data["node"] = convert_symbol_node(self.node, cfg)
131+
else:
132+
# Read the raw node without cross-reference fixup, since exportjson reads
133+
# cache files in isolation and no node fixer is available.
134+
node = self.read_node_no_fixup()
135+
if node is not None:
136+
data["node"] = convert_symbol_node(node, cfg)
133137
return data
134138

135139

mypy/nodes.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4952,6 +4952,17 @@ def node(self) -> SymbolNode | None:
49524952
self.unfixed = False
49534953
return self._node
49544954

4955+
def read_node_no_fixup(self) -> SymbolNode | None:
4956+
"""Return the deserialized node without performing cross-reference fixup.
4957+
4958+
This is intended for introspection tools (such as mypy.exportjson) that read
4959+
cache files in isolation, where no node fixer is available.
4960+
"""
4961+
if self._node is None and self._node_bytes:
4962+
self._node = read_symbol(ReadBuffer(self._node_bytes), self._node_tag)
4963+
self._node_bytes = b""
4964+
return self._node
4965+
49554966
def copy(self) -> SymbolTableNode:
49564967
new = SymbolTableNode(
49574968
self.kind, self._node, self.module_public, self.implicit, self.module_hidden

mypy/test/testexportjson.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from mypy.errors import CompileError
1212
from mypy.exportjson import convert_binary_cache_meta_to_json, convert_binary_cache_to_json
1313
from mypy.modulefinder import BuildSource
14+
from mypy.modules_state import modules_state
1415
from mypy.options import Options
1516
from mypy.test.config import test_temp_dir
1617
from mypy.test.data import DataDrivenTestCase, DataSuite
@@ -44,6 +45,11 @@ def run_case(self, testcase: DataDrivenTestCase) -> None:
4445
major, minor = sys.version_info[:2]
4546
cache_dir = os.path.join(".mypy_cache", f"{major}.{minor}")
4647

48+
# Reset the global fixup state, since the exportjson tool
49+
# reads cache files in isolation (no node fixer available).
50+
modules_state.node_fixer = None
51+
modules_state.modules = {}
52+
4753
for module in result.files:
4854
if module in (
4955
"builtins",

0 commit comments

Comments
 (0)