blob: d31bcb2120e9705ab8a40f2e73f766a5023cae10 [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"
Thomas Wouters477c8d52006-05-27 19:21:47 +000017deeprelimp = "from .... import sub\n"
Thomas Woutersf7f438b2006-02-28 16:09:29 +000018futimp = "from __future__ import absolute_import\n"
19
Phillip J. Eby7ec642a2004-09-23 04:37:36 +000020reload_src = test_src+"""\
21reloaded = True
22"""
23
Just van Rossum52e14d62002-12-30 22:08:05 +000024test_co = compile(test_src, "<???>", "exec")
Phillip J. Eby7ec642a2004-09-23 04:37:36 +000025reload_co = compile(reload_src, "<???>", "exec")
26
Thomas Woutersf7f438b2006-02-28 16:09:29 +000027test2_oldabs_co = compile(absimp + test_src, "<???>", "exec")
28test2_newabs_co = compile(futimp + absimp + test_src, "<???>", "exec")
29test2_newrel_co = compile(relimp + test_src, "<???>", "exec")
Thomas Wouters477c8d52006-05-27 19:21:47 +000030test2_deeprel_co = compile(deeprelimp + test_src, "<???>", "exec")
Thomas Woutersf7f438b2006-02-28 16:09:29 +000031test2_futrel_co = compile(futimp + relimp + test_src, "<???>", "exec")
32
Just van Rossum52e14d62002-12-30 22:08:05 +000033test_path = "!!!_test_!!!"
34
35
36class ImportTracker:
37 """Importer that only tracks attempted imports."""
38 def __init__(self):
39 self.imports = []
40 def find_module(self, fullname, path=None):
41 self.imports.append(fullname)
42 return None
43
44
45class TestImporter:
46
47 modules = {
48 "hooktestmodule": (False, test_co),
49 "hooktestpackage": (True, test_co),
50 "hooktestpackage.sub": (True, test_co),
Thomas Wouters477c8d52006-05-27 19:21:47 +000051 "hooktestpackage.sub.subber": (True, test_co),
Thomas Woutersf7f438b2006-02-28 16:09:29 +000052 "hooktestpackage.oldabs": (False, test2_oldabs_co),
53 "hooktestpackage.newabs": (False, test2_newabs_co),
54 "hooktestpackage.newrel": (False, test2_newrel_co),
Thomas Wouters477c8d52006-05-27 19:21:47 +000055 "hooktestpackage.sub.subber.subest": (True, test2_deeprel_co),
Thomas Woutersf7f438b2006-02-28 16:09:29 +000056 "hooktestpackage.futrel": (False, test2_futrel_co),
57 "sub": (False, test_co),
Phillip J. Eby7ec642a2004-09-23 04:37:36 +000058 "reloadmodule": (False, test_co),
Just van Rossum52e14d62002-12-30 22:08:05 +000059 }
60
61 def __init__(self, path=test_path):
62 if path != test_path:
63 # if out class is on sys.path_hooks, we must raise
64 # ImportError for any path item that we can't handle.
65 raise ImportError
66 self.path = path
67
68 def _get__path__(self):
69 raise NotImplementedError
70
71 def find_module(self, fullname, path=None):
72 if fullname in self.modules:
73 return self
74 else:
75 return None
76
77 def load_module(self, fullname):
78 ispkg, code = self.modules[fullname]
Phillip J. Eby7ec642a2004-09-23 04:37:36 +000079 mod = sys.modules.setdefault(fullname,imp.new_module(fullname))
Just van Rossum52e14d62002-12-30 22:08:05 +000080 mod.__file__ = "<%s>" % self.__class__.__name__
81 mod.__loader__ = self
82 if ispkg:
83 mod.__path__ = self._get__path__()
84 exec code in mod.__dict__
85 return mod
86
87
88class MetaImporter(TestImporter):
89 def _get__path__(self):
90 return []
91
92class PathImporter(TestImporter):
93 def _get__path__(self):
94 return [self.path]
95
96
97class ImportBlocker:
98 """Place an ImportBlocker instance on sys.meta_path and you
99 can be sure the modules you specified can't be imported, even
100 if it's a builtin."""
101 def __init__(self, *namestoblock):
102 self.namestoblock = dict.fromkeys(namestoblock)
103 def find_module(self, fullname, path=None):
104 if fullname in self.namestoblock:
105 return self
106 return None
107 def load_module(self, fullname):
108 raise ImportError, "I dare you"
109
110
111class ImpWrapper:
112
113 def __init__(self, path=None):
114 if path is not None and not os.path.isdir(path):
115 raise ImportError
116 self.path = path
117
118 def find_module(self, fullname, path=None):
119 subname = fullname.split(".")[-1]
120 if subname != fullname and self.path is None:
121 return None
122 if self.path is None:
123 path = None
124 else:
125 path = [self.path]
126 try:
127 file, filename, stuff = imp.find_module(subname, path)
128 except ImportError:
129 return None
130 return ImpLoader(file, filename, stuff)
131
132
133class ImpLoader:
134
135 def __init__(self, file, filename, stuff):
136 self.file = file
137 self.filename = filename
138 self.stuff = stuff
139
140 def load_module(self, fullname):
141 mod = imp.load_module(fullname, self.file, self.filename, self.stuff)
142 if self.file:
143 self.file.close()
144 mod.__loader__ = self # for introspection
145 return mod
146
147
148class ImportHooksBaseTestCase(unittest.TestCase):
149
150 def setUp(self):
151 self.path = sys.path[:]
152 self.meta_path = sys.meta_path[:]
153 self.path_hooks = sys.path_hooks[:]
154 sys.path_importer_cache.clear()
155 self.tracker = ImportTracker()
156 sys.meta_path.insert(0, self.tracker)
157
158 def tearDown(self):
159 sys.path[:] = self.path
160 sys.meta_path[:] = self.meta_path
161 sys.path_hooks[:] = self.path_hooks
162 sys.path_importer_cache.clear()
163 for fullname in self.tracker.imports:
164 if fullname in sys.modules:
165 del sys.modules[fullname]
166
167
168class ImportHooksTestCase(ImportHooksBaseTestCase):
169
170 def doTestImports(self, importer=None):
171 import hooktestmodule
172 import hooktestpackage
173 import hooktestpackage.sub
174 import hooktestpackage.sub.subber
175 self.assertEqual(hooktestmodule.get_name(),
176 "hooktestmodule")
177 self.assertEqual(hooktestpackage.get_name(),
178 "hooktestpackage")
179 self.assertEqual(hooktestpackage.sub.get_name(),
180 "hooktestpackage.sub")
181 self.assertEqual(hooktestpackage.sub.subber.get_name(),
182 "hooktestpackage.sub.subber")
183 if importer:
184 self.assertEqual(hooktestmodule.__loader__, importer)
185 self.assertEqual(hooktestpackage.__loader__, importer)
186 self.assertEqual(hooktestpackage.sub.__loader__, importer)
187 self.assertEqual(hooktestpackage.sub.subber.__loader__, importer)
188
Phillip J. Eby7ec642a2004-09-23 04:37:36 +0000189 TestImporter.modules['reloadmodule'] = (False, test_co)
190 import reloadmodule
191 self.failIf(hasattr(reloadmodule,'reloaded'))
192
193 TestImporter.modules['reloadmodule'] = (False, reload_co)
194 reload(reloadmodule)
195 self.failUnless(hasattr(reloadmodule,'reloaded'))
Tim Peters710ab3b2006-02-28 18:30:36 +0000196
Thomas Woutersf7f438b2006-02-28 16:09:29 +0000197 import hooktestpackage.newrel
198 self.assertEqual(hooktestpackage.newrel.get_name(),
199 "hooktestpackage.newrel")
200 self.assertEqual(hooktestpackage.newrel.sub,
201 hooktestpackage.sub)
202
Thomas Wouters477c8d52006-05-27 19:21:47 +0000203 import hooktestpackage.sub.subber.subest as subest
204 self.assertEqual(subest.get_name(),
205 "hooktestpackage.sub.subber.subest")
206 self.assertEqual(subest.sub,
207 hooktestpackage.sub)
208
Thomas Woutersf7f438b2006-02-28 16:09:29 +0000209 import hooktestpackage.futrel
210 self.assertEqual(hooktestpackage.futrel.get_name(),
211 "hooktestpackage.futrel")
212 self.assertEqual(hooktestpackage.futrel.sub,
213 hooktestpackage.sub)
Tim Peters710ab3b2006-02-28 18:30:36 +0000214
Thomas Woutersf7f438b2006-02-28 16:09:29 +0000215 import sub
216 self.assertEqual(sub.get_name(), "sub")
217
Thomas Wouters60254fe2006-05-28 10:46:55 +0000218 import hooktestpackage.oldabs
219 self.assertEqual(hooktestpackage.oldabs.get_name(),
220 "hooktestpackage.oldabs")
221 self.assertEqual(hooktestpackage.oldabs.sub, sub)
222
Thomas Woutersf7f438b2006-02-28 16:09:29 +0000223 import hooktestpackage.newabs
224 self.assertEqual(hooktestpackage.newabs.get_name(),
225 "hooktestpackage.newabs")
226 self.assertEqual(hooktestpackage.newabs.sub, sub)
Tim Peters1cc37382004-09-24 04:36:47 +0000227
Just van Rossum52e14d62002-12-30 22:08:05 +0000228 def testMetaPath(self):
229 i = MetaImporter()
230 sys.meta_path.append(i)
231 self.doTestImports(i)
232
233 def testPathHook(self):
234 sys.path_hooks.append(PathImporter)
235 sys.path.append(test_path)
236 self.doTestImports()
237
238 def testBlocker(self):
239 mname = "exceptions" # an arbitrary harmless builtin module
240 if mname in sys.modules:
241 del sys.modules[mname]
242 sys.meta_path.append(ImportBlocker(mname))
243 try:
244 __import__(mname)
245 except ImportError:
246 pass
247 else:
248 self.fail("'%s' was not supposed to be importable" % mname)
249
250 def testImpWrapper(self):
251 i = ImpWrapper()
252 sys.meta_path.append(i)
253 sys.path_hooks.append(ImpWrapper)
254 mnames = ("colorsys", "urlparse", "distutils.core", "compiler.misc")
255 for mname in mnames:
256 parent = mname.split(".")[0]
257 for n in sys.modules.keys():
258 if n.startswith(parent):
259 del sys.modules[n]
260 for mname in mnames:
261 m = __import__(mname, globals(), locals(), ["__dummy__"])
262 m.__loader__ # to make sure we actually handled the import
Tim Peterse8d09e52006-03-09 01:15:05 +0000263 # Delete urllib from modules because urlparse was imported above.
Neal Norwitzd8cea792006-03-04 23:13:41 +0000264 # Without this hack, test_socket_ssl fails if run in this order:
265 # regrtest.py test_codecmaps_tw test_importhooks test_socket_ssl
Neal Norwitz83cbb242006-03-04 23:56:53 +0000266 try:
267 del sys.modules['urllib']
268 except KeyError:
269 pass
Just van Rossum52e14d62002-12-30 22:08:05 +0000270
Neal Norwitz996acf12003-02-17 14:51:41 +0000271def test_main():
272 test_support.run_unittest(ImportHooksTestCase)
Just van Rossum52e14d62002-12-30 22:08:05 +0000273
274if __name__ == "__main__":
Neal Norwitz996acf12003-02-17 14:51:41 +0000275 test_main()