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