114114Major todo items:
115115
116116- Fully support multiple type checking passes
117- - Use mypy.fscache to access file system
118117"""
119118
119+ import os
120120import time
121121import os .path
122122from typing import (
123123 Dict , List , Set , Tuple , Iterable , Union , Optional , Mapping , NamedTuple , Callable
124124)
125125
126126from mypy .build import (
127- BuildManager , State , BuildSource , Graph , load_graph , find_module_clear_caches ,
127+ BuildManager , State , BuildSource , BuildResult , Graph , load_graph ,
128128 PRI_INDIRECT , DEBUG_FINE_GRAINED ,
129129)
130130from mypy .checker import DeferredNode
135135)
136136from mypy .options import Options
137137from mypy .types import Type
138+ from mypy .fscache import FileSystemCache
138139from mypy .semanal import apply_semantic_analyzer_patches
139140from mypy .server .astdiff import (
140141 snapshot_symbol_table , compare_symbol_table_snapshots , SnapshotItem
150151
151152
152153class FineGrainedBuildManager :
153- def __init__ (self ,
154- manager : BuildManager ,
155- graph : Graph ) -> None :
154+ def __init__ (self , result : BuildResult ) -> None :
156155 """Initialize fine-grained build based on a batch build.
157156
158157 Args:
158+ result: Result from the initialized build.
159+ The manager and graph will be taken over by this class.
159160 manager: State of the build (mutated by this class)
160161 graph: Additional state of the build (only read to initialize state)
161162 """
163+ manager = result .manager
162164 self .manager = manager
165+ self .graph = result .graph
163166 self .options = manager .options
164167 self .previous_modules = get_module_to_path_map (manager )
165- self .deps = get_all_dependencies (manager , graph , self .options )
168+ self .deps = get_all_dependencies (manager , self . graph , self .options )
166169 self .previous_targets_with_errors = manager .errors .targets ()
167- self .graph = graph
170+ self .previous_messages = result . errors [:]
168171 # Module, if any, that had blocking errors in the last run as (id, path) tuple.
169172 # TODO: Handle blocking errors in the initial build
170173 self .blocking_error = None # type: Optional[Tuple[str, str]]
@@ -205,13 +208,15 @@ def update(self,
205208 A list of errors.
206209 """
207210 changed_modules = changed_modules + removed_modules
208- assert changed_modules or removed_modules , 'No changed modules'
209-
210211 removed_set = {module for module , _ in removed_modules }
211212 self .changed_modules = changed_modules
212213
213- # Reset global caches for the new build.
214- find_module_clear_caches ()
214+ if not changed_modules :
215+ self .manager .fscache .flush ()
216+ return self .previous_messages
217+
218+ # Reset find_module's caches for the new build.
219+ self .manager .find_module_cache .clear ()
215220
216221 self .triggered = []
217222 self .updated_modules = []
@@ -249,8 +254,10 @@ def update(self,
249254 if blocker :
250255 self .blocking_error = (next_id , next_path )
251256 self .stale = changed_modules
252- return messages
257+ break
253258
259+ self .manager .fscache .flush ()
260+ self .previous_messages = messages [:]
254261 return messages
255262
256263 def update_single (self ,
@@ -383,7 +390,7 @@ def update_single_isolated(module: str,
383390 manager .log_fine_grained ('new module %r' % module )
384391
385392 old_modules = dict (manager .modules )
386- sources = get_sources (previous_modules , [(module , path )])
393+ sources = get_sources (manager . fscache , previous_modules , [(module , path )])
387394
388395 if module in manager .missing_modules :
389396 manager .missing_modules .remove (module )
@@ -407,7 +414,7 @@ def update_single_isolated(module: str,
407414 remaining_modules = []
408415 return BlockedUpdate (err .module_with_blocker , path , remaining_modules , err .messages )
409416
410- if not os . path .isfile (path ) or force_removed :
417+ if not manager . fscache .isfile (path ) or force_removed :
411418 delete_module (module , graph , manager )
412419 return NormalUpdate (module , path , [], None )
413420
@@ -537,13 +544,12 @@ def get_module_to_path_map(manager: BuildManager) -> Dict[str, str]:
537544 for module , node in manager .modules .items ()}
538545
539546
540- def get_sources (modules : Dict [str , str ],
547+ def get_sources (fscache : FileSystemCache ,
548+ modules : Dict [str , str ],
541549 changed_modules : List [Tuple [str , str ]]) -> List [BuildSource ]:
542- # TODO: Race condition when reading from the file system; we should only read each
543- # bit of external state once during a build to have a consistent view of the world
544550 sources = []
545551 for id , path in changed_modules :
546- if os . path .isfile (path ):
552+ if fscache .isfile (path ):
547553 sources .append (BuildSource (path , id , None ))
548554 return sources
549555
0 commit comments