diff --git a/Doc/library/filecmp.rst b/Doc/library/filecmp.rst index 95c4ddf2671..8471a726307 100644 --- a/Doc/library/filecmp.rst +++ b/Doc/library/filecmp.rst @@ -27,6 +27,10 @@ The :mod:`filecmp` module defines the following functions: Note that no external programs are called from this function, giving it portability and efficiency. + This function uses a cache for past comparisons and the results, + with a cache invalidation mechanism relying on stale signatures + or by explicitly calling :func:`clear_cache`. + .. function:: cmpfiles(dir1, dir2, common, shallow=True) @@ -48,6 +52,15 @@ The :mod:`filecmp` module defines the following functions: one of the three returned lists. +.. function:: clear_cache() + + .. versionadded:: 3.4 + + Clear the filecmp cache. This may be useful if a file is compared so quickly + after it is modified that it is within the mtime resolution of + the underlying filesystem. + + .. _dircmp-objects: The :class:`dircmp` class diff --git a/Lib/filecmp.py b/Lib/filecmp.py index 014c0d097a4..328528871ad 100644 --- a/Lib/filecmp.py +++ b/Lib/filecmp.py @@ -6,6 +6,7 @@ Classes: Functions: cmp(f1, f2, shallow=True) -> int cmpfiles(a, b, common) -> ([], [], []) + clear_cache() """ @@ -13,7 +14,7 @@ import os import stat from itertools import filterfalse -__all__ = ['cmp', 'dircmp', 'cmpfiles', 'DEFAULT_IGNORES'] +__all__ = ['clear_cache', 'cmp', 'dircmp', 'cmpfiles', 'DEFAULT_IGNORES'] _cache = {} BUFSIZE = 8*1024 @@ -21,6 +22,9 @@ BUFSIZE = 8*1024 DEFAULT_IGNORES = [ 'RCS', 'CVS', 'tags', '.git', '.hg', '.bzr', '_darcs', '__pycache__'] +def clear_cache(): + """Clear the filecmp cache.""" + _cache.clear() def cmp(f1, f2, shallow=True): """Compare two files. @@ -39,7 +43,8 @@ def cmp(f1, f2, shallow=True): True if the files are the same, False otherwise. This function uses a cache for past comparisons and the results, - with a cache invalidation mechanism relying on stale signatures. + with a cache invalidation mechanism relying on stale signatures + or by explicitly calling clear_cache(). """ @@ -56,7 +61,7 @@ def cmp(f1, f2, shallow=True): if outcome is None: outcome = _do_cmp(f1, f2) if len(_cache) > 100: # limit the maximum size of the cache - _cache.clear() + clear_cache() _cache[f1, f2, s1, s2] = outcome return outcome diff --git a/Lib/test/test_filecmp.py b/Lib/test/test_filecmp.py index f7601470163..c7cb3fcf367 100644 --- a/Lib/test/test_filecmp.py +++ b/Lib/test/test_filecmp.py @@ -39,6 +39,13 @@ class FileCompareTestCase(unittest.TestCase): self.assertFalse(filecmp.cmp(self.name, self.dir), "File and directory compare as equal") + def test_cache_clear(self): + first_compare = filecmp.cmp(self.name, self.name_same, shallow=False) + second_compare = filecmp.cmp(self.name, self.name_diff, shallow=False) + filecmp.clear_cache() + self.assertTrue(len(filecmp._cache) == 0, + "Cache not cleared after calling clear_cache") + class DirCompareTestCase(unittest.TestCase): def setUp(self): tmpdir = tempfile.gettempdir() diff --git a/Misc/ACKS b/Misc/ACKS index bff2f3c3e87..ec8d94f611a 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -738,6 +738,7 @@ Benno Leslie Christopher Tur Lesniewski-Laas Alain Leufroy Mark Levinson +Mark Levitt William Lewis Akira Li Xuanji Li diff --git a/Misc/NEWS b/Misc/NEWS index 1fcb9c9cf59..ebb3f69fa8c 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -123,6 +123,9 @@ Core and Builtins Library ------- +- Issue #18149: Add filecmp.clear_cache() to manually clear the filecmp cache. + Patch by Mark Levitt + - Issue #18193: Add importlib.reload(). - Issue #18157: Stop using imp.load_module() in pydoc.