mirror of
https://github.com/python/cpython.git
synced 2025-08-02 08:02:56 +00:00
Update importlib.invalidate_caches() to be more general.
This commit is contained in:
parent
9a4d7ddb6c
commit
b46a1793a7
5 changed files with 62 additions and 38 deletions
|
@ -88,9 +88,12 @@ Functions
|
|||
|
||||
.. function:: invalidate_caches()
|
||||
|
||||
Invalidate importlib's internal caches. Calling this function may be
|
||||
needed if some modules are installed while your program is running and
|
||||
you expect the program to notice the changes.
|
||||
Invalidate the internal caches of the finders stored at
|
||||
:data:`sys.path_importer_cache`. If a finder implements
|
||||
:meth:`abc.Finder.invalidate_caches()` then it will be called to perform the
|
||||
invalidation. This function may be needed if some modules are installed
|
||||
while your program is running and you expect the program to notice the
|
||||
changes.
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
|
@ -119,6 +122,12 @@ are also provided to help in implementing the core ABCs.
|
|||
be the value of :attr:`__path__` from the parent package. If a loader
|
||||
cannot be found, ``None`` is returned.
|
||||
|
||||
.. method:: invalidate_caches()
|
||||
|
||||
An optional method which, when called, should invalidate any internal
|
||||
cache used by the finder. Used by :func:`invalidate_caches()` when
|
||||
invalidating the caches of all cached finders.
|
||||
|
||||
|
||||
.. class:: Loader
|
||||
|
||||
|
|
|
@ -1,23 +1,4 @@
|
|||
"""A pure Python implementation of import.
|
||||
|
||||
References on import:
|
||||
|
||||
* Language reference
|
||||
http://docs.python.org/ref/import.html
|
||||
* __import__ function
|
||||
http://docs.python.org/lib/built-in-funcs.html
|
||||
* Packages
|
||||
http://www.python.org/doc/essays/packages.html
|
||||
* PEP 235: Import on Case-Insensitive Platforms
|
||||
http://www.python.org/dev/peps/pep-0235
|
||||
* PEP 275: Import Modules from Zip Archives
|
||||
http://www.python.org/dev/peps/pep-0273
|
||||
* PEP 302: New Import Hooks
|
||||
http://www.python.org/dev/peps/pep-0302/
|
||||
* PEP 328: Imports: Multi-line and Absolute/Relative
|
||||
http://www.python.org/dev/peps/pep-0328
|
||||
|
||||
"""
|
||||
"""A pure Python implementation of import."""
|
||||
__all__ = ['__import__', 'import_module', 'invalidate_caches']
|
||||
|
||||
from . import _bootstrap
|
||||
|
@ -37,7 +18,15 @@ _bootstrap._setup(sys, imp)
|
|||
|
||||
# Public API #########################################################
|
||||
|
||||
from ._bootstrap import __import__, invalidate_caches
|
||||
from ._bootstrap import __import__
|
||||
|
||||
|
||||
def invalidate_caches():
|
||||
"""Call the invalidate_caches() method on all finders stored in
|
||||
sys.path_importer_caches (where implemented)."""
|
||||
for finder in sys.path_importer_cache.values():
|
||||
if hasattr(finder, 'invalidate_caches'):
|
||||
finder.invalidate_caches()
|
||||
|
||||
|
||||
def import_module(name, package=None):
|
||||
|
|
|
@ -160,17 +160,6 @@ code_type = type(_wrap.__code__)
|
|||
|
||||
# Finder/loader utility code ##################################################
|
||||
|
||||
_cache_refresh = 0
|
||||
|
||||
def invalidate_caches():
|
||||
"""Invalidate importlib's internal caches.
|
||||
|
||||
Calling this function may be needed if some modules are installed while
|
||||
your program is running and you expect the program to notice the changes.
|
||||
"""
|
||||
global _cache_refresh
|
||||
_cache_refresh += 1
|
||||
|
||||
|
||||
def set_package(fxn):
|
||||
"""Set __package__ on the returned module."""
|
||||
|
@ -768,7 +757,10 @@ class _FileFinder:
|
|||
self._path_mtime = -1
|
||||
self._path_cache = set()
|
||||
self._relaxed_path_cache = set()
|
||||
self._cache_refresh = 0
|
||||
|
||||
def invalidate_caches(self):
|
||||
"""Invalidate the directory mtime."""
|
||||
self._path_mtime = -1
|
||||
|
||||
def find_module(self, fullname):
|
||||
"""Try to find a loader for the specified module."""
|
||||
|
@ -777,10 +769,9 @@ class _FileFinder:
|
|||
mtime = _os.stat(self.path).st_mtime
|
||||
except OSError:
|
||||
mtime = -1
|
||||
if mtime != self._path_mtime or _cache_refresh != self._cache_refresh:
|
||||
if mtime != self._path_mtime:
|
||||
self._fill_cache()
|
||||
self._path_mtime = mtime
|
||||
self._cache_refresh = _cache_refresh
|
||||
# tail_module keeps the original casing, for __file__ and friends
|
||||
if _relax_case():
|
||||
cache = self._relaxed_path_cache
|
||||
|
|
|
@ -143,6 +143,13 @@ class FinderTests(abc.FinderTests):
|
|||
finally:
|
||||
os.unlink('mod.py')
|
||||
|
||||
def test_invalidate_caches(self):
|
||||
# invalidate_caches() should reset the mtime.
|
||||
finder = _bootstrap._FileFinder('', _bootstrap._SourceFinderDetails())
|
||||
finder._path_mtime = 42
|
||||
finder.invalidate_caches()
|
||||
self.assertEqual(finder._path_mtime, -1)
|
||||
|
||||
|
||||
def test_main():
|
||||
from test.support import run_unittest
|
||||
|
|
|
@ -84,6 +84,34 @@ class ImportModuleTests(unittest.TestCase):
|
|||
importlib.import_module('a.b')
|
||||
self.assertEqual(b_load_count, 1)
|
||||
|
||||
|
||||
class InvalidateCacheTests(unittest.TestCase):
|
||||
|
||||
def test_method_called(self):
|
||||
# If defined the method should be called.
|
||||
class InvalidatingNullFinder:
|
||||
def __init__(self, *ignored):
|
||||
self.called = False
|
||||
def find_module(self, *args):
|
||||
return None
|
||||
def invalidate_caches(self):
|
||||
self.called = True
|
||||
|
||||
key = 'gobledeegook'
|
||||
ins = InvalidatingNullFinder()
|
||||
sys.path_importer_cache[key] = ins
|
||||
self.addCleanup(lambda: sys.path_importer_cache.__delitem__(key))
|
||||
importlib.invalidate_caches()
|
||||
self.assertTrue(ins.called)
|
||||
|
||||
def test_method_lacking(self):
|
||||
# There should be no issues if the method is not defined.
|
||||
key = 'gobbledeegook'
|
||||
sys.path_importer_cache[key] = imp.NullImporter('abc')
|
||||
self.addCleanup(lambda: sys.path_importer_cache.__delitem__(key))
|
||||
importlib.invalidate_caches() # Shouldn't trigger an exception.
|
||||
|
||||
|
||||
def test_main():
|
||||
from test.support import run_unittest
|
||||
run_unittest(ImportModuleTests)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue