blob: 9e1e8842a35353e78d399db10eabf251419a5998 [file] [log] [blame]
Guido van Rossume7e578f1995-08-04 04:00:20 +00001"""Import hook support.
2
3Consistent use of this module will make it possible to change the
4different mechanisms involved in loading modules independently.
5
6While the built-in module imp exports interfaces to the built-in
7module searching and loading algorithm, and it is possible to replace
8the built-in function __import__ in order to change the semantics of
9the import statement, until now it has been difficult to combine the
10effect of different __import__ hacks, like loading modules from URLs
Guido van Rossum9f5c36f1998-06-29 20:31:16 +000011by rimport.py, or restricted execution by rexec.py.
Guido van Rossume7e578f1995-08-04 04:00:20 +000012
13This module defines three new concepts:
14
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000151) A "file system hooks" class provides an interface to a filesystem.
Guido van Rossume7e578f1995-08-04 04:00:20 +000016
17One hooks class is defined (Hooks), which uses the interface provided
18by standard modules os and os.path. It should be used as the base
19class for other hooks classes.
20
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000212) A "module loader" class provides an interface to to search for a
Guido van Rossume7e578f1995-08-04 04:00:20 +000022module in a search path and to load it. It defines a method which
23searches for a module in a single directory; by overriding this method
24one can redefine the details of the search. If the directory is None,
25built-in and frozen modules are searched instead.
26
27Two module loader class are defined, both implementing the search
28strategy used by the built-in __import__ function: ModuleLoader uses
29the imp module's find_module interface, while HookableModuleLoader
30uses a file system hooks class to interact with the file system. Both
31use the imp module's load_* interfaces to actually load the module.
32
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000333) A "module importer" class provides an interface to import a
Guido van Rossume7e578f1995-08-04 04:00:20 +000034module, as well as interfaces to reload and unload a module. It also
35provides interfaces to install and uninstall itself instead of the
36default __import__ and reload (and unload) functions.
37
38One module importer class is defined (ModuleImporter), which uses a
39module loader instance passed in (by default HookableModuleLoader is
40instantiated).
41
42The classes defined here should be used as base classes for extended
43functionality along those lines.
44
Skip Montanaro2dd42762001-01-23 15:35:05 +000045If a module importer class supports dotted names, its import_module()
Guido van Rossume7e578f1995-08-04 04:00:20 +000046must return a different value depending on whether it is called on
47behalf of a "from ... import ..." statement or not. (This is caused
48by the way the __import__ hook is used by the Python interpreter.) It
49would also do wise to install a different version of reload().
50
Guido van Rossume7e578f1995-08-04 04:00:20 +000051"""
52
53
54import __builtin__
55import imp
56import os
57import sys
Guido van Rossum9f5c36f1998-06-29 20:31:16 +000058import string
59
Skip Montanaro2dd42762001-01-23 15:35:05 +000060__all__ = ["BasicModuleLoader","Hooks","ModuleLoader","FancyModuleLoader",
61 "BasicModuleImporter","ModuleImporter","install","uninstall"]
Guido van Rossum9f5c36f1998-06-29 20:31:16 +000062
63VERBOSE = 0
Guido van Rossume7e578f1995-08-04 04:00:20 +000064
65
66from imp import C_EXTENSION, PY_SOURCE, PY_COMPILED
Guido van Rossum9f5c36f1998-06-29 20:31:16 +000067from imp import C_BUILTIN, PY_FROZEN, PKG_DIRECTORY
68BUILTIN_MODULE = C_BUILTIN
69FROZEN_MODULE = PY_FROZEN
Guido van Rossume7e578f1995-08-04 04:00:20 +000070
71
72class _Verbose:
73
Guido van Rossum9f5c36f1998-06-29 20:31:16 +000074 def __init__(self, verbose = VERBOSE):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000075 self.verbose = verbose
Guido van Rossume7e578f1995-08-04 04:00:20 +000076
77 def get_verbose(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000078 return self.verbose
Guido van Rossume7e578f1995-08-04 04:00:20 +000079
80 def set_verbose(self, verbose):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000081 self.verbose = verbose
Guido van Rossume7e578f1995-08-04 04:00:20 +000082
83 # XXX The following is an experimental interface
84
85 def note(self, *args):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000086 if self.verbose:
87 apply(self.message, args)
Guido van Rossume7e578f1995-08-04 04:00:20 +000088
89 def message(self, format, *args):
Guido van Rossum9f5c36f1998-06-29 20:31:16 +000090 if args:
91 print format%args
92 else:
93 print format
Guido van Rossume7e578f1995-08-04 04:00:20 +000094
95
96class BasicModuleLoader(_Verbose):
97
98 """Basic module loader.
99
100 This provides the same functionality as built-in import. It
101 doesn't deal with checking sys.modules -- all it provides is
102 find_module() and a load_module(), as well as find_module_in_dir()
103 which searches just one directory, and can be overridden by a
104 derived class to change the module search algorithm when the basic
105 dependency on sys.path is unchanged.
106
107 The interface is a little more convenient than imp's:
108 find_module(name, [path]) returns None or 'stuff', and
109 load_module(name, stuff) loads the module.
110
111 """
112
113 def find_module(self, name, path = None):
Tim Peters07e99cb2001-01-14 23:47:14 +0000114 if path is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000115 path = [None] + self.default_path()
116 for dir in path:
117 stuff = self.find_module_in_dir(name, dir)
118 if stuff: return stuff
119 return None
Guido van Rossume7e578f1995-08-04 04:00:20 +0000120
121 def default_path(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000122 return sys.path
Guido van Rossume7e578f1995-08-04 04:00:20 +0000123
124 def find_module_in_dir(self, name, dir):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000125 if dir is None:
126 return self.find_builtin_module(name)
127 else:
128 try:
129 return imp.find_module(name, [dir])
130 except ImportError:
131 return None
Guido van Rossume7e578f1995-08-04 04:00:20 +0000132
133 def find_builtin_module(self, name):
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000134 # XXX frozen packages?
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000135 if imp.is_builtin(name):
136 return None, '', ('', '', BUILTIN_MODULE)
137 if imp.is_frozen(name):
138 return None, '', ('', '', FROZEN_MODULE)
139 return None
Guido van Rossume7e578f1995-08-04 04:00:20 +0000140
141 def load_module(self, name, stuff):
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000142 file, filename, info = stuff
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000143 try:
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000144 return imp.load_module(name, file, filename, info)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000145 finally:
146 if file: file.close()
Guido van Rossume7e578f1995-08-04 04:00:20 +0000147
148
149class Hooks(_Verbose):
150
151 """Hooks into the filesystem and interpreter.
152
153 By deriving a subclass you can redefine your filesystem interface,
154 e.g. to merge it with the URL space.
155
156 This base class behaves just like the native filesystem.
157
158 """
159
160 # imp interface
161 def get_suffixes(self): return imp.get_suffixes()
162 def new_module(self, name): return imp.new_module(name)
163 def is_builtin(self, name): return imp.is_builtin(name)
164 def init_builtin(self, name): return imp.init_builtin(name)
165 def is_frozen(self, name): return imp.is_frozen(name)
166 def init_frozen(self, name): return imp.init_frozen(name)
167 def get_frozen_object(self, name): return imp.get_frozen_object(name)
168 def load_source(self, name, filename, file=None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000169 return imp.load_source(name, filename, file)
Guido van Rossume7e578f1995-08-04 04:00:20 +0000170 def load_compiled(self, name, filename, file=None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000171 return imp.load_compiled(name, filename, file)
Guido van Rossume7e578f1995-08-04 04:00:20 +0000172 def load_dynamic(self, name, filename, file=None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000173 return imp.load_dynamic(name, filename, file)
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000174 def load_package(self, name, filename, file=None):
175 return imp.load_module(name, file, filename, ("", "", PKG_DIRECTORY))
Guido van Rossume7e578f1995-08-04 04:00:20 +0000176
177 def add_module(self, name):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000178 d = self.modules_dict()
179 if d.has_key(name): return d[name]
180 d[name] = m = self.new_module(name)
181 return m
Guido van Rossume7e578f1995-08-04 04:00:20 +0000182
183 # sys interface
184 def modules_dict(self): return sys.modules
185 def default_path(self): return sys.path
186
187 def path_split(self, x): return os.path.split(x)
188 def path_join(self, x, y): return os.path.join(x, y)
189 def path_isabs(self, x): return os.path.isabs(x)
190 # etc.
191
192 def path_exists(self, x): return os.path.exists(x)
193 def path_isdir(self, x): return os.path.isdir(x)
194 def path_isfile(self, x): return os.path.isfile(x)
195 def path_islink(self, x): return os.path.islink(x)
196 # etc.
197
198 def openfile(self, *x): return apply(open, x)
199 openfile_error = IOError
200 def listdir(self, x): return os.listdir(x)
201 listdir_error = os.error
202 # etc.
203
204
205class ModuleLoader(BasicModuleLoader):
206
207 """Default module loader; uses file system hooks.
208
209 By defining suitable hooks, you might be able to load modules from
210 other sources than the file system, e.g. from compressed or
211 encrypted files, tar files or (if you're brave!) URLs.
212
213 """
214
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000215 def __init__(self, hooks = None, verbose = VERBOSE):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000216 BasicModuleLoader.__init__(self, verbose)
217 self.hooks = hooks or Hooks(verbose)
Guido van Rossume7e578f1995-08-04 04:00:20 +0000218
219 def default_path(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000220 return self.hooks.default_path()
Guido van Rossume7e578f1995-08-04 04:00:20 +0000221
222 def modules_dict(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000223 return self.hooks.modules_dict()
Guido van Rossume7e578f1995-08-04 04:00:20 +0000224
225 def get_hooks(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000226 return self.hooks
Guido van Rossume7e578f1995-08-04 04:00:20 +0000227
228 def set_hooks(self, hooks):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000229 self.hooks = hooks
Guido van Rossume7e578f1995-08-04 04:00:20 +0000230
231 def find_builtin_module(self, name):
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000232 # XXX frozen packages?
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000233 if self.hooks.is_builtin(name):
234 return None, '', ('', '', BUILTIN_MODULE)
235 if self.hooks.is_frozen(name):
236 return None, '', ('', '', FROZEN_MODULE)
237 return None
Guido van Rossume7e578f1995-08-04 04:00:20 +0000238
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000239 def find_module_in_dir(self, name, dir, allow_packages=1):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000240 if dir is None:
241 return self.find_builtin_module(name)
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000242 if allow_packages:
243 fullname = self.hooks.path_join(dir, name)
244 if self.hooks.path_isdir(fullname):
245 stuff = self.find_module_in_dir("__init__", fullname, 0)
246 if stuff:
247 file = stuff[0]
248 if file: file.close()
249 return None, fullname, ('', '', PKG_DIRECTORY)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000250 for info in self.hooks.get_suffixes():
251 suff, mode, type = info
252 fullname = self.hooks.path_join(dir, name+suff)
253 try:
254 fp = self.hooks.openfile(fullname, mode)
255 return fp, fullname, info
256 except self.hooks.openfile_error:
257 pass
258 return None
Guido van Rossume7e578f1995-08-04 04:00:20 +0000259
260 def load_module(self, name, stuff):
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000261 file, filename, info = stuff
262 (suff, mode, type) = info
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000263 try:
264 if type == BUILTIN_MODULE:
265 return self.hooks.init_builtin(name)
266 if type == FROZEN_MODULE:
267 return self.hooks.init_frozen(name)
268 if type == C_EXTENSION:
269 m = self.hooks.load_dynamic(name, filename, file)
270 elif type == PY_SOURCE:
271 m = self.hooks.load_source(name, filename, file)
272 elif type == PY_COMPILED:
273 m = self.hooks.load_compiled(name, filename, file)
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000274 elif type == PKG_DIRECTORY:
275 m = self.hooks.load_package(name, filename, file)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000276 else:
277 raise ImportError, "Unrecognized module type (%s) for %s" % \
278 (`type`, name)
279 finally:
280 if file: file.close()
281 m.__file__ = filename
282 return m
Guido van Rossume7e578f1995-08-04 04:00:20 +0000283
284
285class FancyModuleLoader(ModuleLoader):
286
287 """Fancy module loader -- parses and execs the code itself."""
288
289 def load_module(self, name, stuff):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000290 file, filename, (suff, mode, type) = stuff
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000291 realfilename = filename
292 path = None
293
294 if type == PKG_DIRECTORY:
295 initstuff = self.find_module_in_dir("__init__", filename, 0)
296 if not initstuff:
297 raise ImportError, "No __init__ module in package %s" % name
298 initfile, initfilename, initinfo = initstuff
299 initsuff, initmode, inittype = initinfo
300 if inittype not in (PY_COMPILED, PY_SOURCE):
301 if initfile: initfile.close()
302 raise ImportError, \
303 "Bad type (%s) for __init__ module in package %s" % (
304 `inittype`, name)
305 path = [filename]
306 file = initfile
307 realfilename = initfilename
308 type = inittype
309
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000310 if type == FROZEN_MODULE:
311 code = self.hooks.get_frozen_object(name)
312 elif type == PY_COMPILED:
313 import marshal
314 file.seek(8)
315 code = marshal.load(file)
316 elif type == PY_SOURCE:
317 data = file.read()
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000318 code = compile(data, realfilename, 'exec')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000319 else:
320 return ModuleLoader.load_module(self, name, stuff)
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000321
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000322 m = self.hooks.add_module(name)
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000323 if path:
324 m.__path__ = path
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000325 m.__file__ = filename
326 exec code in m.__dict__
327 return m
Guido van Rossume7e578f1995-08-04 04:00:20 +0000328
329
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000330class BasicModuleImporter(_Verbose):
Guido van Rossume7e578f1995-08-04 04:00:20 +0000331
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000332 """Basic module importer; uses module loader.
Guido van Rossume7e578f1995-08-04 04:00:20 +0000333
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000334 This provides basic import facilities but no package imports.
Guido van Rossume7e578f1995-08-04 04:00:20 +0000335
336 """
337
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000338 def __init__(self, loader = None, verbose = VERBOSE):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000339 _Verbose.__init__(self, verbose)
340 self.loader = loader or ModuleLoader(None, verbose)
341 self.modules = self.loader.modules_dict()
Guido van Rossume7e578f1995-08-04 04:00:20 +0000342
343 def get_loader(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000344 return self.loader
Guido van Rossume7e578f1995-08-04 04:00:20 +0000345
346 def set_loader(self, loader):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000347 self.loader = loader
Guido van Rossume7e578f1995-08-04 04:00:20 +0000348
349 def get_hooks(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000350 return self.loader.get_hooks()
Guido van Rossume7e578f1995-08-04 04:00:20 +0000351
352 def set_hooks(self, hooks):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000353 return self.loader.set_hooks(hooks)
Guido van Rossume7e578f1995-08-04 04:00:20 +0000354
355 def import_module(self, name, globals={}, locals={}, fromlist=[]):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000356 if self.modules.has_key(name):
357 return self.modules[name] # Fast path
358 stuff = self.loader.find_module(name)
359 if not stuff:
360 raise ImportError, "No module named %s" % name
361 return self.loader.load_module(name, stuff)
Guido van Rossume7e578f1995-08-04 04:00:20 +0000362
363 def reload(self, module, path = None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000364 name = module.__name__
365 stuff = self.loader.find_module(name, path)
366 if not stuff:
367 raise ImportError, "Module %s not found for reload" % name
368 return self.loader.load_module(name, stuff)
Guido van Rossume7e578f1995-08-04 04:00:20 +0000369
370 def unload(self, module):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000371 del self.modules[module.__name__]
372 # XXX Should this try to clear the module's namespace?
Guido van Rossume7e578f1995-08-04 04:00:20 +0000373
374 def install(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000375 self.save_import_module = __builtin__.__import__
376 self.save_reload = __builtin__.reload
377 if not hasattr(__builtin__, 'unload'):
378 __builtin__.unload = None
379 self.save_unload = __builtin__.unload
380 __builtin__.__import__ = self.import_module
381 __builtin__.reload = self.reload
382 __builtin__.unload = self.unload
Guido van Rossume7e578f1995-08-04 04:00:20 +0000383
384 def uninstall(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000385 __builtin__.__import__ = self.save_import_module
386 __builtin__.reload = self.save_reload
387 __builtin__.unload = self.save_unload
388 if not __builtin__.unload:
389 del __builtin__.unload
Guido van Rossume7e578f1995-08-04 04:00:20 +0000390
391
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000392class ModuleImporter(BasicModuleImporter):
393
394 """A module importer that supports packages."""
Tim Peters07e99cb2001-01-14 23:47:14 +0000395
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000396 def import_module(self, name, globals=None, locals=None, fromlist=None):
397 parent = self.determine_parent(globals)
398 q, tail = self.find_head_package(parent, name)
399 m = self.load_tail(q, tail)
400 if not fromlist:
401 return q
402 if hasattr(m, "__path__"):
403 self.ensure_fromlist(m, fromlist)
404 return m
405
406 def determine_parent(self, globals):
407 if not globals or not globals.has_key("__name__"):
408 return None
409 pname = globals['__name__']
410 if globals.has_key("__path__"):
411 parent = self.modules[pname]
412 assert globals is parent.__dict__
413 return parent
414 if '.' in pname:
415 i = string.rfind(pname, '.')
416 pname = pname[:i]
417 parent = self.modules[pname]
418 assert parent.__name__ == pname
419 return parent
420 return None
421
422 def find_head_package(self, parent, name):
423 if '.' in name:
424 i = string.find(name, '.')
425 head = name[:i]
426 tail = name[i+1:]
427 else:
428 head = name
429 tail = ""
430 if parent:
431 qname = "%s.%s" % (parent.__name__, head)
432 else:
433 qname = head
434 q = self.import_it(head, qname, parent)
435 if q: return q, tail
436 if parent:
437 qname = head
438 parent = None
439 q = self.import_it(head, qname, parent)
440 if q: return q, tail
441 raise ImportError, "No module named " + qname
442
443 def load_tail(self, q, tail):
444 m = q
445 while tail:
446 i = string.find(tail, '.')
447 if i < 0: i = len(tail)
448 head, tail = tail[:i], tail[i+1:]
449 mname = "%s.%s" % (m.__name__, head)
450 m = self.import_it(head, mname, m)
451 if not m:
452 raise ImportError, "No module named " + mname
453 return m
454
455 def ensure_fromlist(self, m, fromlist, recursive=0):
456 for sub in fromlist:
457 if sub == "*":
458 if not recursive:
459 try:
460 all = m.__all__
461 except AttributeError:
462 pass
463 else:
464 self.ensure_fromlist(m, all, 1)
465 continue
466 if sub != "*" and not hasattr(m, sub):
467 subname = "%s.%s" % (m.__name__, sub)
468 submod = self.import_it(sub, subname, m)
469 if not submod:
470 raise ImportError, "No module named " + subname
471
Fred Drake8deeced2000-04-13 14:52:27 +0000472 def import_it(self, partname, fqname, parent, force_load=0):
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000473 if not partname:
474 raise ValueError, "Empty module name"
Fred Drake8deeced2000-04-13 14:52:27 +0000475 if not force_load:
476 try:
477 return self.modules[fqname]
478 except KeyError:
479 pass
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000480 try:
481 path = parent and parent.__path__
482 except AttributeError:
483 return None
484 stuff = self.loader.find_module(partname, path)
485 if not stuff:
486 return None
487 m = self.loader.load_module(fqname, stuff)
488 if parent:
489 setattr(parent, partname, m)
490 return m
491
492 def reload(self, module):
493 name = module.__name__
494 if '.' not in name:
Fred Drake8deeced2000-04-13 14:52:27 +0000495 return self.import_it(name, name, None, force_load=1)
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000496 i = string.rfind(name, '.')
497 pname = name[:i]
498 parent = self.modules[pname]
Fred Drake8deeced2000-04-13 14:52:27 +0000499 return self.import_it(name[i+1:], name, parent, force_load=1)
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000500
501
Guido van Rossume7e578f1995-08-04 04:00:20 +0000502default_importer = None
503current_importer = None
504
505def install(importer = None):
506 global current_importer
507 current_importer = importer or default_importer or ModuleImporter()
508 current_importer.install()
509
510def uninstall():
511 global current_importer
512 current_importer.uninstall()