mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
gh-93461: Invalidate sys.path_importer_cache entries with relative paths (GH-93653)
This commit is contained in:
parent
cf730b595e
commit
09243b898a
5 changed files with 36 additions and 14 deletions
|
@ -1399,7 +1399,9 @@ class PathFinder:
|
|||
"""Call the invalidate_caches() method on all path entry finders
|
||||
stored in sys.path_importer_caches (where implemented)."""
|
||||
for name, finder in list(sys.path_importer_cache.items()):
|
||||
if finder is None:
|
||||
# Drop entry if finder name is a relative path. The current
|
||||
# working directory may have changed.
|
||||
if finder is None or not _path_isabs(name):
|
||||
del sys.path_importer_cache[name]
|
||||
elif hasattr(finder, 'invalidate_caches'):
|
||||
finder.invalidate_caches()
|
||||
|
@ -1567,9 +1569,12 @@ class FileFinder:
|
|||
loaders.extend((suffix, loader) for suffix in suffixes)
|
||||
self._loaders = loaders
|
||||
# Base (directory) path
|
||||
self.path = path or '.'
|
||||
if not _path_isabs(self.path):
|
||||
self.path = _path_join(_os.getcwd(), self.path)
|
||||
if not path or path == '.':
|
||||
self.path = _os.getcwd()
|
||||
elif not _path_isabs(path):
|
||||
self.path = _path_join(_os.getcwd(), path)
|
||||
else:
|
||||
self.path = path
|
||||
self._path_mtime = -1
|
||||
self._path_cache = set()
|
||||
self._relaxed_path_cache = set()
|
||||
|
|
|
@ -927,7 +927,7 @@ class PycacheTests(unittest.TestCase):
|
|||
m = __import__(TESTFN)
|
||||
try:
|
||||
self.assertEqual(m.__file__,
|
||||
os.path.join(os.getcwd(), os.curdir, os.path.relpath(pyc_file)))
|
||||
os.path.join(os.getcwd(), os.path.relpath(pyc_file)))
|
||||
finally:
|
||||
os.remove(pyc_file)
|
||||
|
||||
|
@ -935,7 +935,7 @@ class PycacheTests(unittest.TestCase):
|
|||
# Modules now also have an __cached__ that points to the pyc file.
|
||||
m = __import__(TESTFN)
|
||||
pyc_file = importlib.util.cache_from_source(TESTFN + '.py')
|
||||
self.assertEqual(m.__cached__, os.path.join(os.getcwd(), os.curdir, pyc_file))
|
||||
self.assertEqual(m.__cached__, os.path.join(os.getcwd(), pyc_file))
|
||||
|
||||
@skip_if_dont_write_bytecode
|
||||
def test___cached___legacy_pyc(self):
|
||||
|
@ -951,7 +951,7 @@ class PycacheTests(unittest.TestCase):
|
|||
importlib.invalidate_caches()
|
||||
m = __import__(TESTFN)
|
||||
self.assertEqual(m.__cached__,
|
||||
os.path.join(os.getcwd(), os.curdir, os.path.relpath(pyc_file)))
|
||||
os.path.join(os.getcwd(), os.path.relpath(pyc_file)))
|
||||
|
||||
@skip_if_dont_write_bytecode
|
||||
def test_package___cached__(self):
|
||||
|
@ -971,10 +971,10 @@ class PycacheTests(unittest.TestCase):
|
|||
m = __import__('pep3147.foo')
|
||||
init_pyc = importlib.util.cache_from_source(
|
||||
os.path.join('pep3147', '__init__.py'))
|
||||
self.assertEqual(m.__cached__, os.path.join(os.getcwd(), os.curdir, init_pyc))
|
||||
self.assertEqual(m.__cached__, os.path.join(os.getcwd(), init_pyc))
|
||||
foo_pyc = importlib.util.cache_from_source(os.path.join('pep3147', 'foo.py'))
|
||||
self.assertEqual(sys.modules['pep3147.foo'].__cached__,
|
||||
os.path.join(os.getcwd(), os.curdir, foo_pyc))
|
||||
os.path.join(os.getcwd(), foo_pyc))
|
||||
|
||||
def test_package___cached___from_pyc(self):
|
||||
# Like test___cached__ but ensuring __cached__ when imported from a
|
||||
|
@ -998,10 +998,10 @@ class PycacheTests(unittest.TestCase):
|
|||
m = __import__('pep3147.foo')
|
||||
init_pyc = importlib.util.cache_from_source(
|
||||
os.path.join('pep3147', '__init__.py'))
|
||||
self.assertEqual(m.__cached__, os.path.join(os.getcwd(), os.curdir, init_pyc))
|
||||
self.assertEqual(m.__cached__, os.path.join(os.getcwd(), init_pyc))
|
||||
foo_pyc = importlib.util.cache_from_source(os.path.join('pep3147', 'foo.py'))
|
||||
self.assertEqual(sys.modules['pep3147.foo'].__cached__,
|
||||
os.path.join(os.getcwd(), os.curdir, foo_pyc))
|
||||
os.path.join(os.getcwd(), foo_pyc))
|
||||
|
||||
def test_recompute_pyc_same_second(self):
|
||||
# Even when the source file doesn't change timestamp, a change in
|
||||
|
|
|
@ -202,10 +202,11 @@ class FinderTests:
|
|||
def invalidate_caches(self):
|
||||
self.called = True
|
||||
|
||||
cache = {'leave_alone': object(), 'finder_to_invalidate': FakeFinder()}
|
||||
key = os.path.abspath('finder_to_invalidate')
|
||||
cache = {'leave_alone': object(), key: FakeFinder()}
|
||||
with util.import_state(path_importer_cache=cache):
|
||||
self.machinery.PathFinder.invalidate_caches()
|
||||
self.assertTrue(cache['finder_to_invalidate'].called)
|
||||
self.assertTrue(cache[key].called)
|
||||
|
||||
def test_invalidate_caches_clear_out_None(self):
|
||||
# Clear out None in sys.path_importer_cache() when invalidating caches.
|
||||
|
@ -214,6 +215,16 @@ class FinderTests:
|
|||
self.machinery.PathFinder.invalidate_caches()
|
||||
self.assertEqual(len(cache), 0)
|
||||
|
||||
def test_invalidate_caches_clear_out_relative_path(self):
|
||||
class FakeFinder:
|
||||
def invalidate_caches(self):
|
||||
pass
|
||||
|
||||
cache = {'relative_path': FakeFinder()}
|
||||
with util.import_state(path_importer_cache=cache):
|
||||
self.machinery.PathFinder.invalidate_caches()
|
||||
self.assertEqual(cache, {})
|
||||
|
||||
|
||||
class FindModuleTests(FinderTests):
|
||||
def find(self, *args, **kwargs):
|
||||
|
|
|
@ -396,7 +396,7 @@ class InvalidateCacheTests:
|
|||
def invalidate_caches(self):
|
||||
self.called = True
|
||||
|
||||
key = 'gobledeegook'
|
||||
key = os.path.abspath('gobledeegook')
|
||||
meta_ins = InvalidatingNullFinder()
|
||||
path_ins = InvalidatingNullFinder()
|
||||
sys.meta_path.insert(0, meta_ins)
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
:func:`importlib.invalidate_caches` now drops entries from
|
||||
:data:`sys.path_importer_cache` with a relative path as name. This solves a
|
||||
caching issue when a process changes its current working directory.
|
||||
|
||||
``FileFinder`` no longer inserts a dot in the path, e.g.
|
||||
``/egg/./spam`` is now ``/egg/spam``.
|
Loading…
Add table
Add a link
Reference in a new issue