mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	 23cbd8a656
			
		
	
	
		23cbd8a656
		
	
	
	
	
		
			
			planned for the package. There are no docs yet, but they are coming once the API for the first new function, importlib.import_module() is finalized.
		
			
				
	
	
		
			158 lines
		
	
	
	
		
			5.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			158 lines
		
	
	
	
		
			5.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from ..support import (mock_modules, import_state, import_, mock_path_hook,
 | |
|                         importlib_only, uncache)
 | |
| 
 | |
| from contextlib import nested
 | |
| from imp import new_module
 | |
| import sys
 | |
| from types import MethodType
 | |
| import unittest
 | |
| 
 | |
| 
 | |
| class BaseTests(unittest.TestCase):
 | |
| 
 | |
|     """When sys.meta_path cannot find the desired module, sys.path is
 | |
|     consulted. For each entry on the sequence [order], sys.path_importer_cache
 | |
|     is checked to see if it contains a key for the entry [cache check]. If an
 | |
|     importer is found then it is consulted before trying the next entry in
 | |
|     sys.path [cache use]. The 'path' argument to find_module() is never used
 | |
|     when trying to find a module [path not used].
 | |
| 
 | |
|     If an entry from sys.path is not in sys.path_importer_cache, sys.path_hooks
 | |
|     is called in turn [hooks order]. If a path hook cannot handle an entry,
 | |
|     ImportError is raised [hook failure]. Otherwise the resulting object is
 | |
|     cached in sys.path_importer_cache and then consulted [hook success]. If no
 | |
|     hook is found, None is set in sys.path_importer_cache and the default
 | |
|     importer is tried [no hook].
 | |
| 
 | |
|     For use of __path__ in a package, the above is all true, just substitute
 | |
|     "sys.path" for "__path__".
 | |
| 
 | |
|     """
 | |
| 
 | |
|     def order_test(self, to_import, entry, search_path, path=[]):
 | |
|         # [order]
 | |
|         log = []
 | |
|         class LogFindModule(mock_modules):
 | |
|             def find_module(self, fullname):
 | |
|                 log.append(self)
 | |
|                 return super().find_module(fullname)
 | |
| 
 | |
|         assert len(search_path) == 2
 | |
|         misser = LogFindModule(search_path[0])
 | |
|         hitter = LogFindModule(to_import)
 | |
|         with nested(misser, hitter):
 | |
|             cache = dict(zip(search_path, (misser, hitter)))
 | |
|             with import_state(path=path, path_importer_cache=cache):
 | |
|                 import_(to_import)
 | |
|         self.assertEquals(log[0], misser)
 | |
|         self.assertEquals(log[1], hitter)
 | |
| 
 | |
|     @importlib_only  # __import__ uses PyDict_GetItem(), bypassing log.
 | |
|     def cache_use_test(self, to_import, entry, path=[]):
 | |
|         # [cache check], [cache use]
 | |
|         log = []
 | |
|         class LoggingDict(dict):
 | |
|             def __getitem__(self, item):
 | |
|                 log.append(item)
 | |
|                 return super(LoggingDict, self).__getitem__(item)
 | |
| 
 | |
|         with mock_modules(to_import) as importer:
 | |
|             cache = LoggingDict()
 | |
|             cache[entry] = importer
 | |
|             with import_state(path=[entry], path_importer_cache=cache):
 | |
|                 module = import_(to_import, fromlist=['a'])
 | |
|             self.assert_(module is importer[to_import])
 | |
|         self.assertEquals(len(cache), 1)
 | |
|         self.assertEquals([entry], log)
 | |
| 
 | |
|     def hooks_order_test(self, to_import, entry, path=[]):
 | |
|         # [hooks order], [hooks failure], [hook success]
 | |
|         log = []
 | |
|         def logging_hook(entry):
 | |
|             log.append(entry)
 | |
|             raise ImportError
 | |
|         with mock_modules(to_import) as importer:
 | |
|             hitter = mock_path_hook(entry, importer=importer)
 | |
|             path_hooks = [logging_hook, logging_hook, hitter]
 | |
|             with import_state(path_hooks=path_hooks, path=path):
 | |
|                 import_(to_import)
 | |
|                 self.assertEquals(sys.path_importer_cache[entry], importer)
 | |
|         self.assertEquals(len(log), 2)
 | |
| 
 | |
|     # [no hook] XXX Worry about after deciding how to handle the default hook.
 | |
| 
 | |
|     def path_argument_test(self, to_import):
 | |
|         # [path not used]
 | |
|         class BadImporter:
 | |
|             """Class to help detect TypeError from calling find_module() with
 | |
|             an improper number of arguments."""
 | |
|             def find_module(name):
 | |
|                 raise ImportError
 | |
| 
 | |
|         try:
 | |
|             import_(to_import)
 | |
|         except ImportError:
 | |
|             pass
 | |
| 
 | |
| 
 | |
| class PathTests(BaseTests):
 | |
| 
 | |
|     """Tests for sys.path."""
 | |
| 
 | |
|     def test_order(self):
 | |
|         self.order_test('hit', 'second', ['first', 'second'],
 | |
|                         ['first', 'second'])
 | |
| 
 | |
|     def test_cache_use(self):
 | |
|         entry = "found!"
 | |
|         self.cache_use_test('hit', entry, [entry])
 | |
| 
 | |
|     def test_hooks_order(self):
 | |
|         entry = "found!"
 | |
|         self.hooks_order_test('hit', entry, [entry])
 | |
| 
 | |
|     def test_path_argument(self):
 | |
|         name = 'total junk'
 | |
|         with uncache(name):
 | |
|             self.path_argument_test(name)
 | |
| 
 | |
| 
 | |
| class __path__Tests(BaseTests):
 | |
| 
 | |
|     """Tests for __path__."""
 | |
| 
 | |
|     def run_test(self, test, entry, path, *args):
 | |
|         with mock_modules('pkg.__init__') as importer:
 | |
|             importer['pkg'].__path__ = path
 | |
|             importer.load_module('pkg')
 | |
|             test('pkg.hit', entry, *args)
 | |
| 
 | |
| 
 | |
|     @importlib_only  # XXX Unknown reason why this fails.
 | |
|     def test_order(self):
 | |
|         self.run_test(self.order_test, 'second', ('first', 'second'), ['first',
 | |
|             'second'])
 | |
| 
 | |
|     def test_cache_use(self):
 | |
|         location = "I'm here!"
 | |
|         self.run_test(self.cache_use_test, location, [location])
 | |
| 
 | |
|     def test_hooks_order(self):
 | |
|         location = "I'm here!"
 | |
|         self.run_test(self.hooks_order_test, location, [location])
 | |
| 
 | |
|     def test_path_argument(self):
 | |
|         module = new_module('pkg')
 | |
|         module.__path__ = ['random __path__']
 | |
|         name = 'pkg.whatever'
 | |
|         sys.modules['pkg'] = module
 | |
|         with uncache('pkg', name):
 | |
|             self.path_argument_test(name)
 | |
| 
 | |
| 
 | |
| def test_main():
 | |
|     from test.support import run_unittest
 | |
|     run_unittest(PathTests, __path__Tests)
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     test_main()
 |