annotate Lib/ihooks.py @ 4566:6403c94de50d legacy-trunk

Added safeguard against failure in __del__.
author Guido van Rossum <guido@python.org>
date Wed, 27 Nov 1996 19:39:58 +0000
parents af754961acc5
children b8b6a88f7f44
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2887
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
1 """Import hook support.
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
2
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
3 Consistent use of this module will make it possible to change the
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
4 different mechanisms involved in loading modules independently.
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
5
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
6 While the built-in module imp exports interfaces to the built-in
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
7 module searching and loading algorithm, and it is possible to replace
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
8 the built-in function __import__ in order to change the semantics of
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
9 the import statement, until now it has been difficult to combine the
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
10 effect of different __import__ hacks, like loading modules from URLs
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
11 (rimport.py), implementing a hierarchical module namespace (newimp.py)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
12 or restricted execution (rexec.py).
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
13
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
14 This module defines three new concepts:
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
15
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
16 (1) A "file system hooks" class provides an interface to a filesystem.
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
17
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
18 One hooks class is defined (Hooks), which uses the interface provided
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
19 by standard modules os and os.path. It should be used as the base
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
20 class for other hooks classes.
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
21
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
22 (2) A "module loader" class provides an interface to to search for a
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
23 module in a search path and to load it. It defines a method which
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
24 searches for a module in a single directory; by overriding this method
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
25 one can redefine the details of the search. If the directory is None,
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
26 built-in and frozen modules are searched instead.
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
27
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
28 Two module loader class are defined, both implementing the search
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
29 strategy used by the built-in __import__ function: ModuleLoader uses
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
30 the imp module's find_module interface, while HookableModuleLoader
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
31 uses a file system hooks class to interact with the file system. Both
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
32 use the imp module's load_* interfaces to actually load the module.
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
33
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
34 (3) A "module importer" class provides an interface to import a
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
35 module, as well as interfaces to reload and unload a module. It also
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
36 provides interfaces to install and uninstall itself instead of the
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
37 default __import__ and reload (and unload) functions.
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
38
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
39 One module importer class is defined (ModuleImporter), which uses a
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
40 module loader instance passed in (by default HookableModuleLoader is
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
41 instantiated).
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
42
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
43 The classes defined here should be used as base classes for extended
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
44 functionality along those lines.
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
45
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
46 If a module mporter class supports dotted names, its import_module()
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
47 must return a different value depending on whether it is called on
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
48 behalf of a "from ... import ..." statement or not. (This is caused
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
49 by the way the __import__ hook is used by the Python interpreter.) It
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
50 would also do wise to install a different version of reload().
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
51
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
52 XXX Should the imp.load_* functions also be called via the hooks
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
53 instance?
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
54
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
55 """
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
56
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
57
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
58 import __builtin__
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
59 import imp
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
60 import os
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
61 import sys
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
62
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
63
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
64 from imp import C_EXTENSION, PY_SOURCE, PY_COMPILED
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
65 BUILTIN_MODULE = 32
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
66 FROZEN_MODULE = 33
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
67
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
68
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
69 class _Verbose:
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
70
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
71 def __init__(self, verbose = 0):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
72 self.verbose = verbose
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
73
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
74 def get_verbose(self):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
75 return self.verbose
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
76
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
77 def set_verbose(self, verbose):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
78 self.verbose = verbose
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
79
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
80 # XXX The following is an experimental interface
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
81
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
82 def note(self, *args):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
83 if self.verbose:
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
84 apply(self.message, args)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
85
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
86 def message(self, format, *args):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
87 print format%args
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
88
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
89
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
90 class BasicModuleLoader(_Verbose):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
91
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
92 """Basic module loader.
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
93
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
94 This provides the same functionality as built-in import. It
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
95 doesn't deal with checking sys.modules -- all it provides is
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
96 find_module() and a load_module(), as well as find_module_in_dir()
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
97 which searches just one directory, and can be overridden by a
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
98 derived class to change the module search algorithm when the basic
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
99 dependency on sys.path is unchanged.
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
100
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
101 The interface is a little more convenient than imp's:
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
102 find_module(name, [path]) returns None or 'stuff', and
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
103 load_module(name, stuff) loads the module.
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
104
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
105 """
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
106
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
107 def find_module(self, name, path = None):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
108 if path is None:
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
109 path = [None] + self.default_path()
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
110 for dir in path:
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
111 stuff = self.find_module_in_dir(name, dir)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
112 if stuff: return stuff
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
113 return None
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
114
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
115 def default_path(self):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
116 return sys.path
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
117
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
118 def find_module_in_dir(self, name, dir):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
119 if dir is None:
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
120 return self.find_builtin_module(name)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
121 else:
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
122 try:
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
123 return imp.find_module(name, [dir])
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
124 except ImportError:
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
125 return None
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
126
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
127 def find_builtin_module(self, name):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
128 if imp.is_builtin(name):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
129 return None, '', ('', '', BUILTIN_MODULE)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
130 if imp.is_frozen(name):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
131 return None, '', ('', '', FROZEN_MODULE)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
132 return None
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
133
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
134 def load_module(self, name, stuff):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
135 file, filename, (suff, mode, type) = stuff
4260
516ddf50194d close module file after loading
Guido van Rossum <guido@python.org>
parents: 3686
diff changeset
136 try:
516ddf50194d close module file after loading
Guido van Rossum <guido@python.org>
parents: 3686
diff changeset
137 if type == BUILTIN_MODULE:
516ddf50194d close module file after loading
Guido van Rossum <guido@python.org>
parents: 3686
diff changeset
138 return imp.init_builtin(name)
516ddf50194d close module file after loading
Guido van Rossum <guido@python.org>
parents: 3686
diff changeset
139 if type == FROZEN_MODULE:
516ddf50194d close module file after loading
Guido van Rossum <guido@python.org>
parents: 3686
diff changeset
140 return imp.init_frozen(name)
516ddf50194d close module file after loading
Guido van Rossum <guido@python.org>
parents: 3686
diff changeset
141 if type == C_EXTENSION:
516ddf50194d close module file after loading
Guido van Rossum <guido@python.org>
parents: 3686
diff changeset
142 return imp.load_dynamic(name, filename, file)
516ddf50194d close module file after loading
Guido van Rossum <guido@python.org>
parents: 3686
diff changeset
143 if type == PY_SOURCE:
516ddf50194d close module file after loading
Guido van Rossum <guido@python.org>
parents: 3686
diff changeset
144 return imp.load_source(name, filename, file)
516ddf50194d close module file after loading
Guido van Rossum <guido@python.org>
parents: 3686
diff changeset
145 if type == PY_COMPILED:
516ddf50194d close module file after loading
Guido van Rossum <guido@python.org>
parents: 3686
diff changeset
146 return imp.load_compiled(name, filename, file)
516ddf50194d close module file after loading
Guido van Rossum <guido@python.org>
parents: 3686
diff changeset
147 finally:
516ddf50194d close module file after loading
Guido van Rossum <guido@python.org>
parents: 3686
diff changeset
148 if file: file.close()
2887
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
149 raise ImportError, "Unrecognized module type (%s) for %s" % \
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
150 (`type`, name)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
151
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
152
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
153 class Hooks(_Verbose):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
154
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
155 """Hooks into the filesystem and interpreter.
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
156
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
157 By deriving a subclass you can redefine your filesystem interface,
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
158 e.g. to merge it with the URL space.
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
159
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
160 This base class behaves just like the native filesystem.
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
161
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
162 """
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
163
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
164 # imp interface
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
165 def get_suffixes(self): return imp.get_suffixes()
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
166 def new_module(self, name): return imp.new_module(name)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
167 def is_builtin(self, name): return imp.is_builtin(name)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
168 def init_builtin(self, name): return imp.init_builtin(name)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
169 def is_frozen(self, name): return imp.is_frozen(name)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
170 def init_frozen(self, name): return imp.init_frozen(name)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
171 def get_frozen_object(self, name): return imp.get_frozen_object(name)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
172 def load_source(self, name, filename, file=None):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
173 return imp.load_source(name, filename, file)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
174 def load_compiled(self, name, filename, file=None):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
175 return imp.load_compiled(name, filename, file)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
176 def load_dynamic(self, name, filename, file=None):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
177 return imp.load_dynamic(name, filename, file)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
178
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
179 def add_module(self, name):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
180 d = self.modules_dict()
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
181 if d.has_key(name): return d[name]
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
182 d[name] = m = self.new_module(name)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
183 return m
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
184
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
185 # sys interface
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
186 def modules_dict(self): return sys.modules
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
187 def default_path(self): return sys.path
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
188
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
189 def path_split(self, x): return os.path.split(x)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
190 def path_join(self, x, y): return os.path.join(x, y)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
191 def path_isabs(self, x): return os.path.isabs(x)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
192 # etc.
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
193
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
194 def path_exists(self, x): return os.path.exists(x)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
195 def path_isdir(self, x): return os.path.isdir(x)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
196 def path_isfile(self, x): return os.path.isfile(x)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
197 def path_islink(self, x): return os.path.islink(x)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
198 # etc.
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
199
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
200 def openfile(self, *x): return apply(open, x)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
201 openfile_error = IOError
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
202 def listdir(self, x): return os.listdir(x)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
203 listdir_error = os.error
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
204 # etc.
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
205
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
206
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
207 class ModuleLoader(BasicModuleLoader):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
208
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
209 """Default module loader; uses file system hooks.
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
210
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
211 By defining suitable hooks, you might be able to load modules from
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
212 other sources than the file system, e.g. from compressed or
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
213 encrypted files, tar files or (if you're brave!) URLs.
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
214
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
215 """
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
216
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
217 def __init__(self, hooks = None, verbose = 0):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
218 BasicModuleLoader.__init__(self, verbose)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
219 self.hooks = hooks or Hooks(verbose)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
220
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
221 def default_path(self):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
222 return self.hooks.default_path()
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
223
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
224 def modules_dict(self):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
225 return self.hooks.modules_dict()
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
226
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
227 def get_hooks(self):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
228 return self.hooks
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
229
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
230 def set_hooks(self, hooks):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
231 self.hooks = hooks
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
232
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
233 def find_builtin_module(self, name):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
234 if self.hooks.is_builtin(name):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
235 return None, '', ('', '', BUILTIN_MODULE)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
236 if self.hooks.is_frozen(name):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
237 return None, '', ('', '', FROZEN_MODULE)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
238 return None
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
239
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
240 def find_module_in_dir(self, name, dir):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
241 if dir is None:
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
242 return self.find_builtin_module(name)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
243 for info in self.hooks.get_suffixes():
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
244 suff, mode, type = info
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
245 fullname = self.hooks.path_join(dir, name+suff)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
246 try:
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
247 fp = self.hooks.openfile(fullname, mode)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
248 return fp, fullname, info
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
249 except self.hooks.openfile_error:
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
250 pass
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
251 return None
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
252
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
253 def load_module(self, name, stuff):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
254 file, filename, (suff, mode, type) = stuff
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
255 if type == BUILTIN_MODULE:
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
256 return self.hooks.init_builtin(name)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
257 if type == FROZEN_MODULE:
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
258 return self.hooks.init_frozen(name)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
259 if type == C_EXTENSION:
4361
af754961acc5 Set the __file__ attribute of the imported module in both versions of
Guido van Rossum <guido@python.org>
parents: 4356
diff changeset
260 m = self.hooks.load_dynamic(name, filename, file)
af754961acc5 Set the __file__ attribute of the imported module in both versions of
Guido van Rossum <guido@python.org>
parents: 4356
diff changeset
261 elif type == PY_SOURCE:
af754961acc5 Set the __file__ attribute of the imported module in both versions of
Guido van Rossum <guido@python.org>
parents: 4356
diff changeset
262 m = self.hooks.load_source(name, filename, file)
af754961acc5 Set the __file__ attribute of the imported module in both versions of
Guido van Rossum <guido@python.org>
parents: 4356
diff changeset
263 elif type == PY_COMPILED:
af754961acc5 Set the __file__ attribute of the imported module in both versions of
Guido van Rossum <guido@python.org>
parents: 4356
diff changeset
264 m = self.hooks.load_compiled(name, filename, file)
af754961acc5 Set the __file__ attribute of the imported module in both versions of
Guido van Rossum <guido@python.org>
parents: 4356
diff changeset
265 else:
af754961acc5 Set the __file__ attribute of the imported module in both versions of
Guido van Rossum <guido@python.org>
parents: 4356
diff changeset
266 raise ImportError, "Unrecognized module type (%s) for %s" % \
af754961acc5 Set the __file__ attribute of the imported module in both versions of
Guido van Rossum <guido@python.org>
parents: 4356
diff changeset
267 (`type`, name)
af754961acc5 Set the __file__ attribute of the imported module in both versions of
Guido van Rossum <guido@python.org>
parents: 4356
diff changeset
268 m.__file__ = filename
af754961acc5 Set the __file__ attribute of the imported module in both versions of
Guido van Rossum <guido@python.org>
parents: 4356
diff changeset
269 return m
2887
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
270
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
271
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
272 class FancyModuleLoader(ModuleLoader):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
273
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
274 """Fancy module loader -- parses and execs the code itself."""
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
275
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
276 def load_module(self, name, stuff):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
277 file, filename, (suff, mode, type) = stuff
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
278 if type == FROZEN_MODULE:
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
279 code = self.hooks.get_frozen_object(name)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
280 elif type == PY_COMPILED:
3686
bdbda939b999 Import marshal before using it :-(
Guido van Rossum <guido@python.org>
parents: 2935
diff changeset
281 import marshal
2887
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
282 file.seek(8)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
283 code = marshal.load(file)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
284 elif type == PY_SOURCE:
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
285 data = file.read()
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
286 code = compile(data, filename, 'exec')
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
287 else:
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
288 return ModuleLoader.load_module(self, name, stuff)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
289 m = self.hooks.add_module(name)
4361
af754961acc5 Set the __file__ attribute of the imported module in both versions of
Guido van Rossum <guido@python.org>
parents: 4356
diff changeset
290 m.__file__ = filename
2887
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
291 exec code in m.__dict__
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
292 return m
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
293
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
294
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
295 class ModuleImporter(_Verbose):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
296
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
297 """Default module importer; uses module loader.
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
298
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
299 This provides the same functionality as built-in import, when
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
300 combined with ModuleLoader.
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
301
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
302 """
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
303
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
304 def __init__(self, loader = None, verbose = 0):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
305 _Verbose.__init__(self, verbose)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
306 self.loader = loader or ModuleLoader(None, verbose)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
307 self.modules = self.loader.modules_dict()
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
308
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
309 def get_loader(self):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
310 return self.loader
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
311
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
312 def set_loader(self, loader):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
313 self.loader = loader
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
314
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
315 def get_hooks(self):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
316 return self.loader.get_hooks()
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
317
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
318 def set_hooks(self, hooks):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
319 return self.loader.set_hooks(hooks)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
320
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
321 def import_module(self, name, globals={}, locals={}, fromlist=[]):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
322 if self.modules.has_key(name):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
323 return self.modules[name] # Fast path
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
324 stuff = self.loader.find_module(name)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
325 if not stuff:
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
326 raise ImportError, "No module named %s" % name
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
327 return self.loader.load_module(name, stuff)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
328
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
329 def reload(self, module, path = None):
2935
8aab83cc60a0 fix bug in reload
Guido van Rossum <guido@python.org>
parents: 2887
diff changeset
330 name = module.__name__
2887
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
331 stuff = self.loader.find_module(name, path)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
332 if not stuff:
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
333 raise ImportError, "Module %s not found for reload" % name
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
334 return self.loader.load_module(name, stuff)
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
335
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
336 def unload(self, module):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
337 del self.modules[module.__name__]
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
338 # XXX Should this try to clear the module's namespace?
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
339
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
340 def install(self):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
341 self.save_import_module = __builtin__.__import__
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
342 self.save_reload = __builtin__.reload
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
343 if not hasattr(__builtin__, 'unload'):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
344 __builtin__.unload = None
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
345 self.save_unload = __builtin__.unload
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
346 __builtin__.__import__ = self.import_module
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
347 __builtin__.reload = self.reload
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
348 __builtin__.unload = self.unload
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
349
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
350 def uninstall(self):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
351 __builtin__.__import__ = self.save_import_module
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
352 __builtin__.reload = self.save_reload
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
353 __builtin__.unload = self.save_unload
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
354 if not __builtin__.unload:
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
355 del __builtin__.unload
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
356
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
357
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
358 default_importer = None
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
359 current_importer = None
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
360
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
361 def install(importer = None):
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
362 global current_importer
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
363 current_importer = importer or default_importer or ModuleImporter()
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
364 current_importer.install()
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
365
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
366 def uninstall():
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
367 global current_importer
ec0b42889243 Initial revision
Guido van Rossum <guido@python.org>
parents:
diff changeset
368 current_importer.uninstall()