blob: 5c9adfe82bed4993465dd3ea5f39a121ddf276d7 [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
45If a module mporter class supports dotted names, its import_module()
46must 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
60
61VERBOSE = 0
Guido van Rossume7e578f1995-08-04 04:00:20 +000062
63
64from imp import C_EXTENSION, PY_SOURCE, PY_COMPILED
Guido van Rossum9f5c36f1998-06-29 20:31:16 +000065from imp import C_BUILTIN, PY_FROZEN, PKG_DIRECTORY
66BUILTIN_MODULE = C_BUILTIN
67FROZEN_MODULE = PY_FROZEN
Guido van Rossume7e578f1995-08-04 04:00:20 +000068
69
70class _Verbose:
71
Guido van Rossum9f5c36f1998-06-29 20:31:16 +000072 def __init__(self, verbose = VERBOSE):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000073 self.verbose = verbose
Guido van Rossume7e578f1995-08-04 04:00:20 +000074
75 def get_verbose(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000076 return self.verbose
Guido van Rossume7e578f1995-08-04 04:00:20 +000077
78 def set_verbose(self, verbose):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000079 self.verbose = verbose
Guido van Rossume7e578f1995-08-04 04:00:20 +000080
81 # XXX The following is an experimental interface
82
83 def note(self, *args):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000084 if self.verbose:
85 apply(self.message, args)
Guido van Rossume7e578f1995-08-04 04:00:20 +000086
87 def message(self, format, *args):
Guido van Rossum9f5c36f1998-06-29 20:31:16 +000088 if args:
89 print format%args
90 else:
91 print format
Guido van Rossume7e578f1995-08-04 04:00:20 +000092
93
94class BasicModuleLoader(_Verbose):
95
96 """Basic module loader.
97
98 This provides the same functionality as built-in import. It
99 doesn't deal with checking sys.modules -- all it provides is
100 find_module() and a load_module(), as well as find_module_in_dir()
101 which searches just one directory, and can be overridden by a
102 derived class to change the module search algorithm when the basic
103 dependency on sys.path is unchanged.
104
105 The interface is a little more convenient than imp's:
106 find_module(name, [path]) returns None or 'stuff', and
107 load_module(name, stuff) loads the module.
108
109 """
110
111 def find_module(self, name, path = None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000112 if path is None:
113 path = [None] + self.default_path()
114 for dir in path:
115 stuff = self.find_module_in_dir(name, dir)
116 if stuff: return stuff
117 return None
Guido van Rossume7e578f1995-08-04 04:00:20 +0000118
119 def default_path(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000120 return sys.path
Guido van Rossume7e578f1995-08-04 04:00:20 +0000121
122 def find_module_in_dir(self, name, dir):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000123 if dir is None:
124 return self.find_builtin_module(name)
125 else:
126 try:
127 return imp.find_module(name, [dir])
128 except ImportError:
129 return None
Guido van Rossume7e578f1995-08-04 04:00:20 +0000130
131 def find_builtin_module(self, name):
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000132 # XXX frozen packages?
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000133 if imp.is_builtin(name):
134 return None, '', ('', '', BUILTIN_MODULE)
135 if imp.is_frozen(name):
136 return None, '', ('', '', FROZEN_MODULE)
137 return None
Guido van Rossume7e578f1995-08-04 04:00:20 +0000138
139 def load_module(self, name, stuff):
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000140 file, filename, info = stuff
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000141 try:
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000142 return imp.load_module(name, file, filename, info)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000143 finally:
144 if file: file.close()
Guido van Rossume7e578f1995-08-04 04:00:20 +0000145
146
147class Hooks(_Verbose):
148
149 """Hooks into the filesystem and interpreter.
150
151 By deriving a subclass you can redefine your filesystem interface,
152 e.g. to merge it with the URL space.
153
154 This base class behaves just like the native filesystem.
155
156 """
157
158 # imp interface
159 def get_suffixes(self): return imp.get_suffixes()
160 def new_module(self, name): return imp.new_module(name)
161 def is_builtin(self, name): return imp.is_builtin(name)
162 def init_builtin(self, name): return imp.init_builtin(name)
163 def is_frozen(self, name): return imp.is_frozen(name)
164 def init_frozen(self, name): return imp.init_frozen(name)
165 def get_frozen_object(self, name): return imp.get_frozen_object(name)
166 def load_source(self, name, filename, file=None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000167 return imp.load_source(name, filename, file)
Guido van Rossume7e578f1995-08-04 04:00:20 +0000168 def load_compiled(self, name, filename, file=None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000169 return imp.load_compiled(name, filename, file)
Guido van Rossume7e578f1995-08-04 04:00:20 +0000170 def load_dynamic(self, name, filename, file=None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000171 return imp.load_dynamic(name, filename, file)
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000172 def load_package(self, name, filename, file=None):
173 return imp.load_module(name, file, filename, ("", "", PKG_DIRECTORY))
Guido van Rossume7e578f1995-08-04 04:00:20 +0000174
175 def add_module(self, name):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000176 d = self.modules_dict()
177 if d.has_key(name): return d[name]
178 d[name] = m = self.new_module(name)
179 return m
Guido van Rossume7e578f1995-08-04 04:00:20 +0000180
181 # sys interface
182 def modules_dict(self): return sys.modules
183 def default_path(self): return sys.path
184
185 def path_split(self, x): return os.path.split(x)
186 def path_join(self, x, y): return os.path.join(x, y)
187 def path_isabs(self, x): return os.path.isabs(x)
188 # etc.
189
190 def path_exists(self, x): return os.path.exists(x)
191 def path_isdir(self, x): return os.path.isdir(x)
192 def path_isfile(self, x): return os.path.isfile(x)
193 def path_islink(self, x): return os.path.islink(x)
194 # etc.
195
196 def openfile(self, *x): return apply(open, x)
197 openfile_error = IOError
198 def listdir(self, x): return os.listdir(x)
199 listdir_error = os.error
200 # etc.
201
202
203class ModuleLoader(BasicModuleLoader):
204
205 """Default module loader; uses file system hooks.
206
207 By defining suitable hooks, you might be able to load modules from
208 other sources than the file system, e.g. from compressed or
209 encrypted files, tar files or (if you're brave!) URLs.
210
211 """
212
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000213 def __init__(self, hooks = None, verbose = VERBOSE):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000214 BasicModuleLoader.__init__(self, verbose)
215 self.hooks = hooks or Hooks(verbose)
Guido van Rossume7e578f1995-08-04 04:00:20 +0000216
217 def default_path(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000218 return self.hooks.default_path()
Guido van Rossume7e578f1995-08-04 04:00:20 +0000219
220 def modules_dict(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000221 return self.hooks.modules_dict()
Guido van Rossume7e578f1995-08-04 04:00:20 +0000222
223 def get_hooks(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000224 return self.hooks
Guido van Rossume7e578f1995-08-04 04:00:20 +0000225
226 def set_hooks(self, hooks):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000227 self.hooks = hooks
Guido van Rossume7e578f1995-08-04 04:00:20 +0000228
229 def find_builtin_module(self, name):
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000230 # XXX frozen packages?
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000231 if self.hooks.is_builtin(name):
232 return None, '', ('', '', BUILTIN_MODULE)
233 if self.hooks.is_frozen(name):
234 return None, '', ('', '', FROZEN_MODULE)
235 return None
Guido van Rossume7e578f1995-08-04 04:00:20 +0000236
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000237 def find_module_in_dir(self, name, dir, allow_packages=1):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000238 if dir is None:
239 return self.find_builtin_module(name)
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000240 if allow_packages:
241 fullname = self.hooks.path_join(dir, name)
242 if self.hooks.path_isdir(fullname):
243 stuff = self.find_module_in_dir("__init__", fullname, 0)
244 if stuff:
245 file = stuff[0]
246 if file: file.close()
247 return None, fullname, ('', '', PKG_DIRECTORY)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000248 for info in self.hooks.get_suffixes():
249 suff, mode, type = info
250 fullname = self.hooks.path_join(dir, name+suff)
251 try:
252 fp = self.hooks.openfile(fullname, mode)
253 return fp, fullname, info
254 except self.hooks.openfile_error:
255 pass
256 return None
Guido van Rossume7e578f1995-08-04 04:00:20 +0000257
258 def load_module(self, name, stuff):
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000259 file, filename, info = stuff
260 (suff, mode, type) = info
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000261 try:
262 if type == BUILTIN_MODULE:
263 return self.hooks.init_builtin(name)
264 if type == FROZEN_MODULE:
265 return self.hooks.init_frozen(name)
266 if type == C_EXTENSION:
267 m = self.hooks.load_dynamic(name, filename, file)
268 elif type == PY_SOURCE:
269 m = self.hooks.load_source(name, filename, file)
270 elif type == PY_COMPILED:
271 m = self.hooks.load_compiled(name, filename, file)
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000272 elif type == PKG_DIRECTORY:
273 m = self.hooks.load_package(name, filename, file)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000274 else:
275 raise ImportError, "Unrecognized module type (%s) for %s" % \
276 (`type`, name)
277 finally:
278 if file: file.close()
279 m.__file__ = filename
280 return m
Guido van Rossume7e578f1995-08-04 04:00:20 +0000281
282
283class FancyModuleLoader(ModuleLoader):
284
285 """Fancy module loader -- parses and execs the code itself."""
286
287 def load_module(self, name, stuff):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000288 file, filename, (suff, mode, type) = stuff
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000289 realfilename = filename
290 path = None
291
292 if type == PKG_DIRECTORY:
293 initstuff = self.find_module_in_dir("__init__", filename, 0)
294 if not initstuff:
295 raise ImportError, "No __init__ module in package %s" % name
296 initfile, initfilename, initinfo = initstuff
297 initsuff, initmode, inittype = initinfo
298 if inittype not in (PY_COMPILED, PY_SOURCE):
299 if initfile: initfile.close()
300 raise ImportError, \
301 "Bad type (%s) for __init__ module in package %s" % (
302 `inittype`, name)
303 path = [filename]
304 file = initfile
305 realfilename = initfilename
306 type = inittype
307
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000308 if type == FROZEN_MODULE:
309 code = self.hooks.get_frozen_object(name)
310 elif type == PY_COMPILED:
311 import marshal
312 file.seek(8)
313 code = marshal.load(file)
314 elif type == PY_SOURCE:
315 data = file.read()
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000316 code = compile(data, realfilename, 'exec')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000317 else:
318 return ModuleLoader.load_module(self, name, stuff)
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000319
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000320 m = self.hooks.add_module(name)
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000321 if path:
322 m.__path__ = path
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000323 m.__file__ = filename
324 exec code in m.__dict__
325 return m
Guido van Rossume7e578f1995-08-04 04:00:20 +0000326
327
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000328class BasicModuleImporter(_Verbose):
Guido van Rossume7e578f1995-08-04 04:00:20 +0000329
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000330 """Basic module importer; uses module loader.
Guido van Rossume7e578f1995-08-04 04:00:20 +0000331
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000332 This provides basic import facilities but no package imports.
Guido van Rossume7e578f1995-08-04 04:00:20 +0000333
334 """
335
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000336 def __init__(self, loader = None, verbose = VERBOSE):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000337 _Verbose.__init__(self, verbose)
338 self.loader = loader or ModuleLoader(None, verbose)
339 self.modules = self.loader.modules_dict()
Guido van Rossume7e578f1995-08-04 04:00:20 +0000340
341 def get_loader(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000342 return self.loader
Guido van Rossume7e578f1995-08-04 04:00:20 +0000343
344 def set_loader(self, loader):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000345 self.loader = loader
Guido van Rossume7e578f1995-08-04 04:00:20 +0000346
347 def get_hooks(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000348 return self.loader.get_hooks()
Guido van Rossume7e578f1995-08-04 04:00:20 +0000349
350 def set_hooks(self, hooks):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000351 return self.loader.set_hooks(hooks)
Guido van Rossume7e578f1995-08-04 04:00:20 +0000352
353 def import_module(self, name, globals={}, locals={}, fromlist=[]):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000354 if self.modules.has_key(name):
355 return self.modules[name] # Fast path
356 stuff = self.loader.find_module(name)
357 if not stuff:
358 raise ImportError, "No module named %s" % name
359 return self.loader.load_module(name, stuff)
Guido van Rossume7e578f1995-08-04 04:00:20 +0000360
361 def reload(self, module, path = None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000362 name = module.__name__
363 stuff = self.loader.find_module(name, path)
364 if not stuff:
365 raise ImportError, "Module %s not found for reload" % name
366 return self.loader.load_module(name, stuff)
Guido van Rossume7e578f1995-08-04 04:00:20 +0000367
368 def unload(self, module):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000369 del self.modules[module.__name__]
370 # XXX Should this try to clear the module's namespace?
Guido van Rossume7e578f1995-08-04 04:00:20 +0000371
372 def install(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000373 self.save_import_module = __builtin__.__import__
374 self.save_reload = __builtin__.reload
375 if not hasattr(__builtin__, 'unload'):
376 __builtin__.unload = None
377 self.save_unload = __builtin__.unload
378 __builtin__.__import__ = self.import_module
379 __builtin__.reload = self.reload
380 __builtin__.unload = self.unload
Guido van Rossume7e578f1995-08-04 04:00:20 +0000381
382 def uninstall(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000383 __builtin__.__import__ = self.save_import_module
384 __builtin__.reload = self.save_reload
385 __builtin__.unload = self.save_unload
386 if not __builtin__.unload:
387 del __builtin__.unload
Guido van Rossume7e578f1995-08-04 04:00:20 +0000388
389
Guido van Rossum9f5c36f1998-06-29 20:31:16 +0000390class ModuleImporter(BasicModuleImporter):
391
392 """A module importer that supports packages."""
393
394 def import_module(self, name, globals=None, locals=None, fromlist=None):
395 parent = self.determine_parent(globals)
396 q, tail = self.find_head_package(parent, name)
397 m = self.load_tail(q, tail)
398 if not fromlist:
399 return q
400 if hasattr(m, "__path__"):
401 self.ensure_fromlist(m, fromlist)
402 return m
403
404 def determine_parent(self, globals):
405 if not globals or not globals.has_key("__name__"):
406 return None
407 pname = globals['__name__']
408 if globals.has_key("__path__"):
409 parent = self.modules[pname]
410 assert globals is parent.__dict__
411 return parent
412 if '.' in pname:
413 i = string.rfind(pname, '.')
414 pname = pname[:i]
415 parent = self.modules[pname]
416 assert parent.__name__ == pname
417 return parent
418 return None
419
420 def find_head_package(self, parent, name):
421 if '.' in name:
422 i = string.find(name, '.')
423 head = name[:i]
424 tail = name[i+1:]
425 else:
426 head = name
427 tail = ""
428 if parent:
429 qname = "%s.%s" % (parent.__name__, head)
430 else:
431 qname = head
432 q = self.import_it(head, qname, parent)
433 if q: return q, tail
434 if parent:
435 qname = head
436 parent = None
437 q = self.import_it(head, qname, parent)
438 if q: return q, tail
439 raise ImportError, "No module named " + qname
440
441 def load_tail(self, q, tail):
442 m = q
443 while tail:
444 i = string.find(tail, '.')
445 if i < 0: i = len(tail)
446 head, tail = tail[:i], tail[i+1:]
447 mname = "%s.%s" % (m.__name__, head)
448 m = self.import_it(head, mname, m)
449 if not m:
450 raise ImportError, "No module named " + mname
451 return m
452
453 def ensure_fromlist(self, m, fromlist, recursive=0):
454 for sub in fromlist:
455 if sub == "*":
456 if not recursive:
457 try:
458 all = m.__all__
459 except AttributeError:
460 pass
461 else:
462 self.ensure_fromlist(m, all, 1)
463 continue
464 if sub != "*" and not hasattr(m, sub):
465 subname = "%s.%s" % (m.__name__, sub)
466 submod = self.import_it(sub, subname, m)
467 if not submod:
468 raise ImportError, "No module named " + subname
469
470 def import_it(self, partname, fqname, parent):
471 if not partname:
472 raise ValueError, "Empty module name"
473 try:
474 return self.modules[fqname]
475 except KeyError:
476 pass
477 try:
478 path = parent and parent.__path__
479 except AttributeError:
480 return None
481 stuff = self.loader.find_module(partname, path)
482 if not stuff:
483 return None
484 m = self.loader.load_module(fqname, stuff)
485 if parent:
486 setattr(parent, partname, m)
487 return m
488
489 def reload(self, module):
490 name = module.__name__
491 if '.' not in name:
492 return self.import_it(name, name, None)
493 i = string.rfind(name, '.')
494 pname = name[:i]
495 parent = self.modules[pname]
496 return self.import_it(name[i+1:], name, parent)
497
498
Guido van Rossume7e578f1995-08-04 04:00:20 +0000499default_importer = None
500current_importer = None
501
502def install(importer = None):
503 global current_importer
504 current_importer = importer or default_importer or ModuleImporter()
505 current_importer.install()
506
507def uninstall():
508 global current_importer
509 current_importer.uninstall()