blob: c58075543b49ef9ea4f526e8c8dbb8067dfeb06d [file] [log] [blame]
Just van Rossum52e14d62002-12-30 22:08:05 +00001import sys
2import imp
3import os
4import unittest
5from test import test_support
6
7
8test_src = """\
9def get_name():
10 return __name__
11def get_file():
12 return __file__
13"""
14
Thomas Woutersf7f438b2006-02-28 16:09:29 +000015absimp = "import sub\n"
16relimp = "from . import sub\n"
17futimp = "from __future__ import absolute_import\n"
18
Phillip J. Eby7ec642a2004-09-23 04:37:36 +000019reload_src = test_src+"""\
20reloaded = True
21"""
22
Just van Rossum52e14d62002-12-30 22:08:05 +000023test_co = compile(test_src, "<???>", "exec")
Phillip J. Eby7ec642a2004-09-23 04:37:36 +000024reload_co = compile(reload_src, "<???>", "exec")
25
Thomas Woutersf7f438b2006-02-28 16:09:29 +000026test2_oldabs_co = compile(absimp + test_src, "<???>", "exec")
27test2_newabs_co = compile(futimp + absimp + test_src, "<???>", "exec")
28test2_newrel_co = compile(relimp + test_src, "<???>", "exec")
29test2_futrel_co = compile(futimp + relimp + test_src, "<???>", "exec")
30
Just van Rossum52e14d62002-12-30 22:08:05 +000031test_path = "!!!_test_!!!"
32
33
34class ImportTracker:
35 """Importer that only tracks attempted imports."""
36 def __init__(self):
37 self.imports = []
38 def find_module(self, fullname, path=None):
39 self.imports.append(fullname)
40 return None
41
42
43class TestImporter:
44
45 modules = {
46 "hooktestmodule": (False, test_co),
47 "hooktestpackage": (True, test_co),
48 "hooktestpackage.sub": (True, test_co),
49 "hooktestpackage.sub.subber": (False, test_co),
Thomas Woutersf7f438b2006-02-28 16:09:29 +000050 "hooktestpackage.oldabs": (False, test2_oldabs_co),
51 "hooktestpackage.newabs": (False, test2_newabs_co),
52 "hooktestpackage.newrel": (False, test2_newrel_co),
53 "hooktestpackage.futrel": (False, test2_futrel_co),
54 "sub": (False, test_co),
Phillip J. Eby7ec642a2004-09-23 04:37:36 +000055 "reloadmodule": (False, test_co),
Just van Rossum52e14d62002-12-30 22:08:05 +000056 }
57
58 def __init__(self, path=test_path):
59 if path != test_path:
60 # if out class is on sys.path_hooks, we must raise
61 # ImportError for any path item that we can't handle.
62 raise ImportError
63 self.path = path
64
65 def _get__path__(self):
66 raise NotImplementedError
67
68 def find_module(self, fullname, path=None):
69 if fullname in self.modules:
70 return self
71 else:
72 return None
73
74 def load_module(self, fullname):
75 ispkg, code = self.modules[fullname]
Phillip J. Eby7ec642a2004-09-23 04:37:36 +000076 mod = sys.modules.setdefault(fullname,imp.new_module(fullname))
Just van Rossum52e14d62002-12-30 22:08:05 +000077 mod.__file__ = "<%s>" % self.__class__.__name__
78 mod.__loader__ = self
79 if ispkg:
80 mod.__path__ = self._get__path__()
81 exec code in mod.__dict__
82 return mod
83
84
85class MetaImporter(TestImporter):
86 def _get__path__(self):
87 return []
88
89class PathImporter(TestImporter):
90 def _get__path__(self):
91 return [self.path]
92
93
94class ImportBlocker:
95 """Place an ImportBlocker instance on sys.meta_path and you
96 can be sure the modules you specified can't be imported, even
97 if it's a builtin."""
98 def __init__(self, *namestoblock):
99 self.namestoblock = dict.fromkeys(namestoblock)
100 def find_module(self, fullname, path=None):
101 if fullname in self.namestoblock:
102 return self
103 return None
104 def load_module(self, fullname):
105 raise ImportError, "I dare you"
106
107
108class ImpWrapper:
109
110 def __init__(self, path=None):
111 if path is not None and not os.path.isdir(path):
112 raise ImportError
113 self.path = path
114
115 def find_module(self, fullname, path=None):
116 subname = fullname.split(".")[-1]
117 if subname != fullname and self.path is None:
118 return None
119 if self.path is None:
120 path = None
121 else:
122 path = [self.path]
123 try:
124 file, filename, stuff = imp.find_module(subname, path)
125 except ImportError:
126 return None
127 return ImpLoader(file, filename, stuff)
128
129
130class ImpLoader:
131
132 def __init__(self, file, filename, stuff):
133 self.file = file
134 self.filename = filename
135 self.stuff = stuff
136
137 def load_module(self, fullname):
138 mod = imp.load_module(fullname, self.file, self.filename, self.stuff)
139 if self.file:
140 self.file.close()
141 mod.__loader__ = self # for introspection
142 return mod
143
144
145class ImportHooksBaseTestCase(unittest.TestCase):
146
147 def setUp(self):
148 self.path = sys.path[:]
149 self.meta_path = sys.meta_path[:]
150 self.path_hooks = sys.path_hooks[:]
151 sys.path_importer_cache.clear()
152 self.tracker = ImportTracker()
153 sys.meta_path.insert(0, self.tracker)
154
155 def tearDown(self):
156 sys.path[:] = self.path
157 sys.meta_path[:] = self.meta_path
158 sys.path_hooks[:] = self.path_hooks
159 sys.path_importer_cache.clear()
160 for fullname in self.tracker.imports:
161 if fullname in sys.modules:
162 del sys.modules[fullname]
163
164
165class ImportHooksTestCase(ImportHooksBaseTestCase):
166
167 def doTestImports(self, importer=None):
168 import hooktestmodule
169 import hooktestpackage
170 import hooktestpackage.sub
171 import hooktestpackage.sub.subber
172 self.assertEqual(hooktestmodule.get_name(),
173 "hooktestmodule")
174 self.assertEqual(hooktestpackage.get_name(),
175 "hooktestpackage")
176 self.assertEqual(hooktestpackage.sub.get_name(),
177 "hooktestpackage.sub")
178 self.assertEqual(hooktestpackage.sub.subber.get_name(),
179 "hooktestpackage.sub.subber")
180 if importer:
181 self.assertEqual(hooktestmodule.__loader__, importer)
182 self.assertEqual(hooktestpackage.__loader__, importer)
183 self.assertEqual(hooktestpackage.sub.__loader__, importer)
184 self.assertEqual(hooktestpackage.sub.subber.__loader__, importer)
185
Phillip J. Eby7ec642a2004-09-23 04:37:36 +0000186 TestImporter.modules['reloadmodule'] = (False, test_co)
187 import reloadmodule
188 self.failIf(hasattr(reloadmodule,'reloaded'))
189
190 TestImporter.modules['reloadmodule'] = (False, reload_co)
191 reload(reloadmodule)
192 self.failUnless(hasattr(reloadmodule,'reloaded'))
Thomas Woutersf7f438b2006-02-28 16:09:29 +0000193
194 import hooktestpackage.oldabs
195 self.assertEqual(hooktestpackage.oldabs.get_name(),
196 "hooktestpackage.oldabs")
197 self.assertEqual(hooktestpackage.oldabs.sub,
198 hooktestpackage.sub)
199
200 import hooktestpackage.newrel
201 self.assertEqual(hooktestpackage.newrel.get_name(),
202 "hooktestpackage.newrel")
203 self.assertEqual(hooktestpackage.newrel.sub,
204 hooktestpackage.sub)
205
206 import hooktestpackage.futrel
207 self.assertEqual(hooktestpackage.futrel.get_name(),
208 "hooktestpackage.futrel")
209 self.assertEqual(hooktestpackage.futrel.sub,
210 hooktestpackage.sub)
211
212 import sub
213 self.assertEqual(sub.get_name(), "sub")
214
215 import hooktestpackage.newabs
216 self.assertEqual(hooktestpackage.newabs.get_name(),
217 "hooktestpackage.newabs")
218 self.assertEqual(hooktestpackage.newabs.sub, sub)
Tim Peters1cc37382004-09-24 04:36:47 +0000219
Just van Rossum52e14d62002-12-30 22:08:05 +0000220 def testMetaPath(self):
221 i = MetaImporter()
222 sys.meta_path.append(i)
223 self.doTestImports(i)
224
225 def testPathHook(self):
226 sys.path_hooks.append(PathImporter)
227 sys.path.append(test_path)
228 self.doTestImports()
229
230 def testBlocker(self):
231 mname = "exceptions" # an arbitrary harmless builtin module
232 if mname in sys.modules:
233 del sys.modules[mname]
234 sys.meta_path.append(ImportBlocker(mname))
235 try:
236 __import__(mname)
237 except ImportError:
238 pass
239 else:
240 self.fail("'%s' was not supposed to be importable" % mname)
241
242 def testImpWrapper(self):
243 i = ImpWrapper()
244 sys.meta_path.append(i)
245 sys.path_hooks.append(ImpWrapper)
246 mnames = ("colorsys", "urlparse", "distutils.core", "compiler.misc")
247 for mname in mnames:
248 parent = mname.split(".")[0]
249 for n in sys.modules.keys():
250 if n.startswith(parent):
251 del sys.modules[n]
252 for mname in mnames:
253 m = __import__(mname, globals(), locals(), ["__dummy__"])
254 m.__loader__ # to make sure we actually handled the import
255
Neal Norwitz996acf12003-02-17 14:51:41 +0000256def test_main():
257 test_support.run_unittest(ImportHooksTestCase)
Just van Rossum52e14d62002-12-30 22:08:05 +0000258
259if __name__ == "__main__":
Neal Norwitz996acf12003-02-17 14:51:41 +0000260 test_main()