1import sys 2from types import ModuleType 3import os, imp 4class ImpLoader: 5 code = source = None 6 7 def __init__(self, fullname, file, filename, etc): 8 self.file = file 9 self.filename = filename 10 self.fullname = fullname 11 self.etc = etc 12 13 def load_module(self, fullname): 14 self._reopen() 15 try: 16 mod = imp.load_module(fullname, self.file, self.filename, self.etc) 17 finally: 18 if self.file: 19 self.file.close() 20 return mod 21 22 def get_data(self, pathname): 23 return open(pathname, "rb").read() 24 25 def _reopen(self): 26 if self.file and self.file.closed: 27 mod_type = self.etc[2] 28 if mod_type==imp.PY_SOURCE: 29 self.file = open(self.filename, 'rU') 30 elif mod_type in (imp.PY_COMPILED, imp.C_EXTENSION): 31 self.file = open(self.filename, 'rb') 32 33 def _fix_name(self, fullname): 34 if fullname is None: 35 fullname = self.fullname 36 elif fullname != self.fullname: 37 raise ImportError("Loader for module %s cannot handle " 38 "module %s" % (self.fullname, fullname)) 39 return fullname 40 41 def is_package(self, fullname): 42 fullname = self._fix_name(fullname) 43 return self.etc[2]==imp.PKG_DIRECTORY 44 45 def get_code(self, fullname=None): 46 fullname = self._fix_name(fullname) 47 if self.code is None: 48 mod_type = self.etc[2] 49 if mod_type==imp.PY_SOURCE: 50 source = self.get_source(fullname) 51 self.code = compile(source, self.filename, 'exec') 52 elif mod_type==imp.PY_COMPILED: 53 self._reopen() 54 try: 55 self.code = read_code(self.file) 56 finally: 57 self.file.close() 58 elif mod_type==imp.PKG_DIRECTORY: 59 self.code = self._get_delegate().get_code() 60 return self.code 61 62 def get_source(self, fullname=None): 63 fullname = self._fix_name(fullname) 64 if self.source is None: 65 mod_type = self.etc[2] 66 if mod_type==imp.PY_SOURCE: 67 self._reopen() 68 try: 69 self.source = self.file.read() 70 finally: 71 self.file.close() 72 elif mod_type==imp.PY_COMPILED: 73 if os.path.exists(self.filename[:-1]): 74 f = open(self.filename[:-1], 'rU') 75 self.source = f.read() 76 f.close() 77 elif mod_type==imp.PKG_DIRECTORY: 78 self.source = self._get_delegate().get_source() 79 return self.source 80 81 82 def _get_delegate(self): 83 return ImpImporter(self.filename).find_module('__init__') 84 85 def get_filename(self, fullname=None): 86 fullname = self._fix_name(fullname) 87 mod_type = self.etc[2] 88 if self.etc[2]==imp.PKG_DIRECTORY: 89 return self._get_delegate().get_filename() 90 elif self.etc[2] in (imp.PY_SOURCE, imp.PY_COMPILED, imp.C_EXTENSION): 91 return self.filename 92 return None 93 94 95class ImpImporter: 96 def __init__(self, path=None): 97 self.path = path 98 99 def find_module(self, fullname, path=None): 100 # Note: we ignore 'path' argument since it is only used via meta_path 101 subname = fullname.split(".")[-1] 102 if subname != fullname and self.path is None: 103 return None 104 if self.path is None: 105 path = None 106 else: 107 path = [os.path.realpath(self.path)] 108 try: 109 file, filename, etc = imp.find_module(subname, path) 110 except ImportError: 111 return None 112 return ImpLoader(fullname, file, filename, etc) 113 114 def iter_modules(self, prefix=''): 115 if self.path is None or not os.path.isdir(self.path): 116 return 117 118 yielded = {} 119 import inspect 120 121 filenames = os.listdir(self.path) 122 filenames.sort() # handle packages before same-named modules 123 124 for fn in filenames: 125 modname = inspect.getmodulename(fn) 126 if modname=='__init__' or modname in yielded: 127 continue 128 129 path = os.path.join(self.path, fn) 130 ispkg = False 131 132 if not modname and os.path.isdir(path) and '.' not in fn: 133 modname = fn 134 for fn in os.listdir(path): 135 subname = inspect.getmodulename(fn) 136 if subname=='__init__': 137 ispkg = True 138 break 139 else: 140 continue # not a package 141 142 if modname and '.' not in modname: 143 yielded[modname] = 1 144 yield prefix + modname, ispkg 145 146def get_importer(path_item): 147 try: 148 importer = sys.path_importer_cache[path_item] 149 except KeyError: 150 for path_hook in sys.path_hooks: 151 try: 152 importer = path_hook(path_item) 153 break 154 except ImportError: 155 pass 156 else: 157 importer = None 158 sys.path_importer_cache.setdefault(path_item, importer) 159 160 if importer is None: 161 try: 162 importer = ImpImporter(path_item) 163 except ImportError: 164 importer = None 165 return importer 166 167def iter_importers(fullname=""): 168 if fullname.startswith('.'): 169 raise ImportError("Relative module names not supported") 170 if '.' in fullname: 171 # Get the containing package's __path__ 172 pkg = '.'.join(fullname.split('.')[:-1]) 173 if pkg not in sys.modules: 174 __import__(pkg) 175 path = getattr(sys.modules[pkg], '__path__', None) or [] 176 else: 177 for importer in sys.meta_path: 178 yield importer 179 path = sys.path 180 for item in path: 181 yield get_importer(item) 182 if '.' not in fullname: 183 yield ImpImporter() 184 185def find_loader(fullname): 186 for importer in iter_importers(fullname): 187 loader = importer.find_module(fullname) 188 if loader is not None: 189 return loader 190 191 return None 192 193def get_loader(module_or_name): 194 if module_or_name in sys.modules: 195 module_or_name = sys.modules[module_or_name] 196 if isinstance(module_or_name, ModuleType): 197 module = module_or_name 198 loader = getattr(module, '__loader__', None) 199 if loader is not None: 200 return loader 201 fullname = module.__name__ 202 else: 203 fullname = module_or_name 204 return find_loader(fullname) 205 206 207def _get_filename(loader, mod_name): 208 for attr in ("get_filename", "_get_filename"): 209 meth = getattr(loader, attr, None) 210 if meth is not None: 211 return meth(mod_name) 212 return None 213 214def _get_module_details(mod_name): 215 loader = get_loader(mod_name) 216 if loader is None: 217 raise ImportError("No module named %s" % mod_name) 218 if loader.is_package(mod_name): 219 if mod_name == "__main__" or mod_name.endswith(".__main__"): 220 raise ImportError("Cannot use package as __main__ module") 221 try: 222 pkg_main_name = mod_name + ".__main__" 223 return _get_module_details(pkg_main_name) 224 except ImportError, e: 225 raise ImportError(("%s; %r is a package and cannot " + 226 "be directly executed") %(e, mod_name)) 227 code = loader.get_code(mod_name) 228 if code is None: 229 raise ImportError("No code object available for %s" % mod_name) 230 filename = _get_filename(loader, mod_name) 231 return mod_name, loader, code, filename 232 233def _run_code(code, run_globals, init_globals=None, 234 mod_name=None, mod_fname=None, 235 mod_loader=None, pkg_name=None): 236 if init_globals is not None: 237 run_globals.update(init_globals) 238 run_globals.update(__name__ = mod_name, 239 __file__ = mod_fname, 240 __loader__ = mod_loader, 241 __package__ = pkg_name) 242 exec code in run_globals 243 return run_globals 244 245def run_module(mod_name, init_globals=None, 246 run_name=None): 247 mod_name, loader, code, fname = _get_module_details(mod_name) 248 if run_name is None: 249 run_name = mod_name 250 251 ind = mod_name.rfind(".") 252 if ind != -1: 253 pkg_name = mod_name[:ind] 254 else: 255 pkg_name = mod_name 256 return _run_code(code, {}, init_globals, run_name, 257 fname, loader, pkg_name)