Skip to content

[WIP] When a module has errors but the interface hash is the same, keep the cache #4353

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 27 additions & 5 deletions mypy/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -1139,6 +1139,20 @@ def compute_hash(text: str) -> str:
return hashlib.md5(text.encode('utf-8')).hexdigest()


def compute_interface_hash(tree: MypyFile, manager: BuildManager) -> str:
"""Compute interface hash for a tree.

Should be called when we want to interface hash but don't want to
write the cache.
"""
data = tree.serialize()
if manager.options.debug_cache:
data_str = json.dumps(data, indent=2, sort_keys=True)
else:
data_str = json.dumps(data, sort_keys=True)
return compute_hash(data_str)


def write_cache(id: str, path: str, tree: MypyFile,
dependencies: List[str], suppressed: List[str],
child_modules: List[str], dep_prios: List[int],
Expand Down Expand Up @@ -1947,15 +1961,23 @@ def write_cache(self) -> None:
assert self.tree is not None, "Internal error: method must be called on parsed file only"
if not self.path or self.options.cache_dir == os.devnull:
return
is_errors_for_file = self.manager.errors.is_errors_for_file(self.path)
if self.manager.options.quick_and_dirty:
is_errors = self.manager.errors.is_errors_for_file(self.path)
is_errors = is_errors_for_file
else:
is_errors = self.transitive_error
if is_errors:
delete_cache(self.id, self.path, self.manager)
self.meta = None
self.mark_interface_stale(on_errors=True)
return
new_interface_hash = compute_interface_hash(self.tree, self.manager)
if new_interface_hash != self.interface_hash:
delete_cache(self.id, self.path, self.manager)
self.meta = None
self.mark_interface_stale(on_errors=True)
self.interface_hash = new_interface_hash
return
if is_errors_for_file:
delete_cache(self.id, self.path, self.manager)
self.meta = None
return
dep_prios = self.dependency_priorities()
new_interface_hash, self.meta = write_cache(
self.id, self.path, self.tree,
Expand Down
2 changes: 1 addition & 1 deletion test-data/unit/check-incremental.test
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ def foo() -> int:
return "foo"
return inner2()

[rechecked mod1, mod2]
[rechecked mod2]
[stale]
[out2]
tmp/mod2.py:4: error: Incompatible return value type (got "str", expected "int")
Expand Down