From 264715e1fdcc9e8df2bbdff1168b68725864c01b Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Wed, 19 Apr 2017 14:51:30 -0700 Subject: [PATCH] Always write the cache (unless cache_dir is /dev/null) (#3133) --- mypy/build.py | 59 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/mypy/build.py b/mypy/build.py index 682fa1e00398..5ab87ab323f0 100644 --- a/mypy/build.py +++ b/mypy/build.py @@ -860,8 +860,7 @@ def write_cache(id: str, path: str, tree: MypyFile, # Make sure directory for cache files exists parent = os.path.dirname(data_json) - if not os.path.isdir(parent): - os.makedirs(parent) + os.makedirs(parent, exist_ok=True) assert os.path.dirname(meta_json) == parent # Construct temp file names @@ -877,6 +876,20 @@ def write_cache(id: str, path: str, tree: MypyFile, data_str = json.dumps(data, sort_keys=True) interface_hash = compute_hash(data_str) + # Obtain and set up metadata + try: + st = manager.get_stat(path) + except OSError as err: + manager.log("Cannot get stat for {}: {}".format(path, err)) + # Remove apparently-invalid cache files. + for filename in [data_json, meta_json]: + try: + os.remove(filename) + except OSError: + pass + # Still return the interface hash we computed. + return interface_hash + # Write data cache file, if applicable if old_interface_hash == interface_hash: # If the interface is unchanged, the cached data is guaranteed @@ -891,8 +904,6 @@ def write_cache(id: str, path: str, tree: MypyFile, os.replace(data_json_tmp, data_json) manager.trace("Interface for {} has changed".format(id)) - # Obtain and set up metadata - st = manager.get_stat(path) # TODO: Handle errors mtime = st.st_mtime size = st.st_size options = manager.options.clone_for_module(id) @@ -1524,26 +1535,26 @@ def valid_references(self) -> Set[str]: return valid_refs def write_cache(self) -> None: - ok = self.path and self.options.incremental - if ok: - if self.manager.options.quick_and_dirty: - is_errors = self.manager.errors.is_errors_for_file(self.path) - else: - is_errors = self.manager.errors.is_errors() - ok = not is_errors - if ok: - dep_prios = [self.priorities.get(dep, PRI_HIGH) for dep in self.dependencies] - new_interface_hash = write_cache( - self.id, self.path, self.tree, - list(self.dependencies), list(self.suppressed), list(self.child_modules), - dep_prios, self.interface_hash, - self.manager) - if new_interface_hash == self.interface_hash: - self.manager.log("Cached module {} has same interface".format(self.id)) - else: - self.manager.log("Cached module {} has changed interface".format(self.id)) - self.mark_interface_stale() - self.interface_hash = new_interface_hash + if not self.path or self.options.cache_dir == os.devnull: + return + if self.manager.options.quick_and_dirty: + is_errors = self.manager.errors.is_errors_for_file(self.path) + else: + is_errors = self.manager.errors.is_errors() + if is_errors: + return + dep_prios = [self.priorities.get(dep, PRI_HIGH) for dep in self.dependencies] + new_interface_hash = write_cache( + self.id, self.path, self.tree, + list(self.dependencies), list(self.suppressed), list(self.child_modules), + dep_prios, self.interface_hash, + self.manager) + if new_interface_hash == self.interface_hash: + self.manager.log("Cached module {} has same interface".format(self.id)) + else: + self.manager.log("Cached module {} has changed interface".format(self.id)) + self.mark_interface_stale() + self.interface_hash = new_interface_hash def dispatch(sources: List[BuildSource], manager: BuildManager) -> Graph: