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