Skip to content

Commit 250eafe

Browse files
authored
Load .data.json files on-demand in fine-grained mode (#4910)
1 parent f63ccbb commit 250eafe

File tree

5 files changed

+193
-110
lines changed

5 files changed

+193
-110
lines changed

mypy/build.py

Lines changed: 26 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -692,23 +692,17 @@ def correct_rel_imp(imp: Union[ImportFrom, ImportAll]) -> str:
692692
elif isinstance(imp, ImportFrom):
693693
cur_id = correct_rel_imp(imp)
694694
pos = len(res)
695-
all_are_submodules = True
696695
# Also add any imported names that are submodules.
697696
pri = import_priority(imp, PRI_MED)
698697
for name, __ in imp.names:
699698
sub_id = cur_id + '.' + name
700699
if self.is_module(sub_id):
701700
res.append((pri, sub_id, imp.line))
702-
else:
703-
all_are_submodules = False
704-
# If all imported names are submodules, don't add
705-
# cur_id as a dependency. Otherwise (i.e., if at
706-
# least one imported name isn't a submodule)
707-
# cur_id is also a dependency, and we should
708-
# insert it *before* any submodules.
709-
if not all_are_submodules:
710-
pri = import_priority(imp, PRI_HIGH)
711-
res.insert(pos, ((pri, cur_id, imp.line)))
701+
# Add cur_id as a dependency, even if all of the
702+
# imports are submodules. Processing import from will try
703+
# to look through cur_id, so we should depend on it.
704+
pri = import_priority(imp, PRI_HIGH)
705+
res.insert(pos, ((pri, cur_id, imp.line)))
712706
elif isinstance(imp, ImportAll):
713707
pri = import_priority(imp, PRI_HIGH)
714708
res.append((pri, correct_rel_imp(imp), imp.line))
@@ -1731,7 +1725,7 @@ def fix_cross_refs(self) -> None:
17311725
# cache load because we need to gracefully handle missing modules.
17321726
fixup_module(self.tree, self.manager.modules,
17331727
self.manager.options.quick_and_dirty or
1734-
self.manager.use_fine_grained_cache())
1728+
self.options.use_fine_grained_cache)
17351729

17361730
def patch_dependency_parents(self) -> None:
17371731
"""
@@ -2322,12 +2316,17 @@ def dump_graph(graph: Graph) -> None:
23222316

23232317

23242318
def load_graph(sources: List[BuildSource], manager: BuildManager,
2325-
old_graph: Optional[Graph] = None) -> Graph:
2319+
old_graph: Optional[Graph] = None,
2320+
new_modules: Optional[List[State]] = None) -> Graph:
23262321
"""Given some source files, load the full dependency graph.
23272322
23282323
If an old_graph is passed in, it is used as the starting point and
23292324
modified during graph loading.
23302325
2326+
If a new_modules is passed in, any modules that are loaded are
2327+
added to the list. This is an argument and not a return value
2328+
so that the caller can access it even if load_graph fails.
2329+
23312330
As this may need to parse files, this can raise CompileError in case
23322331
there are syntax errors.
23332332
"""
@@ -2337,7 +2336,7 @@ def load_graph(sources: List[BuildSource], manager: BuildManager,
23372336
# The deque is used to implement breadth-first traversal.
23382337
# TODO: Consider whether to go depth-first instead. This may
23392338
# affect the order in which we process files within import cycles.
2340-
new = collections.deque() # type: Deque[State]
2339+
new = new_modules if new_modules is not None else []
23412340
entry_points = set() # type: Set[str]
23422341
# Seed the graph with the initial root sources.
23432342
for bs in sources:
@@ -2354,8 +2353,8 @@ def load_graph(sources: List[BuildSource], manager: BuildManager,
23542353
new.append(st)
23552354
entry_points.add(bs.module)
23562355
# Collect dependencies. We go breadth-first.
2357-
while new:
2358-
st = new.popleft()
2356+
# More nodes might get added to new as we go, but that's fine.
2357+
for st in new:
23592358
assert st.ancestors is not None
23602359
# Strip out indirect dependencies. These will be dealt with
23612360
# when they show up as direct dependencies, and there's a
@@ -2534,7 +2533,7 @@ def process_graph(graph: Graph, manager: BuildManager) -> None:
25342533
# TODO: see if it's possible to determine if we need to process only a
25352534
# _subset_ of the past SCCs instead of having to process them all.
25362535
for prev_scc in fresh_scc_queue:
2537-
process_fresh_scc(graph, prev_scc, manager)
2536+
process_fresh_modules(graph, prev_scc, manager)
25382537
fresh_scc_queue = []
25392538
size = len(scc)
25402539
if size == 1:
@@ -2558,21 +2557,10 @@ def process_fine_grained_cache_graph(graph: Graph, manager: BuildManager) -> Non
25582557
"""Finish loading everything for use in the fine-grained incremental cache"""
25592558

25602559
# If we are running in fine-grained incremental mode with caching,
2561-
# we process all SCCs as fresh SCCs so that we have all of the symbol
2562-
# tables and fine-grained dependencies available.
2563-
# We fail the loading of any SCC that we can't load a meta for, so we
2564-
# don't have anything *but* fresh SCCs.
2565-
sccs = sorted_components(graph)
2566-
manager.log("Found %d SCCs; largest has %d nodes" %
2567-
(len(sccs), max(len(scc) for scc in sccs)))
2568-
2569-
for ascc in sccs:
2570-
# Order the SCC's nodes using a heuristic.
2571-
# Note that ascc is a set, and scc is a list.
2572-
scc = order_ascc(graph, ascc)
2573-
process_fresh_scc(graph, scc, manager)
2574-
for id in scc:
2575-
graph[id].load_fine_grained_deps()
2560+
# we don't actually have much to do: just load the fine-grained
2561+
# deps.
2562+
for id, state in graph.items():
2563+
state.load_fine_grained_deps()
25762564

25772565

25782566
def order_ascc(graph: Graph, ascc: AbstractSet[str], pri_max: int = PRI_ALL) -> List[str]:
@@ -2622,16 +2610,17 @@ def order_ascc(graph: Graph, ascc: AbstractSet[str], pri_max: int = PRI_ALL) ->
26222610
return [s for ss in sccs for s in order_ascc(graph, ss, pri_max)]
26232611

26242612

2625-
def process_fresh_scc(graph: Graph, scc: List[str], manager: BuildManager) -> None:
2626-
"""Process the modules in one SCC from their cached data.
2613+
def process_fresh_modules(graph: Graph, modules: List[str], manager: BuildManager) -> None:
2614+
"""Process the modules in one group of modules from their cached data.
26272615
2616+
This can be used to process an SCC of modules
26282617
This involves loading the tree from JSON and then doing various cleanups.
26292618
"""
2630-
for id in scc:
2619+
for id in modules:
26312620
graph[id].load_tree()
2632-
for id in scc:
2621+
for id in modules:
26332622
graph[id].fix_cross_refs()
2634-
for id in scc:
2623+
for id in modules:
26352624
graph[id].patch_dependency_parents()
26362625

26372626

0 commit comments

Comments
 (0)