def test_shallow_relative_package_import(self): # Test importing a module from a package through a relative import. pkg_name = 'pkg' pkg_long_name = '{0}.__init__'.format(pkg_name) module_name = 'mod' absolute_name = '{0}.{1}'.format(pkg_name, module_name) relative_name = '.{0}'.format(module_name) with test_util.mock_spec(pkg_long_name, absolute_name) as mock: with test_util.import_state(meta_path=[mock]): self.init.import_module(pkg_name) module = self.init.import_module(relative_name, pkg_name) self.assertEqual(module.__name__, absolute_name)
def test_fromlist_load_error_propagates(self): # If something in fromlist triggers an exception not related to not # existing, let that exception propagate. # issue15316 mod = types.ModuleType(PKG_NAME) mod.__path__ = ['XXX'] with util.import_state(meta_path=[self.bad_finder_loader]): with util.uncache(PKG_NAME): sys.modules[PKG_NAME] = mod with self.assertRaises(ImportError): self.__import__(PKG_NAME, fromlist=[SUBMOD_NAME.rpartition('.')[-1]])
def test_path_hooks(self): # Test that sys.path_hooks is used. # Test that sys.path_importer_cache is set. module = '<test module>' path = '<test path>' importer = util.mock_spec(module) hook = util.mock_path_hook(path, importer=importer) with util.import_state(path_hooks=[hook]): found = self.find(module, [path]) self.check_found(found, importer) self.assertIn(path, sys.path_importer_cache) self.assertIs(sys.path_importer_cache[path], importer)
def test_finder_with_find_loader(self): class TestFinder: loader = None portions = [] def find_loader(self, fullname): return self.loader, self.portions path = 'testing path' with util.import_state(path_importer_cache={path: TestFinder()}): with warnings.catch_warnings(): warnings.simplefilter("ignore", ImportWarning) self.assertIsNone( self.machinery.PathFinder.find_spec('whatever', [path])) success_finder = TestFinder() success_finder.loader = __loader__ with util.import_state(path_importer_cache={path: success_finder}): with warnings.catch_warnings(): warnings.simplefilter("ignore", ImportWarning) spec = self.machinery.PathFinder.find_spec('whatever', [path]) self.assertEqual(spec.loader, __loader__)
def test___loader___missing(self): with warnings.catch_warnings(): warnings.simplefilter("ignore", ImportWarning) module = types.ModuleType('blah') try: del module.__loader__ except AttributeError: pass loader = LoaderMock() loader.module = module with util.uncache('blah'), util.import_state(meta_path=[loader]): module = self.__import__('blah') self.assertEqual(loader, module.__loader__)
def test_blocked_fromlist(self): # If fromlist entry is None, let a ModuleNotFoundError propagate. # issue31642 mod = types.ModuleType(PKG_NAME) mod.__path__ = [] with util.import_state(meta_path=[self.bad_finder_loader]): with util.uncache(PKG_NAME, SUBMOD_NAME): sys.modules[PKG_NAME] = mod sys.modules[SUBMOD_NAME] = None with self.assertRaises(ModuleNotFoundError) as cm: self.__import__(PKG_NAME, fromlist=[SUBMOD_NAME.rpartition('.')[-1]]) self.assertEqual(cm.exception.name, SUBMOD_NAME)
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_empty_path_hooks(self): # Test that if sys.path_hooks is empty a warning is raised, # sys.path_importer_cache gets None set, and PathFinder returns None. path_entry = 'bogus_path' with util.import_state(path_importer_cache={}, path_hooks=[], path=[path_entry]): with warnings.catch_warnings(record=True) as w: warnings.simplefilter('always', ImportWarning) warnings.simplefilter('ignore', DeprecationWarning) self.assertIsNone(self.find('os')) self.assertIsNone(sys.path_importer_cache[path_entry]) self.assertEqual(len(w), 1) self.assertTrue(issubclass(w[-1].category, ImportWarning))
def test_module_from_package_triggers_ModuleNotFoundError(self): # If a submodule causes an ModuleNotFoundError because it tries # to import a module which doesn't exist, that should let the # ModuleNotFoundError propagate. def module_code(): import i_do_not_exist with util.mock_spec('pkg.__init__', 'pkg.mod', module_code={'pkg.mod': module_code}) as importer: with util.import_state(meta_path=[importer]): with self.assertRaises(ModuleNotFoundError) as exc: self.__import__('pkg', fromlist=['mod']) self.assertEqual('i_do_not_exist', exc.exception.name)
def namespace_tree_context(**kwargs): """ Save import state and sys.modules cache and restore it on exit. Typical usage: >>> with namespace_tree_context(path=['/tmp/xxyy/portion1', ... '/tmp/xxyy/portion2']): ... pass """ kwargs.setdefault('meta_path', sys.meta_path) kwargs.setdefault('path_hooks', sys.path_hooks) import_context = util.import_state(**kwargs) with import_context, sys_modules_context(): yield
def test_empty(self): # Raise an ImportWarning if sys.meta_path is empty. module_name = 'nothing' try: del sys.modules[module_name] except KeyError: pass with util.import_state(meta_path=[]): with warnings.catch_warnings(record=True) as w: warnings.simplefilter('always') self.assertIsNone( importlib._bootstrap._find_spec('nothing', None)) self.assertEqual(len(w), 1) self.assertTrue(issubclass(w[-1].category, ImportWarning))
def test_module_replaced(self): def code(): import sys module = type(sys)('top_level') module.spam = 3 sys.modules['top_level'] = module mock = test_util.mock_spec('top_level', module_code={'top_level': code}) with mock: with test_util.import_state(meta_path=[mock]): module = self.init.import_module('top_level') reloaded = self.init.reload(module) actual = sys.modules['top_level'] self.assertEqual(actual.spam, 3) self.assertEqual(reloaded.spam, 3)
def test_module_replaced(self): # see #18698 def code(): module = type(sys)('top_level') module.spam = 3 sys.modules['top_level'] = module mock = util.mock_modules('top_level', module_code={'top_level': code}) with mock: with util.import_state(meta_path=[mock]): module = importlib.import_module('top_level') reloaded = imp.reload(module) actual = sys.modules['top_level'] self.assertEqual(actual.spam, 3) self.assertEqual(reloaded.spam, 3)
def relative_import_test(self, create, globals_, callback): """Abstract out boilerplace for setting up for an import test.""" uncache_names = [] for name in create: if not name.endswith('.__init__'): uncache_names.append(name) else: uncache_names.append(name[:-len('.__init__')]) with util.mock_spec(*create) as importer: with util.import_state(meta_path=[importer]): with warnings.catch_warnings(): warnings.simplefilter("ignore") for global_ in globals_: with util.uncache(*uncache_names): callback(global_)
def test_no_path(self): # [no path] mod_name = 'top_level' assert '.' not in mod_name with self.mock_modules(mod_name) as importer: log, wrapped_call = self.log_finder(importer) setattr(importer, self.finder_name, MethodType(wrapped_call, importer)) with util.import_state(meta_path=[importer]): self.__import__(mod_name) assert len(log) == 1 args = log[0][0] # Assuming all arguments are positional. self.assertEqual(args[0], mod_name) self.assertIsNone(args[1])
def namespace_tree_context(**kwargs): """ Save import state and sys.modules cache and restore it on exit. Typical usage: >>> with namespace_tree_context(path=['/tmp/xxyy/portion1', ... '/tmp/xxyy/portion2']): ... pass """ # use default meta_path and path_hooks unless specified otherwise kwargs.setdefault('meta_path', sys.meta_path) kwargs.setdefault('path_hooks', sys.path_hooks) import_context = util.import_state(**kwargs) with import_context, sys_modules_context(): yield
def test_loaded_once(self): # Issue #13591: Modules should only be loaded once when # initializing the parent package attempts to import the # module currently being imported. b_load_count = 0 def load_a(): self.init.import_module('a.b') def load_b(): nonlocal b_load_count b_load_count += 1 code = {'a': load_a, 'a.b': load_b} modules = ['a.__init__', 'a.b'] with test_util.mock_spec(*modules, module_code=code) as mock: with test_util.import_state(meta_path=[mock]): self.init.import_module('a.b') self.assertEqual(b_load_count, 1)
def test_module_not_package_but_side_effects(self): # If a module injects something into sys.modules as a side-effect, then # pick up on that fact. name = 'mod' subname = name + '.b' def module_injection(): sys.modules[subname] = 'total bunk' mock_spec = util.mock_spec('mod', module_code={'mod': module_injection}) with mock_spec as mock: with util.import_state(meta_path=[mock]): try: submodule = self.__import__(subname) finally: import_helper.unload(subname)
def test_raising_parent_after_relative_importing_child(self): def __init__(): from . import module 1 / 0 mock = util.mock_spec('pkg.__init__', 'pkg.module', module_code={'pkg': __init__}) with mock: with util.import_state(meta_path=[mock]): with self.assertRaises((ZeroDivisionError, ImportError)): # This raises ImportError on the "from . import module" # line, not sure why. self.__import__('pkg') self.assertNotIn('pkg', sys.modules) with self.assertRaises((ZeroDivisionError, ImportError)): self.__import__('pkg.module') self.assertNotIn('pkg', sys.modules)
def test_raising_parent_after_importing_child(self): def __init__(): import pkg.module 1 / 0 mock = util.mock_spec('pkg.__init__', 'pkg.module', module_code={'pkg': __init__}) with mock: with util.import_state(meta_path=[mock]): with self.assertRaises(ZeroDivisionError): self.__import__('pkg') self.assertNotIn('pkg', sys.modules) self.assertIn('pkg.module', sys.modules) with self.assertRaises(ZeroDivisionError): self.__import__('pkg.module') self.assertNotIn('pkg', sys.modules) self.assertIn('pkg.module', sys.modules)
def test_finder_with_failing_find_spec(self): # PathEntryFinder with find_module() defined should work. # Issue #20763. class Finder: path_location = 'test_finder_with_find_module' def __init__(self, path): if path != self.path_location: raise ImportError @staticmethod def find_module(fullname): return None with util.import_state(path=[Finder.path_location] + sys.path[:], path_hooks=[Finder]): with warnings.catch_warnings(): warnings.simplefilter("ignore", ImportWarning) self.machinery.PathFinder.find_spec('importlib')
def test_with_path(self): # [path set] pkg_name = 'pkg' mod_name = pkg_name + '.module' path = [42] assert '.' in mod_name with self.mock_modules(pkg_name + '.__init__', mod_name) as importer: importer.modules[pkg_name].__path__ = path log, wrapped_call = self.log_finder(importer) setattr(importer, self.finder_name, MethodType(wrapped_call, importer)) with util.import_state(meta_path=[importer]): self.__import__(mod_name) assert len(log) == 2 args = log[1][0] kwargs = log[1][1] # Assuming all arguments are positional. self.assertFalse(kwargs) self.assertEqual(args[0], mod_name) self.assertIs(args[1], path)
def test_deleted_cwd(self): # Issue #22834 old_dir = os.getcwd() self.addCleanup(os.chdir, old_dir) new_dir = tempfile.mkdtemp() try: os.chdir(new_dir) try: os.rmdir(new_dir) except OSError: # EINVAL on Solaris, EBUSY on AIX, ENOTEMPTY on Windows self.skipTest("platform does not allow " "the deletion of the cwd") except: os.chdir(old_dir) os.rmdir(new_dir) raise with util.import_state(path=['']): # Do not want FileNotFoundError raised. self.assertIsNone(self.machinery.PathFinder.find_spec('whatever'))
def test___loader__(self): loader = SpecLoaderMock() with util.uncache('blah'), util.import_state(meta_path=[loader]): module = self.__import__('blah') self.assertEqual(loader, module.__loader__)
def test_empty_string(self): with util.mock_spec('pkg.__init__', 'pkg.mod') as importer: with util.import_state(meta_path=[importer]): module = self.__import__('pkg.mod', fromlist=['']) self.assertEqual(module.__name__, 'pkg.mod')
def test_nonexistent_from_package(self): with util.mock_spec('pkg.__init__') as importer: with util.import_state(meta_path=[importer]): module = self.__import__('pkg', fromlist=['non_existent']) self.assertEqual(module.__name__, 'pkg') self.assertFalse(hasattr(module, 'non_existent'))
def test_object(self): # [object case] with util.mock_spec('module') as importer: with util.import_state(meta_path=[importer]): module = self.__import__('module', fromlist=['attr']) self.assertEqual(module.__name__, 'module')
def test_return_from_from_import(self): # [from return] with util.mock_spec('pkg.__init__', 'pkg.module') as importer: with util.import_state(meta_path=[importer]): module = self.__import__('pkg.module', fromlist=['attr']) self.assertEqual(module.__name__, 'pkg.module')
def test_module_import(self): # Test importing a top-level module. with test_util.mock_spec('top_level') as mock: with test_util.import_state(meta_path=[mock]): module = self.init.import_module('top_level') self.assertEqual(module.__name__, 'top_level')
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)
def test_failure(self): # Test None returned upon not finding a suitable loader. module = '<test module>' with util.import_state(): self.assertIsNone(self.find(module))