| import sys |
| import imp |
| import os |
| import unittest |
| from test import test_support |
| |
| |
| test_src = """\ |
| def get_name(): |
| return __name__ |
| def get_file(): |
| return __file__ |
| """ |
| |
| test_co = compile(test_src, "<???>", "exec") |
| test_path = "!!!_test_!!!" |
| |
| |
| class ImportTracker: |
| """Importer that only tracks attempted imports.""" |
| def __init__(self): |
| self.imports = [] |
| def find_module(self, fullname, path=None): |
| self.imports.append(fullname) |
| return None |
| |
| |
| class TestImporter: |
| |
| modules = { |
| "hooktestmodule": (False, test_co), |
| "hooktestpackage": (True, test_co), |
| "hooktestpackage.sub": (True, test_co), |
| "hooktestpackage.sub.subber": (False, test_co), |
| } |
| |
| def __init__(self, path=test_path): |
| if path != test_path: |
| # if out class is on sys.path_hooks, we must raise |
| # ImportError for any path item that we can't handle. |
| raise ImportError |
| self.path = path |
| |
| def _get__path__(self): |
| raise NotImplementedError |
| |
| def find_module(self, fullname, path=None): |
| if fullname in self.modules: |
| return self |
| else: |
| return None |
| |
| def load_module(self, fullname): |
| ispkg, code = self.modules[fullname] |
| mod = imp.new_module(fullname) |
| sys.modules[fullname] = mod |
| mod.__file__ = "<%s>" % self.__class__.__name__ |
| mod.__loader__ = self |
| if ispkg: |
| mod.__path__ = self._get__path__() |
| exec code in mod.__dict__ |
| return mod |
| |
| |
| class MetaImporter(TestImporter): |
| def _get__path__(self): |
| return [] |
| |
| class PathImporter(TestImporter): |
| def _get__path__(self): |
| return [self.path] |
| |
| |
| class ImportBlocker: |
| """Place an ImportBlocker instance on sys.meta_path and you |
| can be sure the modules you specified can't be imported, even |
| if it's a builtin.""" |
| def __init__(self, *namestoblock): |
| self.namestoblock = dict.fromkeys(namestoblock) |
| def find_module(self, fullname, path=None): |
| if fullname in self.namestoblock: |
| return self |
| return None |
| def load_module(self, fullname): |
| raise ImportError, "I dare you" |
| |
| |
| class ImpWrapper: |
| |
| def __init__(self, path=None): |
| if path is not None and not os.path.isdir(path): |
| raise ImportError |
| self.path = path |
| |
| def find_module(self, fullname, path=None): |
| subname = fullname.split(".")[-1] |
| if subname != fullname and self.path is None: |
| return None |
| if self.path is None: |
| path = None |
| else: |
| path = [self.path] |
| try: |
| file, filename, stuff = imp.find_module(subname, path) |
| except ImportError: |
| return None |
| return ImpLoader(file, filename, stuff) |
| |
| |
| class ImpLoader: |
| |
| def __init__(self, file, filename, stuff): |
| self.file = file |
| self.filename = filename |
| self.stuff = stuff |
| |
| def load_module(self, fullname): |
| mod = imp.load_module(fullname, self.file, self.filename, self.stuff) |
| if self.file: |
| self.file.close() |
| mod.__loader__ = self # for introspection |
| return mod |
| |
| |
| class ImportHooksBaseTestCase(unittest.TestCase): |
| |
| def setUp(self): |
| self.path = sys.path[:] |
| self.meta_path = sys.meta_path[:] |
| self.path_hooks = sys.path_hooks[:] |
| sys.path_importer_cache.clear() |
| self.tracker = ImportTracker() |
| sys.meta_path.insert(0, self.tracker) |
| |
| def tearDown(self): |
| sys.path[:] = self.path |
| sys.meta_path[:] = self.meta_path |
| sys.path_hooks[:] = self.path_hooks |
| sys.path_importer_cache.clear() |
| for fullname in self.tracker.imports: |
| if fullname in sys.modules: |
| del sys.modules[fullname] |
| |
| |
| class ImportHooksTestCase(ImportHooksBaseTestCase): |
| |
| def doTestImports(self, importer=None): |
| import hooktestmodule |
| import hooktestpackage |
| import hooktestpackage.sub |
| import hooktestpackage.sub.subber |
| self.assertEqual(hooktestmodule.get_name(), |
| "hooktestmodule") |
| self.assertEqual(hooktestpackage.get_name(), |
| "hooktestpackage") |
| self.assertEqual(hooktestpackage.sub.get_name(), |
| "hooktestpackage.sub") |
| self.assertEqual(hooktestpackage.sub.subber.get_name(), |
| "hooktestpackage.sub.subber") |
| if importer: |
| self.assertEqual(hooktestmodule.__loader__, importer) |
| self.assertEqual(hooktestpackage.__loader__, importer) |
| self.assertEqual(hooktestpackage.sub.__loader__, importer) |
| self.assertEqual(hooktestpackage.sub.subber.__loader__, importer) |
| |
| def testMetaPath(self): |
| i = MetaImporter() |
| sys.meta_path.append(i) |
| self.doTestImports(i) |
| |
| def testPathHook(self): |
| sys.path_hooks.append(PathImporter) |
| sys.path.append(test_path) |
| self.doTestImports() |
| |
| def testBlocker(self): |
| mname = "exceptions" # an arbitrary harmless builtin module |
| if mname in sys.modules: |
| del sys.modules[mname] |
| sys.meta_path.append(ImportBlocker(mname)) |
| try: |
| __import__(mname) |
| except ImportError: |
| pass |
| else: |
| self.fail("'%s' was not supposed to be importable" % mname) |
| |
| def testImpWrapper(self): |
| i = ImpWrapper() |
| sys.meta_path.append(i) |
| sys.path_hooks.append(ImpWrapper) |
| mnames = ("colorsys", "urlparse", "distutils.core", "compiler.misc") |
| for mname in mnames: |
| parent = mname.split(".")[0] |
| for n in sys.modules.keys(): |
| if n.startswith(parent): |
| del sys.modules[n] |
| for mname in mnames: |
| m = __import__(mname, globals(), locals(), ["__dummy__"]) |
| m.__loader__ # to make sure we actually handled the import |
| |
| |
| if __name__ == "__main__": |
| test_support.run_unittest(ImportHooksTestCase) |