mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	bpo-33169: Remove values of None from sys.path_importer_cache when invalidating caches (GH-6402)
				
					
				
			An entry of None in sys.path_importer_cache represents a negative/missing finder for a path, so clearing it out makes sense.
This commit is contained in:
		
							parent
							
								
									3a9ccee0e5
								
							
						
					
					
						commit
						9e2be60634
					
				
					 6 changed files with 652 additions and 620 deletions
				
			
		|  | @ -1081,7 +1081,12 @@ find and load modules. | ||||||
|    .. classmethod:: invalidate_caches() |    .. classmethod:: invalidate_caches() | ||||||
| 
 | 
 | ||||||
|       Calls :meth:`importlib.abc.PathEntryFinder.invalidate_caches` on all |       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 |    .. versionchanged:: 3.4 | ||||||
|       Calls objects in :data:`sys.path_hooks` with the current working |       Calls objects in :data:`sys.path_hooks` with the current working | ||||||
|  |  | ||||||
|  | @ -1181,8 +1181,10 @@ class PathFinder: | ||||||
|     def invalidate_caches(cls): |     def invalidate_caches(cls): | ||||||
|         """Call the invalidate_caches() method on all path entry finders |         """Call the invalidate_caches() method on all path entry finders | ||||||
|         stored in sys.path_importer_caches (where implemented).""" |         stored in sys.path_importer_caches (where implemented).""" | ||||||
|         for finder in sys.path_importer_cache.values(): |         for name, finder in list(sys.path_importer_cache.items()): | ||||||
|             if hasattr(finder, 'invalidate_caches'): |             if finder is None: | ||||||
|  |                 del sys.path_importer_cache[name] | ||||||
|  |             elif hasattr(finder, 'invalidate_caches'): | ||||||
|                 finder.invalidate_caches() |                 finder.invalidate_caches() | ||||||
| 
 | 
 | ||||||
|     @classmethod |     @classmethod | ||||||
|  |  | ||||||
|  | @ -184,6 +184,27 @@ def test_deleted_cwd(self): | ||||||
|             # Do not want FileNotFoundError raised. |             # Do not want FileNotFoundError raised. | ||||||
|             self.assertIsNone(self.machinery.PathFinder.find_spec('whatever')) |             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): | class FindModuleTests(FinderTests): | ||||||
|     def find(self, *args, **kwargs): |     def find(self, *args, **kwargs): | ||||||
|  |  | ||||||
|  | @ -406,7 +406,7 @@ def test_method_lacking(self): | ||||||
|         # There should be no issues if the method is not defined. |         # There should be no issues if the method is not defined. | ||||||
|         key = 'gobbledeegook' |         key = 'gobbledeegook' | ||||||
|         sys.path_importer_cache[key] = None |         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. |         self.init.invalidate_caches()  # Shouldn't trigger an exception. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,2 @@ | ||||||
|  | Delete entries of ``None`` in :data:`sys.path_importer_cache` when | ||||||
|  | :meth:`importlib.machinery.invalidate_caches` is called. | ||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Brett Cannon
						Brett Cannon