| 1 | n/a | """ |
|---|
| 2 | n/a | Import utilities |
|---|
| 3 | n/a | |
|---|
| 4 | n/a | Exported classes: |
|---|
| 5 | n/a | ImportManager Manage the import process |
|---|
| 6 | n/a | |
|---|
| 7 | n/a | Importer Base class for replacing standard import functions |
|---|
| 8 | n/a | BuiltinImporter Emulate the import mechanism for builtin and frozen modules |
|---|
| 9 | n/a | |
|---|
| 10 | n/a | DynLoadSuffixImporter |
|---|
| 11 | 1 | """ |
|---|
| 12 | 1 | from warnings import warnpy3k |
|---|
| 13 | 1 | warnpy3k("the imputil module has been removed in Python 3.0", stacklevel=2) |
|---|
| 14 | 1 | del warnpy3k |
|---|
| 15 | n/a | |
|---|
| 16 | n/a | # note: avoid importing non-builtin modules |
|---|
| 17 | 1 | import imp ### not available in Jython? |
|---|
| 18 | 1 | import sys |
|---|
| 19 | 1 | import __builtin__ |
|---|
| 20 | n/a | |
|---|
| 21 | n/a | # for the DirectoryImporter |
|---|
| 22 | 1 | import struct |
|---|
| 23 | 1 | import marshal |
|---|
| 24 | n/a | |
|---|
| 25 | 1 | __all__ = ["ImportManager","Importer","BuiltinImporter"] |
|---|
| 26 | n/a | |
|---|
| 27 | 1 | _StringType = type('') |
|---|
| 28 | 1 | _ModuleType = type(sys) ### doesn't work in Jython... |
|---|
| 29 | n/a | |
|---|
| 30 | 2 | class ImportManager: |
|---|
| 31 | 1 | "Manage the import process." |
|---|
| 32 | n/a | |
|---|
| 33 | 1 | def install(self, namespace=vars(__builtin__)): |
|---|
| 34 | n/a | "Install this ImportManager into the specified namespace." |
|---|
| 35 | n/a | |
|---|
| 36 | 0 | if isinstance(namespace, _ModuleType): |
|---|
| 37 | 0 | namespace = vars(namespace) |
|---|
| 38 | n/a | |
|---|
| 39 | n/a | # Note: we have no notion of "chaining" |
|---|
| 40 | n/a | |
|---|
| 41 | n/a | # Record the previous import hook, then install our own. |
|---|
| 42 | 0 | self.previous_importer = namespace['__import__'] |
|---|
| 43 | 0 | self.namespace = namespace |
|---|
| 44 | 0 | namespace['__import__'] = self._import_hook |
|---|
| 45 | n/a | |
|---|
| 46 | n/a | ### fix this |
|---|
| 47 | n/a | #namespace['reload'] = self._reload_hook |
|---|
| 48 | n/a | |
|---|
| 49 | 1 | def uninstall(self): |
|---|
| 50 | n/a | "Restore the previous import mechanism." |
|---|
| 51 | 0 | self.namespace['__import__'] = self.previous_importer |
|---|
| 52 | n/a | |
|---|
| 53 | 1 | def add_suffix(self, suffix, importFunc): |
|---|
| 54 | 0 | assert hasattr(importFunc, '__call__') |
|---|
| 55 | 0 | self.fs_imp.add_suffix(suffix, importFunc) |
|---|
| 56 | n/a | |
|---|
| 57 | n/a | ###################################################################### |
|---|
| 58 | n/a | # |
|---|
| 59 | n/a | # PRIVATE METHODS |
|---|
| 60 | n/a | # |
|---|
| 61 | n/a | |
|---|
| 62 | 1 | clsFilesystemImporter = None |
|---|
| 63 | n/a | |
|---|
| 64 | 1 | def __init__(self, fs_imp=None): |
|---|
| 65 | n/a | # we're definitely going to be importing something in the future, |
|---|
| 66 | n/a | # so let's just load the OS-related facilities. |
|---|
| 67 | 0 | if not _os_stat: |
|---|
| 68 | 0 | _os_bootstrap() |
|---|
| 69 | n/a | |
|---|
| 70 | n/a | # This is the Importer that we use for grabbing stuff from the |
|---|
| 71 | n/a | # filesystem. It defines one more method (import_from_dir) for our use. |
|---|
| 72 | 0 | if fs_imp is None: |
|---|
| 73 | 0 | cls = self.clsFilesystemImporter or _FilesystemImporter |
|---|
| 74 | 0 | fs_imp = cls() |
|---|
| 75 | 0 | self.fs_imp = fs_imp |
|---|
| 76 | n/a | |
|---|
| 77 | n/a | # Initialize the set of suffixes that we recognize and import. |
|---|
| 78 | n/a | # The default will import dynamic-load modules first, followed by |
|---|
| 79 | n/a | # .py files (or a .py file's cached bytecode) |
|---|
| 80 | 0 | for desc in imp.get_suffixes(): |
|---|
| 81 | 0 | if desc[2] == imp.C_EXTENSION: |
|---|
| 82 | 0 | self.add_suffix(desc[0], |
|---|
| 83 | 0 | DynLoadSuffixImporter(desc).import_file) |
|---|
| 84 | 0 | self.add_suffix('.py', py_suffix_importer) |
|---|
| 85 | n/a | |
|---|
| 86 | 1 | def _import_hook(self, fqname, globals=None, locals=None, fromlist=None): |
|---|
| 87 | n/a | """Python calls this hook to locate and import a module.""" |
|---|
| 88 | n/a | |
|---|
| 89 | 0 | parts = fqname.split('.') |
|---|
| 90 | n/a | |
|---|
| 91 | n/a | # determine the context of this import |
|---|
| 92 | 0 | parent = self._determine_import_context(globals) |
|---|
| 93 | n/a | |
|---|
| 94 | n/a | # if there is a parent, then its importer should manage this import |
|---|
| 95 | 0 | if parent: |
|---|
| 96 | 0 | module = parent.__importer__._do_import(parent, parts, fromlist) |
|---|
| 97 | 0 | if module: |
|---|
| 98 | 0 | return module |
|---|
| 99 | n/a | |
|---|
| 100 | n/a | # has the top module already been imported? |
|---|
| 101 | 0 | try: |
|---|
| 102 | 0 | top_module = sys.modules[parts[0]] |
|---|
| 103 | 0 | except KeyError: |
|---|
| 104 | n/a | |
|---|
| 105 | n/a | # look for the topmost module |
|---|
| 106 | 0 | top_module = self._import_top_module(parts[0]) |
|---|
| 107 | 0 | if not top_module: |
|---|
| 108 | n/a | # the topmost module wasn't found at all. |
|---|
| 109 | 0 | raise ImportError, 'No module named ' + fqname |
|---|
| 110 | n/a | |
|---|
| 111 | n/a | # fast-path simple imports |
|---|
| 112 | 0 | if len(parts) == 1: |
|---|
| 113 | 0 | if not fromlist: |
|---|
| 114 | 0 | return top_module |
|---|
| 115 | n/a | |
|---|
| 116 | 0 | if not top_module.__dict__.get('__ispkg__'): |
|---|
| 117 | n/a | # __ispkg__ isn't defined (the module was not imported by us), |
|---|
| 118 | n/a | # or it is zero. |
|---|
| 119 | n/a | # |
|---|
| 120 | n/a | # In the former case, there is no way that we could import |
|---|
| 121 | n/a | # sub-modules that occur in the fromlist (but we can't raise an |
|---|
| 122 | n/a | # error because it may just be names) because we don't know how |
|---|
| 123 | n/a | # to deal with packages that were imported by other systems. |
|---|
| 124 | n/a | # |
|---|
| 125 | n/a | # In the latter case (__ispkg__ == 0), there can't be any sub- |
|---|
| 126 | n/a | # modules present, so we can just return. |
|---|
| 127 | n/a | # |
|---|
| 128 | n/a | # In both cases, since len(parts) == 1, the top_module is also |
|---|
| 129 | n/a | # the "bottom" which is the defined return when a fromlist |
|---|
| 130 | n/a | # exists. |
|---|
| 131 | 0 | return top_module |
|---|
| 132 | n/a | |
|---|
| 133 | 0 | importer = top_module.__dict__.get('__importer__') |
|---|
| 134 | 0 | if importer: |
|---|
| 135 | 0 | return importer._finish_import(top_module, parts[1:], fromlist) |
|---|
| 136 | n/a | |
|---|
| 137 | n/a | # Grrr, some people "import os.path" or do "from os.path import ..." |
|---|
| 138 | 0 | if len(parts) == 2 and hasattr(top_module, parts[1]): |
|---|
| 139 | 0 | if fromlist: |
|---|
| 140 | 0 | return getattr(top_module, parts[1]) |
|---|
| 141 | n/a | else: |
|---|
| 142 | 0 | return top_module |
|---|
| 143 | n/a | |
|---|
| 144 | n/a | # If the importer does not exist, then we have to bail. A missing |
|---|
| 145 | n/a | # importer means that something else imported the module, and we have |
|---|
| 146 | n/a | # no knowledge of how to get sub-modules out of the thing. |
|---|
| 147 | 0 | raise ImportError, 'No module named ' + fqname |
|---|
| 148 | n/a | |
|---|
| 149 | 1 | def _determine_import_context(self, globals): |
|---|
| 150 | n/a | """Returns the context in which a module should be imported. |
|---|
| 151 | n/a | |
|---|
| 152 | n/a | The context could be a loaded (package) module and the imported module |
|---|
| 153 | n/a | will be looked for within that package. The context could also be None, |
|---|
| 154 | n/a | meaning there is no context -- the module should be looked for as a |
|---|
| 155 | n/a | "top-level" module. |
|---|
| 156 | n/a | """ |
|---|
| 157 | n/a | |
|---|
| 158 | 0 | if not globals or not globals.get('__importer__'): |
|---|
| 159 | n/a | # globals does not refer to one of our modules or packages. That |
|---|
| 160 | n/a | # implies there is no relative import context (as far as we are |
|---|
| 161 | n/a | # concerned), and it should just pick it off the standard path. |
|---|
| 162 | 0 | return None |
|---|
| 163 | n/a | |
|---|
| 164 | n/a | # The globals refer to a module or package of ours. It will define |
|---|
| 165 | n/a | # the context of the new import. Get the module/package fqname. |
|---|
| 166 | 0 | parent_fqname = globals['__name__'] |
|---|
| 167 | n/a | |
|---|
| 168 | n/a | # if a package is performing the import, then return itself (imports |
|---|
| 169 | n/a | # refer to pkg contents) |
|---|
| 170 | 0 | if globals['__ispkg__']: |
|---|
| 171 | 0 | parent = sys.modules[parent_fqname] |
|---|
| 172 | 0 | assert globals is parent.__dict__ |
|---|
| 173 | 0 | return parent |
|---|
| 174 | n/a | |
|---|
| 175 | 0 | i = parent_fqname.rfind('.') |
|---|
| 176 | n/a | |
|---|
| 177 | n/a | # a module outside of a package has no particular import context |
|---|
| 178 | 0 | if i == -1: |
|---|
| 179 | 0 | return None |
|---|
| 180 | n/a | |
|---|
| 181 | n/a | # if a module in a package is performing the import, then return the |
|---|
| 182 | n/a | # package (imports refer to siblings) |
|---|
| 183 | 0 | parent_fqname = parent_fqname[:i] |
|---|
| 184 | 0 | parent = sys.modules[parent_fqname] |
|---|
| 185 | 0 | assert parent.__name__ == parent_fqname |
|---|
| 186 | 0 | return parent |
|---|
| 187 | n/a | |
|---|
| 188 | 1 | def _import_top_module(self, name): |
|---|
| 189 | n/a | # scan sys.path looking for a location in the filesystem that contains |
|---|
| 190 | n/a | # the module, or an Importer object that can import the module. |
|---|
| 191 | 0 | for item in sys.path: |
|---|
| 192 | 0 | if isinstance(item, _StringType): |
|---|
| 193 | 0 | module = self.fs_imp.import_from_dir(item, name) |
|---|
| 194 | n/a | else: |
|---|
| 195 | 0 | module = item.import_top(name) |
|---|
| 196 | 0 | if module: |
|---|
| 197 | 0 | return module |
|---|
| 198 | 0 | return None |
|---|
| 199 | n/a | |
|---|
| 200 | 1 | def _reload_hook(self, module): |
|---|
| 201 | n/a | "Python calls this hook to reload a module." |
|---|
| 202 | n/a | |
|---|
| 203 | n/a | # reloading of a module may or may not be possible (depending on the |
|---|
| 204 | n/a | # importer), but at least we can validate that it's ours to reload |
|---|
| 205 | 0 | importer = module.__dict__.get('__importer__') |
|---|
| 206 | 0 | if not importer: |
|---|
| 207 | n/a | ### oops. now what... |
|---|
| 208 | 0 | pass |
|---|
| 209 | n/a | |
|---|
| 210 | n/a | # okay. it is using the imputil system, and we must delegate it, but |
|---|
| 211 | n/a | # we don't know what to do (yet) |
|---|
| 212 | n/a | ### we should blast the module dict and do another get_code(). need to |
|---|
| 213 | n/a | ### flesh this out and add proper docco... |
|---|
| 214 | 0 | raise SystemError, "reload not yet implemented" |
|---|
| 215 | n/a | |
|---|
| 216 | n/a | |
|---|
| 217 | 2 | class Importer: |
|---|
| 218 | 1 | "Base class for replacing standard import functions." |
|---|
| 219 | n/a | |
|---|
| 220 | 1 | def import_top(self, name): |
|---|
| 221 | n/a | "Import a top-level module." |
|---|
| 222 | 0 | return self._import_one(None, name, name) |
|---|
| 223 | n/a | |
|---|
| 224 | n/a | ###################################################################### |
|---|
| 225 | n/a | # |
|---|
| 226 | n/a | # PRIVATE METHODS |
|---|
| 227 | n/a | # |
|---|
| 228 | 1 | def _finish_import(self, top, parts, fromlist): |
|---|
| 229 | n/a | # if "a.b.c" was provided, then load the ".b.c" portion down from |
|---|
| 230 | n/a | # below the top-level module. |
|---|
| 231 | 0 | bottom = self._load_tail(top, parts) |
|---|
| 232 | n/a | |
|---|
| 233 | n/a | # if the form is "import a.b.c", then return "a" |
|---|
| 234 | 0 | if not fromlist: |
|---|
| 235 | n/a | # no fromlist: return the top of the import tree |
|---|
| 236 | 0 | return top |
|---|
| 237 | n/a | |
|---|
| 238 | n/a | # the top module was imported by self. |
|---|
| 239 | n/a | # |
|---|
| 240 | n/a | # this means that the bottom module was also imported by self (just |
|---|
| 241 | n/a | # now, or in the past and we fetched it from sys.modules). |
|---|
| 242 | n/a | # |
|---|
| 243 | n/a | # since we imported/handled the bottom module, this means that we can |
|---|
| 244 | n/a | # also handle its fromlist (and reliably use __ispkg__). |
|---|
| 245 | n/a | |
|---|
| 246 | n/a | # if the bottom node is a package, then (potentially) import some |
|---|
| 247 | n/a | # modules. |
|---|
| 248 | n/a | # |
|---|
| 249 | n/a | # note: if it is not a package, then "fromlist" refers to names in |
|---|
| 250 | n/a | # the bottom module rather than modules. |
|---|
| 251 | n/a | # note: for a mix of names and modules in the fromlist, we will |
|---|
| 252 | n/a | # import all modules and insert those into the namespace of |
|---|
| 253 | n/a | # the package module. Python will pick up all fromlist names |
|---|
| 254 | n/a | # from the bottom (package) module; some will be modules that |
|---|
| 255 | n/a | # we imported and stored in the namespace, others are expected |
|---|
| 256 | n/a | # to be present already. |
|---|
| 257 | 0 | if bottom.__ispkg__: |
|---|
| 258 | 0 | self._import_fromlist(bottom, fromlist) |
|---|
| 259 | n/a | |
|---|
| 260 | n/a | # if the form is "from a.b import c, d" then return "b" |
|---|
| 261 | 0 | return bottom |
|---|
| 262 | n/a | |
|---|
| 263 | 1 | def _import_one(self, parent, modname, fqname): |
|---|
| 264 | n/a | "Import a single module." |
|---|
| 265 | n/a | |
|---|
| 266 | n/a | # has the module already been imported? |
|---|
| 267 | 0 | try: |
|---|
| 268 | 0 | return sys.modules[fqname] |
|---|
| 269 | 0 | except KeyError: |
|---|
| 270 | 0 | pass |
|---|
| 271 | n/a | |
|---|
| 272 | n/a | # load the module's code, or fetch the module itself |
|---|
| 273 | 0 | result = self.get_code(parent, modname, fqname) |
|---|
| 274 | 0 | if result is None: |
|---|
| 275 | 0 | return None |
|---|
| 276 | n/a | |
|---|
| 277 | 0 | module = self._process_result(result, fqname) |
|---|
| 278 | n/a | |
|---|
| 279 | n/a | # insert the module into its parent |
|---|
| 280 | 0 | if parent: |
|---|
| 281 | 0 | setattr(parent, modname, module) |
|---|
| 282 | 0 | return module |
|---|
| 283 | n/a | |
|---|
| 284 | 1 | def _process_result(self, result, fqname): |
|---|
| 285 | 0 | ispkg, code, values = result |
|---|
| 286 | n/a | # did get_code() return an actual module? (rather than a code object) |
|---|
| 287 | 0 | is_module = isinstance(code, _ModuleType) |
|---|
| 288 | n/a | |
|---|
| 289 | n/a | # use the returned module, or create a new one to exec code into |
|---|
| 290 | 0 | if is_module: |
|---|
| 291 | 0 | module = code |
|---|
| 292 | n/a | else: |
|---|
| 293 | 0 | module = imp.new_module(fqname) |
|---|
| 294 | n/a | |
|---|
| 295 | n/a | ### record packages a bit differently?? |
|---|
| 296 | 0 | module.__importer__ = self |
|---|
| 297 | 0 | module.__ispkg__ = ispkg |
|---|
| 298 | n/a | |
|---|
| 299 | n/a | # insert additional values into the module (before executing the code) |
|---|
| 300 | 0 | module.__dict__.update(values) |
|---|
| 301 | n/a | |
|---|
| 302 | n/a | # the module is almost ready... make it visible |
|---|
| 303 | 0 | sys.modules[fqname] = module |
|---|
| 304 | n/a | |
|---|
| 305 | n/a | # execute the code within the module's namespace |
|---|
| 306 | 0 | if not is_module: |
|---|
| 307 | 0 | try: |
|---|
| 308 | 0 | exec code in module.__dict__ |
|---|
| 309 | 0 | except: |
|---|
| 310 | 0 | if fqname in sys.modules: |
|---|
| 311 | 0 | del sys.modules[fqname] |
|---|
| 312 | 0 | raise |
|---|
| 313 | n/a | |
|---|
| 314 | n/a | # fetch from sys.modules instead of returning module directly. |
|---|
| 315 | n/a | # also make module's __name__ agree with fqname, in case |
|---|
| 316 | n/a | # the "exec code in module.__dict__" played games on us. |
|---|
| 317 | 0 | module = sys.modules[fqname] |
|---|
| 318 | 0 | module.__name__ = fqname |
|---|
| 319 | 0 | return module |
|---|
| 320 | n/a | |
|---|
| 321 | 1 | def _load_tail(self, m, parts): |
|---|
| 322 | n/a | """Import the rest of the modules, down from the top-level module. |
|---|
| 323 | n/a | |
|---|
| 324 | n/a | Returns the last module in the dotted list of modules. |
|---|
| 325 | n/a | """ |
|---|
| 326 | 0 | for part in parts: |
|---|
| 327 | 0 | fqname = "%s.%s" % (m.__name__, part) |
|---|
| 328 | 0 | m = self._import_one(m, part, fqname) |
|---|
| 329 | 0 | if not m: |
|---|
| 330 | 0 | raise ImportError, "No module named " + fqname |
|---|
| 331 | 0 | return m |
|---|
| 332 | n/a | |
|---|
| 333 | 1 | def _import_fromlist(self, package, fromlist): |
|---|
| 334 | n/a | 'Import any sub-modules in the "from" list.' |
|---|
| 335 | n/a | |
|---|
| 336 | n/a | # if '*' is present in the fromlist, then look for the '__all__' |
|---|
| 337 | n/a | # variable to find additional items (modules) to import. |
|---|
| 338 | 0 | if '*' in fromlist: |
|---|
| 339 | 0 | fromlist = list(fromlist) + \ |
|---|
| 340 | 0 | list(package.__dict__.get('__all__', [])) |
|---|
| 341 | n/a | |
|---|
| 342 | 0 | for sub in fromlist: |
|---|
| 343 | n/a | # if the name is already present, then don't try to import it (it |
|---|
| 344 | n/a | # might not be a module!). |
|---|
| 345 | 0 | if sub != '*' and not hasattr(package, sub): |
|---|
| 346 | 0 | subname = "%s.%s" % (package.__name__, sub) |
|---|
| 347 | 0 | submod = self._import_one(package, sub, subname) |
|---|
| 348 | 0 | if not submod: |
|---|
| 349 | 0 | raise ImportError, "cannot import name " + subname |
|---|
| 350 | n/a | |
|---|
| 351 | 1 | def _do_import(self, parent, parts, fromlist): |
|---|
| 352 | n/a | """Attempt to import the module relative to parent. |
|---|
| 353 | n/a | |
|---|
| 354 | n/a | This method is used when the import context specifies that <self> |
|---|
| 355 | n/a | imported the parent module. |
|---|
| 356 | n/a | """ |
|---|
| 357 | 0 | top_name = parts[0] |
|---|
| 358 | 0 | top_fqname = parent.__name__ + '.' + top_name |
|---|
| 359 | 0 | top_module = self._import_one(parent, top_name, top_fqname) |
|---|
| 360 | 0 | if not top_module: |
|---|
| 361 | n/a | # this importer and parent could not find the module (relatively) |
|---|
| 362 | 0 | return None |
|---|
| 363 | n/a | |
|---|
| 364 | 0 | return self._finish_import(top_module, parts[1:], fromlist) |
|---|
| 365 | n/a | |
|---|
| 366 | n/a | ###################################################################### |
|---|
| 367 | n/a | # |
|---|
| 368 | n/a | # METHODS TO OVERRIDE |
|---|
| 369 | n/a | # |
|---|
| 370 | 1 | def get_code(self, parent, modname, fqname): |
|---|
| 371 | n/a | """Find and retrieve the code for the given module. |
|---|
| 372 | n/a | |
|---|
| 373 | n/a | parent specifies a parent module to define a context for importing. It |
|---|
| 374 | n/a | may be None, indicating no particular context for the search. |
|---|
| 375 | n/a | |
|---|
| 376 | n/a | modname specifies a single module (not dotted) within the parent. |
|---|
| 377 | n/a | |
|---|
| 378 | n/a | fqname specifies the fully-qualified module name. This is a |
|---|
| 379 | n/a | (potentially) dotted name from the "root" of the module namespace |
|---|
| 380 | n/a | down to the modname. |
|---|
| 381 | n/a | If there is no parent, then modname==fqname. |
|---|
| 382 | n/a | |
|---|
| 383 | n/a | This method should return None, or a 3-tuple. |
|---|
| 384 | n/a | |
|---|
| 385 | n/a | * If the module was not found, then None should be returned. |
|---|
| 386 | n/a | |
|---|
| 387 | n/a | * The first item of the 2- or 3-tuple should be the integer 0 or 1, |
|---|
| 388 | n/a | specifying whether the module that was found is a package or not. |
|---|
| 389 | n/a | |
|---|
| 390 | n/a | * The second item is the code object for the module (it will be |
|---|
| 391 | n/a | executed within the new module's namespace). This item can also |
|---|
| 392 | n/a | be a fully-loaded module object (e.g. loaded from a shared lib). |
|---|
| 393 | n/a | |
|---|
| 394 | n/a | * The third item is a dictionary of name/value pairs that will be |
|---|
| 395 | n/a | inserted into new module before the code object is executed. This |
|---|
| 396 | n/a | is provided in case the module's code expects certain values (such |
|---|
| 397 | n/a | as where the module was found). When the second item is a module |
|---|
| 398 | n/a | object, then these names/values will be inserted *after* the module |
|---|
| 399 | n/a | has been loaded/initialized. |
|---|
| 400 | n/a | """ |
|---|
| 401 | 0 | raise RuntimeError, "get_code not implemented" |
|---|
| 402 | n/a | |
|---|
| 403 | n/a | |
|---|
| 404 | n/a | ###################################################################### |
|---|
| 405 | n/a | # |
|---|
| 406 | n/a | # Some handy stuff for the Importers |
|---|
| 407 | n/a | # |
|---|
| 408 | n/a | |
|---|
| 409 | n/a | # byte-compiled file suffix character |
|---|
| 410 | 1 | _suffix_char = __debug__ and 'c' or 'o' |
|---|
| 411 | n/a | |
|---|
| 412 | n/a | # byte-compiled file suffix |
|---|
| 413 | 1 | _suffix = '.py' + _suffix_char |
|---|
| 414 | n/a | |
|---|
| 415 | 1 | def _compile(pathname, timestamp): |
|---|
| 416 | n/a | """Compile (and cache) a Python source file. |
|---|
| 417 | n/a | |
|---|
| 418 | n/a | The file specified by <pathname> is compiled to a code object and |
|---|
| 419 | n/a | returned. |
|---|
| 420 | n/a | |
|---|
| 421 | n/a | Presuming the appropriate privileges exist, the bytecodes will be |
|---|
| 422 | n/a | saved back to the filesystem for future imports. The source file's |
|---|
| 423 | n/a | modification timestamp must be provided as a Long value. |
|---|
| 424 | n/a | """ |
|---|
| 425 | 0 | codestring = open(pathname, 'rU').read() |
|---|
| 426 | 0 | if codestring and codestring[-1] != '\n': |
|---|
| 427 | 0 | codestring = codestring + '\n' |
|---|
| 428 | 0 | code = __builtin__.compile(codestring, pathname, 'exec') |
|---|
| 429 | n/a | |
|---|
| 430 | n/a | # try to cache the compiled code |
|---|
| 431 | 0 | try: |
|---|
| 432 | 0 | f = open(pathname + _suffix_char, 'wb') |
|---|
| 433 | 0 | except IOError: |
|---|
| 434 | 0 | pass |
|---|
| 435 | n/a | else: |
|---|
| 436 | 0 | f.write('\0\0\0\0') |
|---|
| 437 | 0 | f.write(struct.pack('<I', timestamp)) |
|---|
| 438 | 0 | marshal.dump(code, f) |
|---|
| 439 | 0 | f.flush() |
|---|
| 440 | 0 | f.seek(0, 0) |
|---|
| 441 | 0 | f.write(imp.get_magic()) |
|---|
| 442 | 0 | f.close() |
|---|
| 443 | n/a | |
|---|
| 444 | 0 | return code |
|---|
| 445 | n/a | |
|---|
| 446 | 1 | _os_stat = _os_path_join = None |
|---|
| 447 | 1 | def _os_bootstrap(): |
|---|
| 448 | n/a | "Set up 'os' module replacement functions for use during import bootstrap." |
|---|
| 449 | n/a | |
|---|
| 450 | 0 | names = sys.builtin_module_names |
|---|
| 451 | n/a | |
|---|
| 452 | 0 | join = None |
|---|
| 453 | 0 | if 'posix' in names: |
|---|
| 454 | 0 | sep = '/' |
|---|
| 455 | 0 | from posix import stat |
|---|
| 456 | 0 | elif 'nt' in names: |
|---|
| 457 | 0 | sep = '\\' |
|---|
| 458 | 0 | from nt import stat |
|---|
| 459 | 0 | elif 'dos' in names: |
|---|
| 460 | 0 | sep = '\\' |
|---|
| 461 | 0 | from dos import stat |
|---|
| 462 | 0 | elif 'os2' in names: |
|---|
| 463 | 0 | sep = '\\' |
|---|
| 464 | 0 | from os2 import stat |
|---|
| 465 | n/a | else: |
|---|
| 466 | 0 | raise ImportError, 'no os specific module found' |
|---|
| 467 | n/a | |
|---|
| 468 | 0 | if join is None: |
|---|
| 469 | 0 | def join(a, b, sep=sep): |
|---|
| 470 | 0 | if a == '': |
|---|
| 471 | 0 | return b |
|---|
| 472 | 0 | lastchar = a[-1:] |
|---|
| 473 | 0 | if lastchar == '/' or lastchar == sep: |
|---|
| 474 | 0 | return a + b |
|---|
| 475 | 0 | return a + sep + b |
|---|
| 476 | n/a | |
|---|
| 477 | n/a | global _os_stat |
|---|
| 478 | 0 | _os_stat = stat |
|---|
| 479 | n/a | |
|---|
| 480 | n/a | global _os_path_join |
|---|
| 481 | 0 | _os_path_join = join |
|---|
| 482 | n/a | |
|---|
| 483 | 1 | def _os_path_isdir(pathname): |
|---|
| 484 | n/a | "Local replacement for os.path.isdir()." |
|---|
| 485 | 0 | try: |
|---|
| 486 | 0 | s = _os_stat(pathname) |
|---|
| 487 | 0 | except OSError: |
|---|
| 488 | 0 | return None |
|---|
| 489 | 0 | return (s.st_mode & 0170000) == 0040000 |
|---|
| 490 | n/a | |
|---|
| 491 | 1 | def _timestamp(pathname): |
|---|
| 492 | n/a | "Return the file modification time as a Long." |
|---|
| 493 | 0 | try: |
|---|
| 494 | 0 | s = _os_stat(pathname) |
|---|
| 495 | 0 | except OSError: |
|---|
| 496 | 0 | return None |
|---|
| 497 | 0 | return long(s.st_mtime) |
|---|
| 498 | n/a | |
|---|
| 499 | n/a | |
|---|
| 500 | n/a | ###################################################################### |
|---|
| 501 | n/a | # |
|---|
| 502 | n/a | # Emulate the import mechanism for builtin and frozen modules |
|---|
| 503 | n/a | # |
|---|
| 504 | 2 | class BuiltinImporter(Importer): |
|---|
| 505 | 1 | def get_code(self, parent, modname, fqname): |
|---|
| 506 | 0 | if parent: |
|---|
| 507 | n/a | # these modules definitely do not occur within a package context |
|---|
| 508 | 0 | return None |
|---|
| 509 | n/a | |
|---|
| 510 | n/a | # look for the module |
|---|
| 511 | 0 | if imp.is_builtin(modname): |
|---|
| 512 | 0 | type = imp.C_BUILTIN |
|---|
| 513 | 0 | elif imp.is_frozen(modname): |
|---|
| 514 | 0 | type = imp.PY_FROZEN |
|---|
| 515 | n/a | else: |
|---|
| 516 | n/a | # not found |
|---|
| 517 | 0 | return None |
|---|
| 518 | n/a | |
|---|
| 519 | n/a | # got it. now load and return it. |
|---|
| 520 | 0 | module = imp.load_module(modname, None, modname, ('', '', type)) |
|---|
| 521 | 0 | return 0, module, { } |
|---|
| 522 | n/a | |
|---|
| 523 | n/a | |
|---|
| 524 | n/a | ###################################################################### |
|---|
| 525 | n/a | # |
|---|
| 526 | n/a | # Internal importer used for importing from the filesystem |
|---|
| 527 | n/a | # |
|---|
| 528 | 2 | class _FilesystemImporter(Importer): |
|---|
| 529 | 1 | def __init__(self): |
|---|
| 530 | 0 | self.suffixes = [ ] |
|---|
| 531 | n/a | |
|---|
| 532 | 1 | def add_suffix(self, suffix, importFunc): |
|---|
| 533 | 0 | assert hasattr(importFunc, '__call__') |
|---|
| 534 | 0 | self.suffixes.append((suffix, importFunc)) |
|---|
| 535 | n/a | |
|---|
| 536 | 1 | def import_from_dir(self, dir, fqname): |
|---|
| 537 | 0 | result = self._import_pathname(_os_path_join(dir, fqname), fqname) |
|---|
| 538 | 0 | if result: |
|---|
| 539 | 0 | return self._process_result(result, fqname) |
|---|
| 540 | 0 | return None |
|---|
| 541 | n/a | |
|---|
| 542 | 1 | def get_code(self, parent, modname, fqname): |
|---|
| 543 | n/a | # This importer is never used with an empty parent. Its existence is |
|---|
| 544 | n/a | # private to the ImportManager. The ImportManager uses the |
|---|
| 545 | n/a | # import_from_dir() method to import top-level modules/packages. |
|---|
| 546 | n/a | # This method is only used when we look for a module within a package. |
|---|
| 547 | 0 | assert parent |
|---|
| 548 | n/a | |
|---|
| 549 | 0 | for submodule_path in parent.__path__: |
|---|
| 550 | 0 | code = self._import_pathname(_os_path_join(submodule_path, modname), fqname) |
|---|
| 551 | 0 | if code is not None: |
|---|
| 552 | 0 | return code |
|---|
| 553 | 0 | return self._import_pathname(_os_path_join(parent.__pkgdir__, modname), |
|---|
| 554 | 0 | fqname) |
|---|
| 555 | n/a | |
|---|
| 556 | 1 | def _import_pathname(self, pathname, fqname): |
|---|
| 557 | 0 | if _os_path_isdir(pathname): |
|---|
| 558 | 0 | result = self._import_pathname(_os_path_join(pathname, '__init__'), |
|---|
| 559 | 0 | fqname) |
|---|
| 560 | 0 | if result: |
|---|
| 561 | 0 | values = result[2] |
|---|
| 562 | 0 | values['__pkgdir__'] = pathname |
|---|
| 563 | 0 | values['__path__'] = [ pathname ] |
|---|
| 564 | 0 | return 1, result[1], values |
|---|
| 565 | 0 | return None |
|---|
| 566 | n/a | |
|---|
| 567 | 0 | for suffix, importFunc in self.suffixes: |
|---|
| 568 | 0 | filename = pathname + suffix |
|---|
| 569 | 0 | try: |
|---|
| 570 | 0 | finfo = _os_stat(filename) |
|---|
| 571 | 0 | except OSError: |
|---|
| 572 | 0 | pass |
|---|
| 573 | n/a | else: |
|---|
| 574 | 0 | return importFunc(filename, finfo, fqname) |
|---|
| 575 | 0 | return None |
|---|
| 576 | n/a | |
|---|
| 577 | n/a | ###################################################################### |
|---|
| 578 | n/a | # |
|---|
| 579 | n/a | # SUFFIX-BASED IMPORTERS |
|---|
| 580 | n/a | # |
|---|
| 581 | n/a | |
|---|
| 582 | 1 | def py_suffix_importer(filename, finfo, fqname): |
|---|
| 583 | 0 | file = filename[:-3] + _suffix |
|---|
| 584 | 0 | t_py = long(finfo[8]) |
|---|
| 585 | 0 | t_pyc = _timestamp(file) |
|---|
| 586 | n/a | |
|---|
| 587 | 0 | code = None |
|---|
| 588 | 0 | if t_pyc is not None and t_pyc >= t_py: |
|---|
| 589 | 0 | f = open(file, 'rb') |
|---|
| 590 | 0 | if f.read(4) == imp.get_magic(): |
|---|
| 591 | 0 | t = struct.unpack('<I', f.read(4))[0] |
|---|
| 592 | 0 | if t == t_py: |
|---|
| 593 | 0 | code = marshal.load(f) |
|---|
| 594 | 0 | f.close() |
|---|
| 595 | 0 | if code is None: |
|---|
| 596 | 0 | file = filename |
|---|
| 597 | 0 | code = _compile(file, t_py) |
|---|
| 598 | n/a | |
|---|
| 599 | 0 | return 0, code, { '__file__' : file } |
|---|
| 600 | n/a | |
|---|
| 601 | 2 | class DynLoadSuffixImporter: |
|---|
| 602 | 1 | def __init__(self, desc): |
|---|
| 603 | 0 | self.desc = desc |
|---|
| 604 | n/a | |
|---|
| 605 | 1 | def import_file(self, filename, finfo, fqname): |
|---|
| 606 | 0 | fp = open(filename, self.desc[1]) |
|---|
| 607 | 0 | module = imp.load_module(fqname, fp, filename, self.desc) |
|---|
| 608 | 0 | module.__file__ = filename |
|---|
| 609 | 0 | return 0, module, { } |
|---|
| 610 | n/a | |
|---|
| 611 | n/a | |
|---|
| 612 | n/a | ###################################################################### |
|---|
| 613 | n/a | |
|---|
| 614 | 1 | def _print_importers(): |
|---|
| 615 | 0 | items = sys.modules.items() |
|---|
| 616 | 0 | items.sort() |
|---|
| 617 | 0 | for name, module in items: |
|---|
| 618 | 0 | if module: |
|---|
| 619 | 0 | print name, module.__dict__.get('__importer__', '-- no importer') |
|---|
| 620 | n/a | else: |
|---|
| 621 | 0 | print name, '-- non-existent module' |
|---|
| 622 | n/a | |
|---|
| 623 | 1 | def _test_revamp(): |
|---|
| 624 | 0 | ImportManager().install() |
|---|
| 625 | 0 | sys.path.insert(0, BuiltinImporter()) |
|---|
| 626 | n/a | |
|---|
| 627 | n/a | ###################################################################### |
|---|
| 628 | n/a | |
|---|
| 629 | n/a | # |
|---|
| 630 | n/a | # TODO |
|---|
| 631 | n/a | # |
|---|
| 632 | n/a | # from Finn Bock: |
|---|
| 633 | n/a | # type(sys) is not a module in Jython. what to use instead? |
|---|
| 634 | n/a | # imp.C_EXTENSION is not in Jython. same for get_suffixes and new_module |
|---|
| 635 | n/a | # |
|---|
| 636 | n/a | # given foo.py of: |
|---|
| 637 | n/a | # import sys |
|---|
| 638 | n/a | # sys.modules['foo'] = sys |
|---|
| 639 | n/a | # |
|---|
| 640 | n/a | # ---- standard import mechanism |
|---|
| 641 | n/a | # >>> import foo |
|---|
| 642 | n/a | # >>> foo |
|---|
| 643 | n/a | # <module 'sys' (built-in)> |
|---|
| 644 | n/a | # |
|---|
| 645 | n/a | # ---- revamped import mechanism |
|---|
| 646 | n/a | # >>> import imputil |
|---|
| 647 | n/a | # >>> imputil._test_revamp() |
|---|
| 648 | n/a | # >>> import foo |
|---|
| 649 | n/a | # >>> foo |
|---|
| 650 | n/a | # <module 'foo' from 'foo.py'> |
|---|
| 651 | n/a | # |
|---|
| 652 | n/a | # |
|---|
| 653 | n/a | # from MAL: |
|---|
| 654 | n/a | # should BuiltinImporter exist in sys.path or hard-wired in ImportManager? |
|---|
| 655 | n/a | # need __path__ processing |
|---|
| 656 | n/a | # performance |
|---|
| 657 | n/a | # move chaining to a subclass [gjs: it's been nuked] |
|---|
| 658 | n/a | # deinstall should be possible |
|---|
| 659 | n/a | # query mechanism needed: is a specific Importer installed? |
|---|
| 660 | n/a | # py/pyc/pyo piping hooks to filter/process these files |
|---|
| 661 | n/a | # wish list: |
|---|
| 662 | n/a | # distutils importer hooked to list of standard Internet repositories |
|---|
| 663 | n/a | # module->file location mapper to speed FS-based imports |
|---|
| 664 | n/a | # relative imports |
|---|
| 665 | n/a | # keep chaining so that it can play nice with other import hooks |
|---|
| 666 | n/a | # |
|---|
| 667 | n/a | # from Gordon: |
|---|
| 668 | n/a | # push MAL's mapper into sys.path[0] as a cache (hard-coded for apps) |
|---|
| 669 | n/a | # |
|---|
| 670 | n/a | # from Guido: |
|---|
| 671 | n/a | # need to change sys.* references for rexec environs |
|---|
| 672 | n/a | # need hook for MAL's walk-me-up import strategy, or Tim's absolute strategy |
|---|
| 673 | n/a | # watch out for sys.modules[...] is None |
|---|
| 674 | n/a | # flag to force absolute imports? (speeds _determine_import_context and |
|---|
| 675 | n/a | # checking for a relative module) |
|---|
| 676 | n/a | # insert names of archives into sys.path (see quote below) |
|---|
| 677 | n/a | # note: reload does NOT blast module dict |
|---|
| 678 | n/a | # shift import mechanisms and policies around; provide for hooks, overrides |
|---|
| 679 | n/a | # (see quote below) |
|---|
| 680 | n/a | # add get_source stuff |
|---|
| 681 | n/a | # get_topcode and get_subcode |
|---|
| 682 | n/a | # CRLF handling in _compile |
|---|
| 683 | n/a | # race condition in _compile |
|---|
| 684 | n/a | # refactoring of os.py to deal with _os_bootstrap problem |
|---|
| 685 | n/a | # any special handling to do for importing a module with a SyntaxError? |
|---|
| 686 | n/a | # (e.g. clean up the traceback) |
|---|
| 687 | n/a | # implement "domain" for path-type functionality using pkg namespace |
|---|
| 688 | n/a | # (rather than FS-names like __path__) |
|---|
| 689 | n/a | # don't use the word "private"... maybe "internal" |
|---|
| 690 | n/a | # |
|---|
| 691 | n/a | # |
|---|
| 692 | n/a | # Guido's comments on sys.path caching: |
|---|
| 693 | n/a | # |
|---|
| 694 | n/a | # We could cache this in a dictionary: the ImportManager can have a |
|---|
| 695 | n/a | # cache dict mapping pathnames to importer objects, and a separate |
|---|
| 696 | n/a | # method for coming up with an importer given a pathname that's not yet |
|---|
| 697 | n/a | # in the cache. The method should do a stat and/or look at the |
|---|
| 698 | n/a | # extension to decide which importer class to use; you can register new |
|---|
| 699 | n/a | # importer classes by registering a suffix or a Boolean function, plus a |
|---|
| 700 | n/a | # class. If you register a new importer class, the cache is zapped. |
|---|
| 701 | n/a | # The cache is independent from sys.path (but maintained per |
|---|
| 702 | n/a | # ImportManager instance) so that rearrangements of sys.path do the |
|---|
| 703 | n/a | # right thing. If a path is dropped from sys.path the corresponding |
|---|
| 704 | n/a | # cache entry is simply no longer used. |
|---|
| 705 | n/a | # |
|---|
| 706 | n/a | # My/Guido's comments on factoring ImportManager and Importer: |
|---|
| 707 | n/a | # |
|---|
| 708 | n/a | # > However, we still have a tension occurring here: |
|---|
| 709 | n/a | # > |
|---|
| 710 | n/a | # > 1) implementing policy in ImportManager assists in single-point policy |
|---|
| 711 | n/a | # > changes for app/rexec situations |
|---|
| 712 | n/a | # > 2) implementing policy in Importer assists in package-private policy |
|---|
| 713 | n/a | # > changes for normal, operating conditions |
|---|
| 714 | n/a | # > |
|---|
| 715 | n/a | # > I'll see if I can sort out a way to do this. Maybe the Importer class will |
|---|
| 716 | n/a | # > implement the methods (which can be overridden to change policy) by |
|---|
| 717 | n/a | # > delegating to ImportManager. |
|---|
| 718 | n/a | # |
|---|
| 719 | n/a | # Maybe also think about what kind of policies an Importer would be |
|---|
| 720 | n/a | # likely to want to change. I have a feeling that a lot of the code |
|---|
| 721 | n/a | # there is actually not so much policy but a *necessity* to get things |
|---|
| 722 | n/a | # working given the calling conventions for the __import__ hook: whether |
|---|
| 723 | n/a | # to return the head or tail of a dotted name, or when to do the "finish |
|---|
| 724 | n/a | # fromlist" stuff. |
|---|
| 725 | n/a | # |
|---|