mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	
		
			
	
	
		
			159 lines
		
	
	
	
		
			5.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			159 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() |