from importlib import util from . import util as test_util import imp import sys import types import unittest class ModuleForLoaderTests(unittest.TestCase): """Tests for importlib.util.module_for_loader.""" def return_module(self, name): fxn = util.module_for_loader(lambda self, module: module) return fxn(self, name) def raise_exception(self, name): def to_wrap(self, module): raise ImportError fxn = util.module_for_loader(to_wrap) try: fxn(self, name) except ImportError: pass def test_new_module(self): # Test that when no module exists in sys.modules a new module is # created. module_name = 'a.b.c' with test_util.uncache(module_name): module = self.return_module(module_name) self.assertIn(module_name, sys.modules) self.assertIsInstance(module, types.ModuleType) self.assertEqual(module.__name__, module_name) def test_reload(self): # Test that a module is reused if already in sys.modules. name = 'a.b.c' module = imp.new_module('a.b.c') with test_util.uncache(name): sys.modules[name] = module returned_module = self.return_module(name) self.assertIs(returned_module, sys.modules[name]) def test_new_module_failure(self): # Test that a module is removed from sys.modules if added but an # exception is raised. name = 'a.b.c' with test_util.uncache(name): self.raise_exception(name) self.assertNotIn(name, sys.modules) def test_reload_failure(self): # Test that a failure on reload leaves the module in-place. name = 'a.b.c' module = imp.new_module(name) with test_util.uncache(name): sys.modules[name] = module self.raise_exception(name) self.assertIs(module, sys.modules[name]) def test_decorator_attrs(self): def fxn(self, module): pass wrapped = util.module_for_loader(fxn) self.assertEqual(wrapped.__name__, fxn.__name__) self.assertEqual(wrapped.__qualname__, fxn.__qualname__) def test_false_module(self): # If for some odd reason a module is considered false, still return it # from sys.modules. class FalseModule(types.ModuleType): def __bool__(self): return False name = 'mod' module = FalseModule(name) with test_util.uncache(name): self.assertFalse(module) sys.modules[name] = module given = self.return_module(name) self.assertIs(given, module) def test_attributes_set(self): # __name__, __loader__, and __package__ should be set (when # is_package() is defined; undefined implicitly tested elsewhere). class FakeLoader: def __init__(self, is_package): self._pkg = is_package def is_package(self, name): return self._pkg @util.module_for_loader def load_module(self, module): return module name = 'pkg.mod' with test_util.uncache(name): loader = FakeLoader(False) module = loader.load_module(name) self.assertEqual(module.__name__, name) self.assertIs(module.__loader__, loader) self.assertEqual(module.__package__, 'pkg') name = 'pkg.sub' with test_util.uncache(name): loader = FakeLoader(True) module = loader.load_module(name) self.assertEqual(module.__name__, name) self.assertIs(module.__loader__, loader) self.assertEqual(module.__package__, name) class SetPackageTests(unittest.TestCase): """Tests for importlib.util.set_package.""" def verify(self, module, expect): """Verify the module has the expected value for __package__ after passing through set_package.""" fxn = lambda: module wrapped = util.set_package(fxn) wrapped() self.assertTrue(hasattr(module, '__package__')) self.assertEqual(expect, module.__package__) def test_top_level(self): # __package__ should be set to the empty string if a top-level module. # Implicitly tests when package is set to None. module = imp.new_module('module') module.__package__ = None self.verify(module, '') def test_package(self): # Test setting __package__ for a package. module = imp.new_module('pkg') module.__path__ = [''] module.__package__ = None self.verify(module, 'pkg') def test_submodule(self): # Test __package__ for a module in a package. module = imp.new_module('pkg.mod') module.__package__ = None self.verify(module, 'pkg') def test_setting_if_missing(self): # __package__ should be set if it is missing. module = imp.new_module('mod') if hasattr(module, '__package__'): delattr(module, '__package__') self.verify(module, '') def test_leaving_alone(self): # If __package__ is set and not None then leave it alone. for value in (True, False): module = imp.new_module('mod') module.__package__ = value self.verify(module, value) def test_decorator_attrs(self): def fxn(module): pass wrapped = util.set_package(fxn) self.assertEqual(wrapped.__name__, fxn.__name__) self.assertEqual(wrapped.__qualname__, fxn.__qualname__) class ResolveNameTests(unittest.TestCase): """Tests importlib.util.resolve_name().""" def test_absolute(self): # bacon self.assertEqual('bacon', util.resolve_name('bacon', None)) def test_aboslute_within_package(self): # bacon in spam self.assertEqual('bacon', util.resolve_name('bacon', 'spam')) def test_no_package(self): # .bacon in '' with self.assertRaises(ValueError): util.resolve_name('.bacon', '') def test_in_package(self): # .bacon in spam self.assertEqual('spam.eggs.bacon', util.resolve_name('.bacon', 'spam.eggs')) def test_other_package(self): # ..bacon in spam.bacon self.assertEqual('spam.bacon', util.resolve_name('..bacon', 'spam.eggs')) def test_escape(self): # ..bacon in spam with self.assertRaises(ValueError): util.resolve_name('..bacon', 'spam') def test_main(): from test import support support.run_unittest( ModuleForLoaderTests, SetPackageTests, ResolveNameTests ) if __name__ == '__main__': test_main()