Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b46a179

Browse files
committed
Update importlib.invalidate_caches() to be more general.
1 parent 9a4d7dd commit b46a179

5 files changed

Lines changed: 62 additions & 38 deletions

File tree

Doc/library/importlib.rst

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,12 @@ Functions
8888

8989
.. function:: invalidate_caches()
9090

91-
Invalidate importlib's internal caches. Calling this function may be
92-
needed if some modules are installed while your program is running and
93-
you expect the program to notice the changes.
91+
Invalidate the internal caches of the finders stored at
92+
:data:`sys.path_importer_cache`. If a finder implements
93+
:meth:`abc.Finder.invalidate_caches()` then it will be called to perform the
94+
invalidation. This function may be needed if some modules are installed
95+
while your program is running and you expect the program to notice the
96+
changes.
9497

9598
.. versionadded:: 3.3
9699

@@ -119,6 +122,12 @@ are also provided to help in implementing the core ABCs.
119122
be the value of :attr:`__path__` from the parent package. If a loader
120123
cannot be found, ``None`` is returned.
121124

125+
.. method:: invalidate_caches()
126+
127+
An optional method which, when called, should invalidate any internal
128+
cache used by the finder. Used by :func:`invalidate_caches()` when
129+
invalidating the caches of all cached finders.
130+
122131

123132
.. class:: Loader
124133

Lib/importlib/__init__.py

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,4 @@
1-
"""A pure Python implementation of import.
2-
3-
References on import:
4-
5-
* Language reference
6-
http://docs.python.org/ref/import.html
7-
* __import__ function
8-
http://docs.python.org/lib/built-in-funcs.html
9-
* Packages
10-
http://www.python.org/doc/essays/packages.html
11-
* PEP 235: Import on Case-Insensitive Platforms
12-
http://www.python.org/dev/peps/pep-0235
13-
* PEP 275: Import Modules from Zip Archives
14-
http://www.python.org/dev/peps/pep-0273
15-
* PEP 302: New Import Hooks
16-
http://www.python.org/dev/peps/pep-0302/
17-
* PEP 328: Imports: Multi-line and Absolute/Relative
18-
http://www.python.org/dev/peps/pep-0328
19-
20-
"""
1+
"""A pure Python implementation of import."""
212
__all__ = ['__import__', 'import_module', 'invalidate_caches']
223

234
from . import _bootstrap
@@ -37,7 +18,15 @@
3718

3819
# Public API #########################################################
3920

40-
from ._bootstrap import __import__, invalidate_caches
21+
from ._bootstrap import __import__
22+
23+
24+
def invalidate_caches():
25+
"""Call the invalidate_caches() method on all finders stored in
26+
sys.path_importer_caches (where implemented)."""
27+
for finder in sys.path_importer_cache.values():
28+
if hasattr(finder, 'invalidate_caches'):
29+
finder.invalidate_caches()
4130

4231

4332
def import_module(name, package=None):

Lib/importlib/_bootstrap.py

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -160,17 +160,6 @@ def _wrap(new, old):
160160

161161
# Finder/loader utility code ##################################################
162162

163-
_cache_refresh = 0
164-
165-
def invalidate_caches():
166-
"""Invalidate importlib's internal caches.
167-
168-
Calling this function may be needed if some modules are installed while
169-
your program is running and you expect the program to notice the changes.
170-
"""
171-
global _cache_refresh
172-
_cache_refresh += 1
173-
174163

175164
def set_package(fxn):
176165
"""Set __package__ on the returned module."""
@@ -768,7 +757,10 @@ def __init__(self, path, *details):
768757
self._path_mtime = -1
769758
self._path_cache = set()
770759
self._relaxed_path_cache = set()
771-
self._cache_refresh = 0
760+
761+
def invalidate_caches(self):
762+
"""Invalidate the directory mtime."""
763+
self._path_mtime = -1
772764

773765
def find_module(self, fullname):
774766
"""Try to find a loader for the specified module."""
@@ -777,10 +769,9 @@ def find_module(self, fullname):
777769
mtime = _os.stat(self.path).st_mtime
778770
except OSError:
779771
mtime = -1
780-
if mtime != self._path_mtime or _cache_refresh != self._cache_refresh:
772+
if mtime != self._path_mtime:
781773
self._fill_cache()
782774
self._path_mtime = mtime
783-
self._cache_refresh = _cache_refresh
784775
# tail_module keeps the original casing, for __file__ and friends
785776
if _relax_case():
786777
cache = self._relaxed_path_cache

Lib/importlib/test/source/test_finder.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,13 @@ def test_empty_string_for_dir(self):
143143
finally:
144144
os.unlink('mod.py')
145145

146+
def test_invalidate_caches(self):
147+
# invalidate_caches() should reset the mtime.
148+
finder = _bootstrap._FileFinder('', _bootstrap._SourceFinderDetails())
149+
finder._path_mtime = 42
150+
finder.invalidate_caches()
151+
self.assertEqual(finder._path_mtime, -1)
152+
146153

147154
def test_main():
148155
from test.support import run_unittest

Lib/importlib/test/test_api.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,34 @@ def load_b():
8484
importlib.import_module('a.b')
8585
self.assertEqual(b_load_count, 1)
8686

87+
88+
class InvalidateCacheTests(unittest.TestCase):
89+
90+
def test_method_called(self):
91+
# If defined the method should be called.
92+
class InvalidatingNullFinder:
93+
def __init__(self, *ignored):
94+
self.called = False
95+
def find_module(self, *args):
96+
return None
97+
def invalidate_caches(self):
98+
self.called = True
99+
100+
key = 'gobledeegook'
101+
ins = InvalidatingNullFinder()
102+
sys.path_importer_cache[key] = ins
103+
self.addCleanup(lambda: sys.path_importer_cache.__delitem__(key))
104+
importlib.invalidate_caches()
105+
self.assertTrue(ins.called)
106+
107+
def test_method_lacking(self):
108+
# There should be no issues if the method is not defined.
109+
key = 'gobbledeegook'
110+
sys.path_importer_cache[key] = imp.NullImporter('abc')
111+
self.addCleanup(lambda: sys.path_importer_cache.__delitem__(key))
112+
importlib.invalidate_caches() # Shouldn't trigger an exception.
113+
114+
87115
def test_main():
88116
from test.support import run_unittest
89117
run_unittest(ImportModuleTests)

0 commit comments

Comments
 (0)