mirror of
https://github.com/python/cpython.git
synced 2025-07-25 12:14:38 +00:00

This should make the Linux distros happy as it is now easier to leave importlib's tests out of their base Python distribution.
208 lines
6.7 KiB
Python
208 lines
6.7 KiB
Python
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__ = ['<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()
|