| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 1 | """Import hook support. | 
 | 2 |  | 
 | 3 | Consistent use of this module will make it possible to change the | 
 | 4 | different mechanisms involved in loading modules independently. | 
 | 5 |  | 
 | 6 | While the built-in module imp exports interfaces to the built-in | 
 | 7 | module searching and loading algorithm, and it is possible to replace | 
 | 8 | the built-in function __import__ in order to change the semantics of | 
 | 9 | the import statement, until now it has been difficult to combine the | 
 | 10 | effect of different __import__ hacks, like loading modules from URLs | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 11 | by rimport.py, or restricted execution by rexec.py. | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 12 |  | 
 | 13 | This module defines three new concepts: | 
 | 14 |  | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 15 | 1) A "file system hooks" class provides an interface to a filesystem. | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 16 |  | 
 | 17 | One hooks class is defined (Hooks), which uses the interface provided | 
 | 18 | by standard modules os and os.path.  It should be used as the base | 
 | 19 | class for other hooks classes. | 
 | 20 |  | 
| Walter Dörwald | f0dfc7a | 2003-10-20 14:01:56 +0000 | [diff] [blame] | 21 | 2) A "module loader" class provides an interface to search for a | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 22 | module in a search path and to load it.  It defines a method which | 
 | 23 | searches for a module in a single directory; by overriding this method | 
 | 24 | one can redefine the details of the search.  If the directory is None, | 
 | 25 | built-in and frozen modules are searched instead. | 
 | 26 |  | 
 | 27 | Two module loader class are defined, both implementing the search | 
 | 28 | strategy used by the built-in __import__ function: ModuleLoader uses | 
 | 29 | the imp module's find_module interface, while HookableModuleLoader | 
 | 30 | uses a file system hooks class to interact with the file system.  Both | 
 | 31 | use the imp module's load_* interfaces to actually load the module. | 
 | 32 |  | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 33 | 3) A "module importer" class provides an interface to import a | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 34 | module, as well as interfaces to reload and unload a module.  It also | 
 | 35 | provides interfaces to install and uninstall itself instead of the | 
 | 36 | default __import__ and reload (and unload) functions. | 
 | 37 |  | 
 | 38 | One module importer class is defined (ModuleImporter), which uses a | 
 | 39 | module loader instance passed in (by default HookableModuleLoader is | 
 | 40 | instantiated). | 
 | 41 |  | 
 | 42 | The classes defined here should be used as base classes for extended | 
 | 43 | functionality along those lines. | 
 | 44 |  | 
| Skip Montanaro | 2dd4276 | 2001-01-23 15:35:05 +0000 | [diff] [blame] | 45 | If a module importer class supports dotted names, its import_module() | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 46 | must return a different value depending on whether it is called on | 
 | 47 | behalf of a "from ... import ..." statement or not.  (This is caused | 
 | 48 | by the way the __import__ hook is used by the Python interpreter.)  It | 
 | 49 | would also do wise to install a different version of reload(). | 
 | 50 |  | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 51 | """ | 
| Brett Cannon | 27508d4 | 2008-05-10 22:45:07 +0000 | [diff] [blame] | 52 | from warnings import warnpy3k | 
 | 53 | warnpy3k("the ihooks module has been removed in Python 3.0", stacklevel=2) | 
 | 54 | del warnpy3k | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 55 |  | 
 | 56 | import __builtin__ | 
 | 57 | import imp | 
 | 58 | import os | 
 | 59 | import sys | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 60 |  | 
| Skip Montanaro | 2dd4276 | 2001-01-23 15:35:05 +0000 | [diff] [blame] | 61 | __all__ = ["BasicModuleLoader","Hooks","ModuleLoader","FancyModuleLoader", | 
 | 62 |            "BasicModuleImporter","ModuleImporter","install","uninstall"] | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 63 |  | 
 | 64 | VERBOSE = 0 | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 65 |  | 
 | 66 |  | 
 | 67 | from imp import C_EXTENSION, PY_SOURCE, PY_COMPILED | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 68 | from imp import C_BUILTIN, PY_FROZEN, PKG_DIRECTORY | 
 | 69 | BUILTIN_MODULE = C_BUILTIN | 
 | 70 | FROZEN_MODULE = PY_FROZEN | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 71 |  | 
 | 72 |  | 
 | 73 | class _Verbose: | 
 | 74 |  | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 75 |     def __init__(self, verbose = VERBOSE): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 76 |         self.verbose = verbose | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 77 |  | 
 | 78 |     def get_verbose(self): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 79 |         return self.verbose | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 80 |  | 
 | 81 |     def set_verbose(self, verbose): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 82 |         self.verbose = verbose | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 83 |  | 
 | 84 |     # XXX The following is an experimental interface | 
 | 85 |  | 
 | 86 |     def note(self, *args): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 87 |         if self.verbose: | 
| Guido van Rossum | 68468eb | 2003-02-27 20:14:51 +0000 | [diff] [blame] | 88 |             self.message(*args) | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 89 |  | 
 | 90 |     def message(self, format, *args): | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 91 |         if args: | 
 | 92 |             print format%args | 
 | 93 |         else: | 
 | 94 |             print format | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 95 |  | 
 | 96 |  | 
 | 97 | class BasicModuleLoader(_Verbose): | 
 | 98 |  | 
 | 99 |     """Basic module loader. | 
 | 100 |  | 
 | 101 |     This provides the same functionality as built-in import.  It | 
 | 102 |     doesn't deal with checking sys.modules -- all it provides is | 
 | 103 |     find_module() and a load_module(), as well as find_module_in_dir() | 
 | 104 |     which searches just one directory, and can be overridden by a | 
 | 105 |     derived class to change the module search algorithm when the basic | 
 | 106 |     dependency on sys.path is unchanged. | 
 | 107 |  | 
 | 108 |     The interface is a little more convenient than imp's: | 
 | 109 |     find_module(name, [path]) returns None or 'stuff', and | 
 | 110 |     load_module(name, stuff) loads the module. | 
 | 111 |  | 
 | 112 |     """ | 
 | 113 |  | 
 | 114 |     def find_module(self, name, path = None): | 
| Tim Peters | 07e99cb | 2001-01-14 23:47:14 +0000 | [diff] [blame] | 115 |         if path is None: | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 116 |             path = [None] + self.default_path() | 
 | 117 |         for dir in path: | 
 | 118 |             stuff = self.find_module_in_dir(name, dir) | 
 | 119 |             if stuff: return stuff | 
 | 120 |         return None | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 121 |  | 
 | 122 |     def default_path(self): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 123 |         return sys.path | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 124 |  | 
 | 125 |     def find_module_in_dir(self, name, dir): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 126 |         if dir is None: | 
 | 127 |             return self.find_builtin_module(name) | 
 | 128 |         else: | 
 | 129 |             try: | 
 | 130 |                 return imp.find_module(name, [dir]) | 
 | 131 |             except ImportError: | 
 | 132 |                 return None | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 133 |  | 
 | 134 |     def find_builtin_module(self, name): | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 135 |         # XXX frozen packages? | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 136 |         if imp.is_builtin(name): | 
 | 137 |             return None, '', ('', '', BUILTIN_MODULE) | 
 | 138 |         if imp.is_frozen(name): | 
 | 139 |             return None, '', ('', '', FROZEN_MODULE) | 
 | 140 |         return None | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 141 |  | 
 | 142 |     def load_module(self, name, stuff): | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 143 |         file, filename, info = stuff | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 144 |         try: | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 145 |             return imp.load_module(name, file, filename, info) | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 146 |         finally: | 
 | 147 |             if file: file.close() | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 148 |  | 
 | 149 |  | 
 | 150 | class Hooks(_Verbose): | 
 | 151 |  | 
 | 152 |     """Hooks into the filesystem and interpreter. | 
 | 153 |  | 
 | 154 |     By deriving a subclass you can redefine your filesystem interface, | 
 | 155 |     e.g. to merge it with the URL space. | 
 | 156 |  | 
 | 157 |     This base class behaves just like the native filesystem. | 
 | 158 |  | 
 | 159 |     """ | 
 | 160 |  | 
 | 161 |     # imp interface | 
 | 162 |     def get_suffixes(self): return imp.get_suffixes() | 
 | 163 |     def new_module(self, name): return imp.new_module(name) | 
 | 164 |     def is_builtin(self, name): return imp.is_builtin(name) | 
 | 165 |     def init_builtin(self, name): return imp.init_builtin(name) | 
 | 166 |     def is_frozen(self, name): return imp.is_frozen(name) | 
 | 167 |     def init_frozen(self, name): return imp.init_frozen(name) | 
 | 168 |     def get_frozen_object(self, name): return imp.get_frozen_object(name) | 
 | 169 |     def load_source(self, name, filename, file=None): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 170 |         return imp.load_source(name, filename, file) | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 171 |     def load_compiled(self, name, filename, file=None): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 172 |         return imp.load_compiled(name, filename, file) | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 173 |     def load_dynamic(self, name, filename, file=None): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 174 |         return imp.load_dynamic(name, filename, file) | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 175 |     def load_package(self, name, filename, file=None): | 
 | 176 |         return imp.load_module(name, file, filename, ("", "", PKG_DIRECTORY)) | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 177 |  | 
 | 178 |     def add_module(self, name): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 179 |         d = self.modules_dict() | 
| Raymond Hettinger | 54f0222 | 2002-06-01 14:18:47 +0000 | [diff] [blame] | 180 |         if name in d: return d[name] | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 181 |         d[name] = m = self.new_module(name) | 
 | 182 |         return m | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 183 |  | 
 | 184 |     # sys interface | 
 | 185 |     def modules_dict(self): return sys.modules | 
 | 186 |     def default_path(self): return sys.path | 
 | 187 |  | 
 | 188 |     def path_split(self, x): return os.path.split(x) | 
 | 189 |     def path_join(self, x, y): return os.path.join(x, y) | 
 | 190 |     def path_isabs(self, x): return os.path.isabs(x) | 
 | 191 |     # etc. | 
 | 192 |  | 
 | 193 |     def path_exists(self, x): return os.path.exists(x) | 
 | 194 |     def path_isdir(self, x): return os.path.isdir(x) | 
 | 195 |     def path_isfile(self, x): return os.path.isfile(x) | 
 | 196 |     def path_islink(self, x): return os.path.islink(x) | 
 | 197 |     # etc. | 
 | 198 |  | 
| Guido van Rossum | 68468eb | 2003-02-27 20:14:51 +0000 | [diff] [blame] | 199 |     def openfile(self, *x): return open(*x) | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 200 |     openfile_error = IOError | 
 | 201 |     def listdir(self, x): return os.listdir(x) | 
 | 202 |     listdir_error = os.error | 
 | 203 |     # etc. | 
 | 204 |  | 
 | 205 |  | 
 | 206 | class ModuleLoader(BasicModuleLoader): | 
 | 207 |  | 
 | 208 |     """Default module loader; uses file system hooks. | 
 | 209 |  | 
 | 210 |     By defining suitable hooks, you might be able to load modules from | 
 | 211 |     other sources than the file system, e.g. from compressed or | 
 | 212 |     encrypted files, tar files or (if you're brave!) URLs. | 
 | 213 |  | 
 | 214 |     """ | 
 | 215 |  | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 216 |     def __init__(self, hooks = None, verbose = VERBOSE): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 217 |         BasicModuleLoader.__init__(self, verbose) | 
 | 218 |         self.hooks = hooks or Hooks(verbose) | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 219 |  | 
 | 220 |     def default_path(self): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 221 |         return self.hooks.default_path() | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 222 |  | 
 | 223 |     def modules_dict(self): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 224 |         return self.hooks.modules_dict() | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 225 |  | 
 | 226 |     def get_hooks(self): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 227 |         return self.hooks | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 228 |  | 
 | 229 |     def set_hooks(self, hooks): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 230 |         self.hooks = hooks | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 231 |  | 
 | 232 |     def find_builtin_module(self, name): | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 233 |         # XXX frozen packages? | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 234 |         if self.hooks.is_builtin(name): | 
 | 235 |             return None, '', ('', '', BUILTIN_MODULE) | 
 | 236 |         if self.hooks.is_frozen(name): | 
 | 237 |             return None, '', ('', '', FROZEN_MODULE) | 
 | 238 |         return None | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 239 |  | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 240 |     def find_module_in_dir(self, name, dir, allow_packages=1): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 241 |         if dir is None: | 
 | 242 |             return self.find_builtin_module(name) | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 243 |         if allow_packages: | 
 | 244 |             fullname = self.hooks.path_join(dir, name) | 
 | 245 |             if self.hooks.path_isdir(fullname): | 
 | 246 |                 stuff = self.find_module_in_dir("__init__", fullname, 0) | 
 | 247 |                 if stuff: | 
 | 248 |                     file = stuff[0] | 
 | 249 |                     if file: file.close() | 
 | 250 |                     return None, fullname, ('', '', PKG_DIRECTORY) | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 251 |         for info in self.hooks.get_suffixes(): | 
 | 252 |             suff, mode, type = info | 
 | 253 |             fullname = self.hooks.path_join(dir, name+suff) | 
 | 254 |             try: | 
 | 255 |                 fp = self.hooks.openfile(fullname, mode) | 
 | 256 |                 return fp, fullname, info | 
 | 257 |             except self.hooks.openfile_error: | 
 | 258 |                 pass | 
 | 259 |         return None | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 260 |  | 
 | 261 |     def load_module(self, name, stuff): | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 262 |         file, filename, info = stuff | 
 | 263 |         (suff, mode, type) = info | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 264 |         try: | 
 | 265 |             if type == BUILTIN_MODULE: | 
 | 266 |                 return self.hooks.init_builtin(name) | 
 | 267 |             if type == FROZEN_MODULE: | 
 | 268 |                 return self.hooks.init_frozen(name) | 
 | 269 |             if type == C_EXTENSION: | 
 | 270 |                 m = self.hooks.load_dynamic(name, filename, file) | 
 | 271 |             elif type == PY_SOURCE: | 
 | 272 |                 m = self.hooks.load_source(name, filename, file) | 
 | 273 |             elif type == PY_COMPILED: | 
 | 274 |                 m = self.hooks.load_compiled(name, filename, file) | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 275 |             elif type == PKG_DIRECTORY: | 
 | 276 |                 m = self.hooks.load_package(name, filename, file) | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 277 |             else: | 
| Walter Dörwald | 70a6b49 | 2004-02-12 17:35:32 +0000 | [diff] [blame] | 278 |                 raise ImportError, "Unrecognized module type (%r) for %s" % \ | 
 | 279 |                       (type, name) | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 280 |         finally: | 
 | 281 |             if file: file.close() | 
 | 282 |         m.__file__ = filename | 
 | 283 |         return m | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 284 |  | 
 | 285 |  | 
 | 286 | class FancyModuleLoader(ModuleLoader): | 
 | 287 |  | 
 | 288 |     """Fancy module loader -- parses and execs the code itself.""" | 
 | 289 |  | 
 | 290 |     def load_module(self, name, stuff): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 291 |         file, filename, (suff, mode, type) = stuff | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 292 |         realfilename = filename | 
 | 293 |         path = None | 
 | 294 |  | 
 | 295 |         if type == PKG_DIRECTORY: | 
 | 296 |             initstuff = self.find_module_in_dir("__init__", filename, 0) | 
 | 297 |             if not initstuff: | 
 | 298 |                 raise ImportError, "No __init__ module in package %s" % name | 
 | 299 |             initfile, initfilename, initinfo = initstuff | 
 | 300 |             initsuff, initmode, inittype = initinfo | 
 | 301 |             if inittype not in (PY_COMPILED, PY_SOURCE): | 
 | 302 |                 if initfile: initfile.close() | 
 | 303 |                 raise ImportError, \ | 
| Walter Dörwald | 70a6b49 | 2004-02-12 17:35:32 +0000 | [diff] [blame] | 304 |                     "Bad type (%r) for __init__ module in package %s" % ( | 
 | 305 |                     inittype, name) | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 306 |             path = [filename] | 
 | 307 |             file = initfile | 
 | 308 |             realfilename = initfilename | 
 | 309 |             type = inittype | 
 | 310 |  | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 311 |         if type == FROZEN_MODULE: | 
 | 312 |             code = self.hooks.get_frozen_object(name) | 
 | 313 |         elif type == PY_COMPILED: | 
 | 314 |             import marshal | 
 | 315 |             file.seek(8) | 
 | 316 |             code = marshal.load(file) | 
 | 317 |         elif type == PY_SOURCE: | 
 | 318 |             data = file.read() | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 319 |             code = compile(data, realfilename, 'exec') | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 320 |         else: | 
 | 321 |             return ModuleLoader.load_module(self, name, stuff) | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 322 |  | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 323 |         m = self.hooks.add_module(name) | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 324 |         if path: | 
 | 325 |             m.__path__ = path | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 326 |         m.__file__ = filename | 
| Tim Peters | 3d3cfdb | 2004-08-04 02:29:12 +0000 | [diff] [blame] | 327 |         try: | 
 | 328 |             exec code in m.__dict__ | 
 | 329 |         except: | 
 | 330 |             d = self.hooks.modules_dict() | 
 | 331 |             if name in d: | 
 | 332 |                 del d[name] | 
 | 333 |             raise | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 334 |         return m | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 335 |  | 
 | 336 |  | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 337 | class BasicModuleImporter(_Verbose): | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 338 |  | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 339 |     """Basic module importer; uses module loader. | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 340 |  | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 341 |     This provides basic import facilities but no package imports. | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 342 |  | 
 | 343 |     """ | 
 | 344 |  | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 345 |     def __init__(self, loader = None, verbose = VERBOSE): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 346 |         _Verbose.__init__(self, verbose) | 
 | 347 |         self.loader = loader or ModuleLoader(None, verbose) | 
 | 348 |         self.modules = self.loader.modules_dict() | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 349 |  | 
 | 350 |     def get_loader(self): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 351 |         return self.loader | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 352 |  | 
 | 353 |     def set_loader(self, loader): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 354 |         self.loader = loader | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 355 |  | 
 | 356 |     def get_hooks(self): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 357 |         return self.loader.get_hooks() | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 358 |  | 
 | 359 |     def set_hooks(self, hooks): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 360 |         return self.loader.set_hooks(hooks) | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 361 |  | 
 | 362 |     def import_module(self, name, globals={}, locals={}, fromlist=[]): | 
| Gustavo Niemeyer | d5ae01a | 2002-12-16 13:11:57 +0000 | [diff] [blame] | 363 |         name = str(name) | 
| Raymond Hettinger | 54f0222 | 2002-06-01 14:18:47 +0000 | [diff] [blame] | 364 |         if name in self.modules: | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 365 |             return self.modules[name] # Fast path | 
 | 366 |         stuff = self.loader.find_module(name) | 
 | 367 |         if not stuff: | 
 | 368 |             raise ImportError, "No module named %s" % name | 
 | 369 |         return self.loader.load_module(name, stuff) | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 370 |  | 
 | 371 |     def reload(self, module, path = None): | 
| Gustavo Niemeyer | d5ae01a | 2002-12-16 13:11:57 +0000 | [diff] [blame] | 372 |         name = str(module.__name__) | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 373 |         stuff = self.loader.find_module(name, path) | 
 | 374 |         if not stuff: | 
 | 375 |             raise ImportError, "Module %s not found for reload" % name | 
 | 376 |         return self.loader.load_module(name, stuff) | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 377 |  | 
 | 378 |     def unload(self, module): | 
