def __import__(name, globals=None, locals=None, fromlist=None): context = getmodcontext(globals) while context is not None: modules = import_in_context(context, name, fromlist) if modules: if fromlist: return modules[-1] else: return modules[0] context = context.getupcontext() raise ImportError(name) def getmodcontext(globals): try: return globals['__context__'] except (KeyError, TypeError): pass try: name = globals['__name__'] except (KeyError, TypeError): return ROOTCTX if '__path__' not in globals: i = name.rfind('.') if i < 0: return ROOTCTX name = name[:i] if isinstance(ROOTCTX, PythonDefaultContext): return PythonDefaultContext(name) else: return ROOTCTX def import_in_context(context, fullname, fromlist=None): components = fullname.split('.') firstname = components[0] mod = context.__import__(firstname) if mod is None: return None result = [mod] parentname = firstname for subname in components[1:]: context = context.getnextcontext(parentname, mod.__dict__) if context is None: raise ImportError, "lost context" mod = context.__import__(subname) if mod is None: raise ImportError, 'No submodule named %s' % (subname,) parentname = subname result.append(mod) if fromlist: context = context.getnextcontext(parentname, mod.__dict__) if context is not None: for tentativesubname in fromlist: context.__import__(tentativesubname) return result # ____________________________________________________________ import new, os, sys, imp def simple_import(sourcefile, mod, storedict): mod.__file__ = getattr(sourcefile, 'name', '?') source = sourcefile.read() sourcefile.close() fullname = mod.__name__ i = fullname.rfind('.') shortname = fullname[i+1:] storedict[shortname] = mod def _cleanup(): try: del storedict[shortname] except KeyError: pass try: co = compile(source, mod.__file__, 'exec') exec co in mod.__dict__ except: _cleanup() raise return mod # ____________________________________________________________ class FilesystemContext(object): __context__ = None # unless overridden in the instance def __import__(self, name): storedict = self.getstoredict() try: return storedict[name] except KeyError: path = self.getpathlist() try: file, pathname, (suff, mode, typ) = imp.find_module(name, path) except ImportError: return None fullname = self.getfullname(name) if typ == imp.PY_SOURCE: mod = new.module(fullname) mod.__context__ = self return simple_import(file, mod, storedict) elif typ == imp.PY_COMPILED: raise ImportError("don't leave your .pyc files around") elif typ == imp.PKG_DIRECTORY: initfile = os.path.join(pathname, '__init__.py') pkg = new.module(fullname) pkg.__path__ = [pathname] pkg.__context__ = self.getsubpkgcontext(pkg) return simple_import(open(initfile, 'U'), pkg, storedict) else: try: mod = imp.load_module(fullname, file, pathname, (suff, mode, typ)) finally: if file is not None: file.close() storedict[name] = mod return mod def getfullname(self, name): return name # default def getpathlist(self): return [] # default def getsubpkgcontext(self, pkg): context = PythonPkgContext(pkg.__dict__) context.__context__ = self.__context__ return context def getupcontext(self): return self.__context__ or ROOTCTX def getnextcontext(self, name, globals): return globals.get('__context__') class PseudoRootContext(FilesystemContext): def getsubpkgcontext(self, pkg): context = PythonPkgContext(pkg.__dict__) context.__context__ = self return context class PythonPkgContext(FilesystemContext): def __init__(self, pkgdict): self.pkgdict = pkgdict def getstoredict(self): return self.pkgdict def getfullname(self, name): return self.pkgdict.get('__name__', '?') + '.' + name def getpathlist(self): return self.pkgdict.get('__path__', []) class PseudoRootPkgContext(PythonPkgContext, PseudoRootContext): pass class SysPathContext(PseudoRootContext): def getstoredict(self): return sys.modules def getpathlist(self): return None # for find_module(), None means "use sys.path and look # for built-in modules as well" def getupcontext(self): return None class PythonDefaultContext(object): def __init__(self, name): self.name = name def getupcontext(self): if self.name is None: return None return ROOTCTX def getnextcontext(self, name, globals): try: return globals['__context__'] except (KeyError, TypeError): return PythonDefaultContext(self.makename(name)) def makename(self, name): thisname = self.name if thisname is None: return name else: return thisname + '.' + name def __import__(self, name): if self.name is None: try: return _original_import_hook(name, None, None, None) except ImportError: return None else: try: parent = _original_import_hook(self.name, None, None, [name]) except ImportError: return None return getattr(parent, name, None) # ____________________________________________________________ ROOTCTX = PythonDefaultContext(None) def install_full_hook(): global ROOTCTX ROOTCTX = SysPathContext() return install_hook() def install_hook(): global _hook_installed, _original_import_hook if not _hook_installed: import __builtin__ _original_import_hook = __builtin__.__import__ __builtin__.__import__ = __import__ _hook_installed = True return _original_import_hook _hook_installed = False