Issue #13959: Introduce importlib.find_loader().

The long-term goal is to deprecate imp.find_module() in favour of this
API, but it will take some time as some APIs explicitly return/use what
imp.find_module() returns.
This commit is contained in:
Brett Cannon 2012-05-12 17:43:17 -04:00
parent acc0c181a8
commit ee78a2b51c
5 changed files with 105 additions and 10 deletions

View file

@ -29,6 +29,30 @@ def invalidate_caches():
finder.invalidate_caches()
def find_loader(name, path=None):
"""Find the loader for the specified module.
First, sys.modules is checked to see if the module was already imported. If
so, then sys.modules[name].__loader__ is returned. If that happens to be
set to None, then ValueError is raised. If the module is not in
sys.modules, then sys.meta_path is searched for a suitable loader with the
value of 'path' given to the finders. None is returned if no loader could
be found.
Dotted names do not have their parent packages implicitly imported.
"""
try:
loader = sys.modules[name].__loader__
if loader is None:
raise ValueError('{}.__loader__ is None'.format(name))
else:
return loader
except KeyError:
pass
return _bootstrap._find_module(name, path)
def import_module(name, package=None):
"""Import a module.

View file

@ -85,6 +85,54 @@ class ImportModuleTests(unittest.TestCase):
self.assertEqual(b_load_count, 1)
class FindLoaderTests(unittest.TestCase):
class FakeMetaFinder:
@staticmethod
def find_module(name, path=None): return name, path
def test_sys_modules(self):
# If a module with __loader__ is in sys.modules, then return it.
name = 'some_mod'
with util.uncache(name):
module = imp.new_module(name)
loader = 'a loader!'
module.__loader__ = loader
sys.modules[name] = module
found = importlib.find_loader(name)
self.assertEqual(loader, found)
def test_sys_modules_loader_is_None(self):
# If sys.modules[name].__loader__ is None, raise ValueError.
name = 'some_mod'
with util.uncache(name):
module = imp.new_module(name)
module.__loader__ = None
sys.modules[name] = module
with self.assertRaises(ValueError):
importlib.find_loader(name)
def test_success(self):
# Return the loader found on sys.meta_path.
name = 'some_mod'
with util.uncache(name):
with util.import_state(meta_path=[self.FakeMetaFinder]):
self.assertEqual((name, None), importlib.find_loader(name))
def test_success_path(self):
# Searching on a path should work.
name = 'some_mod'
path = 'path to some place'
with util.uncache(name):
with util.import_state(meta_path=[self.FakeMetaFinder]):
self.assertEqual((name, path),
importlib.find_loader(name, path))
def test_nothing(self):
# None is returned upon failure to find a loader.
self.assertIsNone(importlib.find_loader('nevergoingtofindthismodule'))
class InvalidateCacheTests(unittest.TestCase):
def test_method_called(self):
@ -114,7 +162,7 @@ class InvalidateCacheTests(unittest.TestCase):
def test_main():
from test.support import run_unittest
run_unittest(ImportModuleTests)
run_unittest(ImportModuleTests, FindLoaderTests, InvalidateCacheTests)
if __name__ == '__main__':