| Gustavo Niemeyer | d5ae01a | 2002-12-16 13:11:57 +0000 | [diff] [blame] | 379 |         del self.modules[str(module.__name__)] | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 380 |         # XXX Should this try to clear the module's namespace? | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 381 |  | 
 | 382 |     def install(self): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 383 |         self.save_import_module = __builtin__.__import__ | 
 | 384 |         self.save_reload = __builtin__.reload | 
 | 385 |         if not hasattr(__builtin__, 'unload'): | 
 | 386 |             __builtin__.unload = None | 
 | 387 |         self.save_unload = __builtin__.unload | 
 | 388 |         __builtin__.__import__ = self.import_module | 
 | 389 |         __builtin__.reload = self.reload | 
 | 390 |         __builtin__.unload = self.unload | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 391 |  | 
 | 392 |     def uninstall(self): | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 393 |         __builtin__.__import__ = self.save_import_module | 
 | 394 |         __builtin__.reload = self.save_reload | 
 | 395 |         __builtin__.unload = self.save_unload | 
 | 396 |         if not __builtin__.unload: | 
 | 397 |             del __builtin__.unload | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 398 |  | 
 | 399 |  | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 400 | class ModuleImporter(BasicModuleImporter): | 
 | 401 |  | 
 | 402 |     """A module importer that supports packages.""" | 
| Tim Peters | 07e99cb | 2001-01-14 23:47:14 +0000 | [diff] [blame] | 403 |  | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 404 |     def import_module(self, name, globals=None, locals=None, fromlist=None): | 
 | 405 |         parent = self.determine_parent(globals) | 
| Gustavo Niemeyer | d5ae01a | 2002-12-16 13:11:57 +0000 | [diff] [blame] | 406 |         q, tail = self.find_head_package(parent, str(name)) | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 407 |         m = self.load_tail(q, tail) | 
 | 408 |         if not fromlist: | 
 | 409 |             return q | 
 | 410 |         if hasattr(m, "__path__"): | 
 | 411 |             self.ensure_fromlist(m, fromlist) | 
 | 412 |         return m | 
 | 413 |  | 
 | 414 |     def determine_parent(self, globals): | 
| Raymond Hettinger | 54f0222 | 2002-06-01 14:18:47 +0000 | [diff] [blame] | 415 |         if not globals or not "__name__" in globals: | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 416 |             return None | 
 | 417 |         pname = globals['__name__'] | 
| Raymond Hettinger | 54f0222 | 2002-06-01 14:18:47 +0000 | [diff] [blame] | 418 |         if "__path__" in globals: | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 419 |             parent = self.modules[pname] | 
 | 420 |             assert globals is parent.__dict__ | 
 | 421 |             return parent | 
 | 422 |         if '.' in pname: | 
| Eric S. Raymond | bf97c9d | 2001-02-09 10:18:37 +0000 | [diff] [blame] | 423 |             i = pname.rfind('.') | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 424 |             pname = pname[:i] | 
 | 425 |             parent = self.modules[pname] | 
 | 426 |             assert parent.__name__ == pname | 
 | 427 |             return parent | 
 | 428 |         return None | 
 | 429 |  | 
 | 430 |     def find_head_package(self, parent, name): | 
 | 431 |         if '.' in name: | 
| Eric S. Raymond | bf97c9d | 2001-02-09 10:18:37 +0000 | [diff] [blame] | 432 |             i = name.find('.') | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 433 |             head = name[:i] | 
 | 434 |             tail = name[i+1:] | 
 | 435 |         else: | 
 | 436 |             head = name | 
 | 437 |             tail = "" | 
 | 438 |         if parent: | 
 | 439 |             qname = "%s.%s" % (parent.__name__, head) | 
 | 440 |         else: | 
 | 441 |             qname = head | 
 | 442 |         q = self.import_it(head, qname, parent) | 
 | 443 |         if q: return q, tail | 
 | 444 |         if parent: | 
 | 445 |             qname = head | 
 | 446 |             parent = None | 
 | 447 |             q = self.import_it(head, qname, parent) | 
 | 448 |             if q: return q, tail | 
 | 449 |         raise ImportError, "No module named " + qname | 
 | 450 |  | 
 | 451 |     def load_tail(self, q, tail): | 
 | 452 |         m = q | 
 | 453 |         while tail: | 
