/Lib/test/test_importhooks.py

http://unladen-swallow.googlecode.com/ · Python · 259 lines · 237 code · 19 blank · 3 comment · 5 complexity · ed8d8cc7304b2e74723dcd919d8900f5 MD5 · raw file

  1. import sys
  2. import imp
  3. import os
  4. import unittest
  5. from test import test_support
  6. test_src = """\
  7. def get_name():
  8. return __name__
  9. def get_file():
  10. return __file__
  11. """
  12. absimp = "import sub\n"
  13. relimp = "from . import sub\n"
  14. deeprelimp = "from .... import sub\n"
  15. futimp = "from __future__ import absolute_import\n"
  16. reload_src = test_src+"""\
  17. reloaded = True
  18. """
  19. test_co = compile(test_src, "<???>", "exec")
  20. reload_co = compile(reload_src, "<???>", "exec")
  21. test2_oldabs_co = compile(absimp + test_src, "<???>", "exec")
  22. test2_newabs_co = compile(futimp + absimp + test_src, "<???>", "exec")
  23. test2_newrel_co = compile(relimp + test_src, "<???>", "exec")
  24. test2_deeprel_co = compile(deeprelimp + test_src, "<???>", "exec")
  25. test2_futrel_co = compile(futimp + relimp + test_src, "<???>", "exec")
  26. test_path = "!!!_test_!!!"
  27. class TestImporter:
  28. modules = {
  29. "hooktestmodule": (False, test_co),
  30. "hooktestpackage": (True, test_co),
  31. "hooktestpackage.sub": (True, test_co),
  32. "hooktestpackage.sub.subber": (True, test_co),
  33. "hooktestpackage.oldabs": (False, test2_oldabs_co),
  34. "hooktestpackage.newabs": (False, test2_newabs_co),
  35. "hooktestpackage.newrel": (False, test2_newrel_co),
  36. "hooktestpackage.sub.subber.subest": (True, test2_deeprel_co),
  37. "hooktestpackage.futrel": (False, test2_futrel_co),
  38. "sub": (False, test_co),
  39. "reloadmodule": (False, test_co),
  40. }
  41. def __init__(self, path=test_path):
  42. if path != test_path:
  43. # if out class is on sys.path_hooks, we must raise
  44. # ImportError for any path item that we can't handle.
  45. raise ImportError
  46. self.path = path
  47. def _get__path__(self):
  48. raise NotImplementedError
  49. def find_module(self, fullname, path=None):
  50. if fullname in self.modules:
  51. return self
  52. else:
  53. return None
  54. def load_module(self, fullname):
  55. ispkg, code = self.modules[fullname]
  56. mod = sys.modules.setdefault(fullname,imp.new_module(fullname))
  57. mod.__file__ = "<%s>" % self.__class__.__name__
  58. mod.__loader__ = self
  59. if ispkg:
  60. mod.__path__ = self._get__path__()
  61. exec code in mod.__dict__
  62. return mod
  63. class MetaImporter(TestImporter):
  64. def _get__path__(self):
  65. return []
  66. class PathImporter(TestImporter):
  67. def _get__path__(self):
  68. return [self.path]
  69. class ImportBlocker:
  70. """Place an ImportBlocker instance on sys.meta_path and you
  71. can be sure the modules you specified can't be imported, even
  72. if it's a builtin."""
  73. def __init__(self, *namestoblock):
  74. self.namestoblock = dict.fromkeys(namestoblock)
  75. def find_module(self, fullname, path=None):
  76. if fullname in self.namestoblock:
  77. return self
  78. return None
  79. def load_module(self, fullname):
  80. raise ImportError, "I dare you"
  81. class ImpWrapper:
  82. def __init__(self, path=None):
  83. if path is not None and not os.path.isdir(path):
  84. raise ImportError
  85. self.path = path
  86. def find_module(self, fullname, path=None):
  87. subname = fullname.split(".")[-1]
  88. if subname != fullname and self.path is None:
  89. return None
  90. if self.path is None:
  91. path = None
  92. else:
  93. path = [self.path]
  94. try:
  95. file, filename, stuff = imp.find_module(subname, path)
  96. except ImportError:
  97. return None
  98. return ImpLoader(file, filename, stuff)
  99. class ImpLoader:
  100. def __init__(self, file, filename, stuff):
  101. self.file = file
  102. self.filename = filename
  103. self.stuff = stuff
  104. def load_module(self, fullname):
  105. mod = imp.load_module(fullname, self.file, self.filename, self.stuff)
  106. if self.file:
  107. self.file.close()
  108. mod.__loader__ = self # for introspection
  109. return mod
  110. class ImportHooksBaseTestCase(unittest.TestCase):
  111. def setUp(self):
  112. self.path = sys.path[:]
  113. self.meta_path = sys.meta_path[:]
  114. self.path_hooks = sys.path_hooks[:]
  115. sys.path_importer_cache.clear()
  116. self.modules_before = sys.modules.copy()
  117. def tearDown(self):
  118. sys.path[:] = self.path
  119. sys.meta_path[:] = self.meta_path
  120. sys.path_hooks[:] = self.path_hooks
  121. sys.path_importer_cache.clear()
  122. sys.modules.clear()
  123. sys.modules.update(self.modules_before)
  124. class ImportHooksTestCase(ImportHooksBaseTestCase):
  125. def doTestImports(self, importer=None):
  126. import hooktestmodule
  127. import hooktestpackage
  128. import hooktestpackage.sub
  129. import hooktestpackage.sub.subber
  130. self.assertEqual(hooktestmodule.get_name(),
  131. "hooktestmodule")
  132. self.assertEqual(hooktestpackage.get_name(),
  133. "hooktestpackage")
  134. self.assertEqual(hooktestpackage.sub.get_name(),
  135. "hooktestpackage.sub")
  136. self.assertEqual(hooktestpackage.sub.subber.get_name(),
  137. "hooktestpackage.sub.subber")
  138. if importer:
  139. self.assertEqual(hooktestmodule.__loader__, importer)
  140. self.assertEqual(hooktestpackage.__loader__, importer)
  141. self.assertEqual(hooktestpackage.sub.__loader__, importer)
  142. self.assertEqual(hooktestpackage.sub.subber.__loader__, importer)
  143. TestImporter.modules['reloadmodule'] = (False, test_co)
  144. import reloadmodule
  145. self.failIf(hasattr(reloadmodule,'reloaded'))
  146. TestImporter.modules['reloadmodule'] = (False, reload_co)
  147. reload(reloadmodule)
  148. self.failUnless(hasattr(reloadmodule,'reloaded'))
  149. import hooktestpackage.oldabs
  150. self.assertEqual(hooktestpackage.oldabs.get_name(),
  151. "hooktestpackage.oldabs")
  152. self.assertEqual(hooktestpackage.oldabs.sub,
  153. hooktestpackage.sub)
  154. import hooktestpackage.newrel
  155. self.assertEqual(hooktestpackage.newrel.get_name(),
  156. "hooktestpackage.newrel")
  157. self.assertEqual(hooktestpackage.newrel.sub,
  158. hooktestpackage.sub)
  159. import hooktestpackage.sub.subber.subest as subest
  160. self.assertEqual(subest.get_name(),
  161. "hooktestpackage.sub.subber.subest")
  162. self.assertEqual(subest.sub,
  163. hooktestpackage.sub)
  164. import hooktestpackage.futrel
  165. self.assertEqual(hooktestpackage.futrel.get_name(),
  166. "hooktestpackage.futrel")
  167. self.assertEqual(hooktestpackage.futrel.sub,
  168. hooktestpackage.sub)
  169. import sub
  170. self.assertEqual(sub.get_name(), "sub")
  171. import hooktestpackage.newabs
  172. self.assertEqual(hooktestpackage.newabs.get_name(),
  173. "hooktestpackage.newabs")
  174. self.assertEqual(hooktestpackage.newabs.sub, sub)
  175. def testMetaPath(self):
  176. i = MetaImporter()
  177. sys.meta_path.append(i)
  178. self.doTestImports(i)
  179. def testPathHook(self):
  180. sys.path_hooks.append(PathImporter)
  181. sys.path.append(test_path)
  182. self.doTestImports()
  183. def testBlocker(self):
  184. mname = "exceptions" # an arbitrary harmless builtin module
  185. if mname in sys.modules:
  186. del sys.modules[mname]
  187. sys.meta_path.append(ImportBlocker(mname))
  188. try:
  189. __import__(mname)
  190. except ImportError:
  191. pass
  192. else:
  193. self.fail("'%s' was not supposed to be importable" % mname)
  194. def testImpWrapper(self):
  195. i = ImpWrapper()
  196. sys.meta_path.append(i)
  197. sys.path_hooks.append(ImpWrapper)
  198. mnames = ("colorsys", "urlparse", "distutils.core", "compiler.misc")
  199. for mname in mnames:
  200. parent = mname.split(".")[0]
  201. for n in sys.modules.keys():
  202. if n.startswith(parent):
  203. del sys.modules[n]
  204. for mname in mnames:
  205. m = __import__(mname, globals(), locals(), ["__dummy__"])
  206. m.__loader__ # to make sure we actually handled the import
  207. def test_main():
  208. test_support.run_unittest(ImportHooksTestCase)
  209. if __name__ == "__main__":
  210. test_main()