Skip to content

Commit a09bb87

Browse files
authored
[3.7] bpo-33169: Remove values of None from sys.path_importer_cache when invalidating caches (GH-6402) (GH-6403)
An entry of None in sys.path_importer_cache represents a negative/missing finder for a path, so clearing it out makes sense. (cherry picked from commit 9e2be60)
1 parent 3c193cf commit a09bb87

File tree

7 files changed

+654
-616
lines changed

7 files changed

+654
-616
lines changed

Doc/library/importlib.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1081,7 +1081,12 @@ find and load modules.
10811081
.. classmethod:: invalidate_caches()
10821082

10831083
Calls :meth:`importlib.abc.PathEntryFinder.invalidate_caches` on all
1084-
finders stored in :attr:`sys.path_importer_cache`.
1084+
finders stored in :data:`sys.path_importer_cache` that define the method.
1085+
Otherwise entries in :data:`sys.path_importer_cache` set to ``None`` are
1086+
deleted.
1087+
1088+
.. versionchanged:: 3.7
1089+
Entries of ``None`` in :data:`sys.path_importer_cache` are deleted.
10851090

10861091
.. versionchanged:: 3.4
10871092
Calls objects in :data:`sys.path_hooks` with the current working

Doc/whatsnew/3.7.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,7 @@ importlib
561561
---------
562562

563563
The :class:`importlib.abc.ResourceReader` ABC was introduced to
564-
support the loading of resource from packages.
564+
support the loading of resources from packages.
565565

566566
locale
567567
------
@@ -1274,6 +1274,11 @@ Changes in the Python API
12741274
previous behaviour, or use
12751275
:attr:`STARTUPINFO.lpAttributeList <subprocess.STARTUPINFO.lpAttributeList>`.
12761276

1277+
* :meth:`importlib.machinery.PathFinder.invalidate_caches` -- which implicitly
1278+
affects :func:`importlib.invalidate_caches` -- now deletes entries
1279+
in :data:`sys.path_importer_cache` which are set to ``None``.
1280+
(Contributed by Brett Cannon in :issue:`33169`.)
1281+
12771282

12781283
Changes in the C API
12791284
--------------------

Lib/importlib/_bootstrap_external.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,8 +1179,10 @@ class PathFinder:
11791179
def invalidate_caches(cls):
11801180
"""Call the invalidate_caches() method on all path entry finders
11811181
stored in sys.path_importer_caches (where implemented)."""
1182-
for finder in sys.path_importer_cache.values():
1183-
if hasattr(finder, 'invalidate_caches'):
1182+
for name, finder in list(sys.path_importer_cache.items()):
1183+
if finder is None:
1184+
del sys.path_importer_cache[name]
1185+
elif hasattr(finder, 'invalidate_caches'):
11841186
finder.invalidate_caches()
11851187

11861188
@classmethod

Lib/test/test_importlib/import_/test_path.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,27 @@ def test_deleted_cwd(self):
184184
# Do not want FileNotFoundError raised.
185185
self.assertIsNone(self.machinery.PathFinder.find_spec('whatever'))
186186

187+
def test_invalidate_caches_finders(self):
188+
# Finders with an invalidate_caches() method have it called.
189+
class FakeFinder:
190+
def __init__(self):
191+
self.called = False
192+
193+
def invalidate_caches(self):
194+
self.called = True
195+
196+
cache = {'leave_alone': object(), 'finder_to_invalidate': FakeFinder()}
197+
with util.import_state(path_importer_cache=cache):
198+
self.machinery.PathFinder.invalidate_caches()
199+
self.assertTrue(cache['finder_to_invalidate'].called)
200+
201+
def test_invalidate_caches_clear_out_None(self):
202+
# Clear out None in sys.path_importer_cache() when invalidating caches.
203+
cache = {'clear_out': None}
204+
with util.import_state(path_importer_cache=cache):
205+
self.machinery.PathFinder.invalidate_caches()
206+
self.assertEqual(len(cache), 0)
207+
187208

188209
class FindModuleTests(FinderTests):
189210
def find(self, *args, **kwargs):

Lib/test/test_importlib/test_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ def test_method_lacking(self):
406406
# There should be no issues if the method is not defined.
407407
key = 'gobbledeegook'
408408
sys.path_importer_cache[key] = None
409-
self.addCleanup(lambda: sys.path_importer_cache.__delitem__(key))
409+
self.addCleanup(lambda: sys.path_importer_cache.pop(key, None))
410410
self.init.invalidate_caches() # Shouldn't trigger an exception.
411411

412412

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Delete entries of ``None`` in :data:`sys.path_importer_cache` when
2+
:meth:`importlib.machinery.invalidate_caches` is called.

0 commit comments

Comments
 (0)