| Eric S. Raymond | bf97c9d | 2001-02-09 10:18:37 +0000 | [diff] [blame] | 454 |             i = tail.find('.') | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 455 |             if i < 0: i = len(tail) | 
 | 456 |             head, tail = tail[:i], tail[i+1:] | 
 | 457 |             mname = "%s.%s" % (m.__name__, head) | 
 | 458 |             m = self.import_it(head, mname, m) | 
 | 459 |             if not m: | 
 | 460 |                 raise ImportError, "No module named " + mname | 
 | 461 |         return m | 
 | 462 |  | 
 | 463 |     def ensure_fromlist(self, m, fromlist, recursive=0): | 
 | 464 |         for sub in fromlist: | 
 | 465 |             if sub == "*": | 
 | 466 |                 if not recursive: | 
 | 467 |                     try: | 
 | 468 |                         all = m.__all__ | 
 | 469 |                     except AttributeError: | 
 | 470 |                         pass | 
 | 471 |                     else: | 
 | 472 |                         self.ensure_fromlist(m, all, 1) | 
 | 473 |                 continue | 
 | 474 |             if sub != "*" and not hasattr(m, sub): | 
 | 475 |                 subname = "%s.%s" % (m.__name__, sub) | 
 | 476 |                 submod = self.import_it(sub, subname, m) | 
 | 477 |                 if not submod: | 
 | 478 |                     raise ImportError, "No module named " + subname | 
 | 479 |  | 
| Fred Drake | 8deeced | 2000-04-13 14:52:27 +0000 | [diff] [blame] | 480 |     def import_it(self, partname, fqname, parent, force_load=0): | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 481 |         if not partname: | 
 | 482 |             raise ValueError, "Empty module name" | 
| Fred Drake | 8deeced | 2000-04-13 14:52:27 +0000 | [diff] [blame] | 483 |         if not force_load: | 
 | 484 |             try: | 
 | 485 |                 return self.modules[fqname] | 
 | 486 |             except KeyError: | 
 | 487 |                 pass | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 488 |         try: | 
 | 489 |             path = parent and parent.__path__ | 
 | 490 |         except AttributeError: | 
 | 491 |             return None | 
| Gustavo Niemeyer | d5ae01a | 2002-12-16 13:11:57 +0000 | [diff] [blame] | 492 |         partname = str(partname) | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 493 |         stuff = self.loader.find_module(partname, path) | 
 | 494 |         if not stuff: | 
 | 495 |             return None | 
| Gustavo Niemeyer | d5ae01a | 2002-12-16 13:11:57 +0000 | [diff] [blame] | 496 |         fqname = str(fqname) | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 497 |         m = self.loader.load_module(fqname, stuff) | 
 | 498 |         if parent: | 
 | 499 |             setattr(parent, partname, m) | 
 | 500 |         return m | 
 | 501 |  | 
 | 502 |     def reload(self, module): | 
| Gustavo Niemeyer | d5ae01a | 2002-12-16 13:11:57 +0000 | [diff] [blame] | 503 |         name = str(module.__name__) | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 504 |         if '.' not in name: | 
| Fred Drake | 8deeced | 2000-04-13 14:52:27 +0000 | [diff] [blame] | 505 |             return self.import_it(name, name, None, force_load=1) | 
| Eric S. Raymond | bf97c9d | 2001-02-09 10:18:37 +0000 | [diff] [blame] | 506 |         i = name.rfind('.') | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 507 |         pname = name[:i] | 
 | 508 |         parent = self.modules[pname] | 
| Fred Drake | 8deeced | 2000-04-13 14:52:27 +0000 | [diff] [blame] | 509 |         return self.import_it(name[i+1:], name, parent, force_load=1) | 
| Guido van Rossum | 9f5c36f | 1998-06-29 20:31:16 +0000 | [diff] [blame] | 510 |  | 
 | 511 |  | 
| Guido van Rossum | e7e578f | 1995-08-04 04:00:20 +0000 | [diff] [blame] | 512 | default_importer = None | 
 | 513 | current_importer = None | 
 | 514 |  | 
 | 515 | def install(importer = None): | 
 | 516 |     global current_importer | 
 | 517 |     current_importer = importer or default_importer or ModuleImporter() | 
 | 518 |     current_importer.install() | 
 | 519 |  | 
 | 520 | def uninstall(): | 
 | 521 |     global current_importer | 
 | 522 |     current_importer.uninstall() |