8000 [3.7] bpo-33169: Remove values of `None` from sys.path_importer_cache when invalidating caches (GH-6402) by brettcannon · Pull Request #6403 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

[3.7] bpo-33169: Remove values of None from sys.path_importer_cache when invalidating caches (GH-6402) #6403

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 7, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion Doc/library/importlib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1081,7 +1081,12 @@ find and load modules.
.. classmethod:: invalidate_caches()

Calls :meth:`importlib.abc.PathEntryFinder.invalidate_caches` on all
finders stored in :attr:`sys.path_importer_cache`.
finders stored in :data:`sys.path_importer_cache` that define the method.
Otherwise entries in :data:`sys.path_importer_cache` set to ``None`` are
deleted.

.. versionchanged:: 3.7
Entries of ``None`` in :data:`sys.path_importer_cache` are deleted.

.. versionchanged:: 3.4
Calls objects in :data:`sys.path_hooks` with the current working
Expand Down
7 changes: 6 additions & 1 deletion Doc/whatsnew/3.7.rst
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,7 @@ importlib
---------

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

locale
------
Expand Down Expand Up @@ -1274,6 +1274,11 @@ Changes in the Python API
previous behaviour, or use
:attr:`STARTUPINFO.lpAttributeList <subprocess.STARTUPINFO.lpAttributeList>`.

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


Changes in the C API
--------------------
Expand Down
6 changes: 4 additions & 2 deletions Lib/importlib/_bootstrap_external.py
Original file line number Diff line number Diff line change
Expand Up @@ -1179,8 +1179,10 @@ class PathFinder:
def invalidate_caches(cls):
"""Call the invalidate_caches() method on all path entry finders
stored in sys.path_importer_caches (where implemented)."""
for finder in sys.path_importer_cache.values():
if hasattr(finder, 'invalidate_caches'):
for name, finder in list(sys.path_importer_cache.items()):
if finder is None:
del sys.path_importer_cache[name]
elif hasattr(finder, 'invalidate_caches'):
finder.invalidate_caches()

@classmethod
Expand Down
21 changes: 21 additions & 0 deletions Lib/test/test_importlib/import_/test_path.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,27 @@ def test_deleted_cwd(self):
# Do not want FileNotFoundError raised.
self.assertIsNone(self.machinery.PathFinder.find_spec('whatever'))

def test_invalidate_caches_finders(self):
# Finders with an invalidate_caches() method have it called.
class FakeFinder:
def __init__(self):
self.called = False

def invalidate_caches(self):
self.called = True

cache = {'leave_alone': object(), 'finder_to_invalidate': FakeFinder()}
with util.import_state(path_importer_cache=cache):
self.machinery.PathFinder.invalidate_caches()
self.assertTrue(cache['finder_to_invalidate'].called)

def test_invalidate_caches_clear_out_None(self):
# Clear out None in sys.path_importer_cache() when invalidating caches.
cache = {'clear_out': None}
with util.import_state(path_importer_cache=cache):
self.machinery.PathFinder.invalidate_caches()
self.assertEqual(len(cache), 0)


class FindModuleTests(FinderTests):
def find(self, *args, **kwargs):
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_importlib/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ def test_method_lacking(self):
# There should be no issues if the method is not defined.
key = 'gobbledeegook'
sys.path_importer_cache[key] = None
self.addCleanup(lambda: sys.path_importer_cache.__delitem__(key))
self.addCleanup(lambda: sys.path_importer_cache.pop(key, None))
self.init.invalidate_caches() # Shouldn't trigger an exception.


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Delete entries of ``None`` in :data:`sys.path_importer_cache` when
:meth:`importlib.machinery.invalidate_caches` is called.
Loading
0