diff --git a/scripts/generate_readme.py b/scripts/generate_readme.py index c6a3b2143..0f5476db2 100644 --- a/scripts/generate_readme.py +++ b/scripts/generate_readme.py @@ -219,13 +219,16 @@ def platform_coverages( except FileNotFoundError as exc: print(f" {name}: skipped ({exc})", file=sys.stderr) COVERAGE_CACHE_DIR.mkdir(parents=True, exist_ok=True) - for stale in COVERAGE_CACHE_DIR.glob("*.pickle"): - stale.unlink() scratch = cache.with_suffix(f".{os.getpid()}.tmp") with scratch.open("wb") as handle: pickle.dump({"platforms": names, "coverages": coverages}, handle, protocol=pickle.HIGHEST_PROTOCOL) scratch.replace(cache) + # generate_site and generate_readme both purge here. One unlinking + # what the other had just listed ended it on FileNotFoundError. + for stale in COVERAGE_CACHE_DIR.glob("*.pickle"): + if stale != cache: + stale.unlink(missing_ok=True) ordered = {name: coverages[name] for name in platform_names if name in coverages} if report: for name in names: diff --git a/tests/test_coverage_cache.py b/tests/test_coverage_cache.py index 95f7a99d8..8c2b56175 100644 --- a/tests/test_coverage_cache.py +++ b/tests/test_coverage_cache.py @@ -95,6 +95,23 @@ class CoverageCache(unittest.TestCase): self._run() self.assertEqual(len(list((self.work / "cache").glob("*.pickle"))), 1) + def test_a_purge_racing_another_generator_does_not_fail(self): + """generate_site and generate_readme purge the same directory: one + unlinking a pickle the other had listed ended on FileNotFoundError.""" + cache_dir = self.work / "cache" + cache_dir.mkdir() + ghost = cache_dir / "gone.pickle" + real_glob = Path.glob + + def listing_a_vanished_file(path, pattern): + found = list(real_glob(path, pattern)) + return [*found, ghost] if path == cache_dir else found + + with mock.patch.object(Path, "glob", listing_a_vanished_file): + coverages = self._run() + self.assertEqual(sorted(coverages), ["alpha", "beta"]) + self.assertEqual(len(list(cache_dir.glob("*.pickle"))), 1) + def test_a_missing_input_directory_stops_the_run(self): """A missing --emulators-dir skipped every platform as if it had no YAML, then replaced the cache with the empty result."""