ยปCore Development>Code coverage>Lib/ihooks.py

Python code coverage for Lib/ihooks.py

#countcontent
1n/a"""Import hook support.
2n/a
3n/aConsistent use of this module will make it possible to change the
4n/adifferent mechanisms involved in loading modules independently.
5n/a
6n/aWhile the built-in module imp exports interfaces to the built-in
7n/amodule searching and loading algorithm, and it is possible to replace
8n/athe built-in function __import__ in order to change the semantics of
9n/athe import statement, until now it has been difficult to combine the
10n/aeffect of different __import__ hacks, like loading modules from URLs
11n/aby rimport.py, or restricted execution by rexec.py.
12n/a
13n/aThis module defines three new concepts:
14n/a
15n/a1) A "file system hooks" class provides an interface to a filesystem.
16n/a
17n/aOne hooks class is defined (Hooks), which uses the interface provided
18n/aby standard modules os and os.path. It should be used as the base
19n/aclass for other hooks classes.
20n/a
21n/a2) A "module loader" class provides an interface to search for a
22n/amodule in a search path and to load it. It defines a method which
23n/asearches for a module in a single directory; by overriding this method
24n/aone can redefine the details of the search. If the directory is None,
25n/abuilt-in and frozen modules are searched instead.
26n/a
27n/aTwo module loader class are defined, both implementing the search
28n/astrategy used by the built-in __import__ function: ModuleLoader uses
29n/athe imp module's find_module interface, while HookableModuleLoader
30n/auses a file system hooks class to interact with the file system. Both
31n/ause the imp module's load_* interfaces to actually load the module.
32n/a
33n/a3) A "module importer" class provides an interface to import a
34n/amodule, as well as interfaces to reload and unload a module. It also
35n/aprovides interfaces to install and uninstall itself instead of the
36n/adefault __import__ and reload (and unload) functions.
37n/a
38n/aOne module importer class is defined (ModuleImporter), which uses a
39n/amodule loader instance passed in (by default HookableModuleLoader is
40n/ainstantiated).
41n/a
42n/aThe classes defined here should be used as base classes for extended
43n/afunctionality along those lines.
44n/a
45n/aIf a module importer class supports dotted names, its import_module()
46n/amust return a different value depending on whether it is called on
47n/abehalf of a "from ... import ..." statement or not. (This is caused
48n/aby the way the __import__ hook is used by the Python interpreter.) It
49n/awould also do wise to install a different version of reload().
50n/a
511"""
521from warnings import warnpy3k, warn
531warnpy3k("the ihooks module has been removed in Python 3.0", stacklevel=2)
541del warnpy3k
55n/a
561import __builtin__
571import imp
581import os
591import sys
60n/a
611__all__ = ["BasicModuleLoader","Hooks","ModuleLoader","FancyModuleLoader",
621 "BasicModuleImporter","ModuleImporter","install","uninstall"]
63n/a
641VERBOSE = 0
65n/a
66n/a
671from imp import C_EXTENSION, PY_SOURCE, PY_COMPILED
681from imp import C_BUILTIN, PY_FROZEN, PKG_DIRECTORY
691BUILTIN_MODULE = C_BUILTIN
701FROZEN_MODULE = PY_FROZEN
71n/a
72n/a
732class _Verbose:
74n/a
751 def __init__(self, verbose = VERBOSE):
760 self.verbose = verbose
77n/a
781 def get_verbose(self):
790 return self.verbose
80n/a
811 def set_verbose(self, verbose):
820 self.verbose = verbose
83n/a
84n/a # XXX The following is an experimental interface
85n/a
861 def note(self, *args):
870 if self.verbose:
880 self.message(*args)
89n/a
901 def message(self, format, *args):
910 if args:
920 print format%args
93n/a else:
940 print format
95n/a
96n/a
972class BasicModuleLoader(_Verbose):
98n/a
99n/a """Basic module loader.
100n/a
101n/a This provides the same functionality as built-in import. It
102n/a doesn't deal with checking sys.modules -- all it provides is
103n/a find_module() and a load_module(), as well as find_module_in_dir()
104n/a which searches just one directory, and can be overridden by a
105n/a derived class to change the module search algorithm when the basic
106n/a dependency on sys.path is unchanged.
107n/a
108n/a The interface is a little more convenient than imp's:
109n/a find_module(name, [path]) returns None or 'stuff', and
110n/a load_module(name, stuff) loads the module.
111n/a
1121 """
113n/a
1141 def find_module(self, name, path = None):
1150 if path is None:
1160 path = [None] + self.default_path()
1170 for dir in path:
1180 stuff = self.find_module_in_dir(name, dir)
1190 if stuff: return stuff
1200 return None
121n/a
1221 def default_path(self):
1230 return sys.path
124n/a
1251 def find_module_in_dir(self, name, dir):
1260 if dir is None:
1270 return self.find_builtin_module(name)
128n/a else:
1290 try:
1300 return imp.find_module(name, [dir])
1310 except ImportError:
1320 return None
133n/a
1341 def find_builtin_module(self, name):
135n/a # XXX frozen packages?
1360 if imp.is_builtin(name):
1370 return None, '', ('', '', BUILTIN_MODULE)
1380 if imp.is_frozen(name):
1390 return None, '', ('', '', FROZEN_MODULE)
1400 return None
141n/a
1421 def load_module(self, name, stuff):
1430 file, filename, info = stuff
1440 try:
1450 return imp.load_module(name, file, filename, info)
146n/a finally:
1470 if file: file.close()
148n/a
149n/a
1502class Hooks(_Verbose):
151n/a
152n/a """Hooks into the filesystem and interpreter.
153n/a
154n/a By deriving a subclass you can redefine your filesystem interface,
155n/a e.g. to merge it with the URL space.
156n/a
157n/a This base class behaves just like the native filesystem.
158n/a
1591 """
160n/a
161n/a # imp interface
1621 def get_suffixes(self): return imp.get_suffixes()
1631 def new_module(self, name): return imp.new_module(name)
1641 def is_builtin(self, name): return imp.is_builtin(name)
1651 def init_builtin(self, name): return imp.init_builtin(name)
1661 def is_frozen(self, name): return imp.is_frozen(name)
1671 def init_frozen(self, name): return imp.init_frozen(name)
1681 def get_frozen_object(self, name): return imp.get_frozen_object(name)
1691 def load_source(self, name, filename, file=None):
1700 return imp.load_source(name, filename, file)
1711 def load_compiled(self, name, filename, file=None):
1720 return imp.load_compiled(name, filename, file)
1731 def load_dynamic(self, name, filename, file=None):
1740 return imp.load_dynamic(name, filename, file)
1751 def load_package(self, name, filename, file=None):
1760 return imp.load_module(name, file, filename, ("", "", PKG_DIRECTORY))
177n/a
1781 def add_module(self, name):
1790 d = self.modules_dict()
1800 if name in d: return d[name]
1810 d[name] = m = self.new_module(name)
1820 return m
183n/a
184n/a # sys interface
1851 def modules_dict(self): return sys.modules
1861 def default_path(self): return sys.path
187n/a
1881 def path_split(self, x): return os.path.split(x)
1891 def path_join(self, x, y): return os.path.join(x, y)
1901 def path_isabs(self, x): return os.path.isabs(x)
191n/a # etc.
192n/a
1931 def path_exists(self, x): return os.path.exists(x)
1941 def path_isdir(self, x): return os.path.isdir(x)
1951 def path_isfile(self, x): return os.path.isfile(x)
1961 def path_islink(self, x): return os.path.islink(x)
197n/a # etc.
198n/a
1991 def openfile(self, *x): return open(*x)
2001 openfile_error = IOError
2011 def listdir(self, x): return os.listdir(x)
2021 listdir_error = os.error
203n/a # etc.
204n/a
205n/a
2062class ModuleLoader(BasicModuleLoader):
207n/a
208n/a """Default module loader; uses file system hooks.
209n/a
210n/a By defining suitable hooks, you might be able to load modules from
211n/a other sources than the file system, e.g. from compressed or
212n/a encrypted files, tar files or (if you're brave!) URLs.
213n/a
2141 """
215n/a
2161 def __init__(self, hooks = None, verbose = VERBOSE):
2170 BasicModuleLoader.__init__(self, verbose)
2180 self.hooks = hooks or Hooks(verbose)
219n/a
2201 def default_path(self):
2210 return self.hooks.default_path()
222n/a
2231 def modules_dict(self):
2240 return self.hooks.modules_dict()
225n/a
2261 def get_hooks(self):
2270 return self.hooks
228n/a
2291 def set_hooks(self, hooks):
2300 self.hooks = hooks
231n/a
2321 def find_builtin_module(self, name):
233n/a # XXX frozen packages?
2340 if self.hooks.is_builtin(name):
2350 return None, '', ('', '', BUILTIN_MODULE)
2360 if self.hooks.is_frozen(name):
2370 return None, '', ('', '', FROZEN_MODULE)
2380 return None
239n/a
2401 def find_module_in_dir(self, name, dir, allow_packages=1):
2410 if dir is None:
2420 return self.find_builtin_module(name)
2430 if allow_packages:
2440 fullname = self.hooks.path_join(dir, name)
2450 if self.hooks.path_isdir(fullname):
2460 stuff = self.find_module_in_dir("__init__", fullname, 0)
2470 if stuff:
2480 file = stuff[0]
2490 if file: file.close()
2500 return None, fullname, ('', '', PKG_DIRECTORY)
2510 for info in self.hooks.get_suffixes():
2520 suff, mode, type = info
2530 fullname = self.hooks.path_join(dir, name+suff)
2540 try:
2550 fp = self.hooks.openfile(fullname, mode)
2560 return fp, fullname, info
2570 except self.hooks.openfile_error:
2580 pass
2590 return None
260n/a
2611 def load_module(self, name, stuff):
2620 file, filename, info = stuff
2630 (suff, mode, type) = info
2640 try:
2650 if type == BUILTIN_MODULE:
2660 return self.hooks.init_builtin(name)
2670 if type == FROZEN_MODULE:
2680 return self.hooks.init_frozen(name)
2690 if type == C_EXTENSION:
2700 m = self.hooks.load_dynamic(name, filename, file)
2710 elif type == PY_SOURCE:
2720 m = self.hooks.load_source(name, filename, file)
2730 elif type == PY_COMPILED:
2740 m = self.hooks.load_compiled(name, filename, file)
2750 elif type == PKG_DIRECTORY:
2760 m = self.hooks.load_package(name, filename, file)
277n/a else:
2780 raise ImportError, "Unrecognized module type (%r) for %s" % \
2790 (type, name)
280n/a finally:
2810 if file: file.close()
2820 m.__file__ = filename
2830 return m
284n/a
285n/a
2862class FancyModuleLoader(ModuleLoader):
287n/a
2881 """Fancy module loader -- parses and execs the code itself."""
289n/a
2901 def load_module(self, name, stuff):
2910 file, filename, (suff, mode, type) = stuff
2920 realfilename = filename
2930 path = None
294n/a
2950 if type == PKG_DIRECTORY:
2960 initstuff = self.find_module_in_dir("__init__", filename, 0)
2970 if not initstuff:
2980 raise ImportError, "No __init__ module in package %s" % name
2990 initfile, initfilename, initinfo = initstuff
3000 initsuff, initmode, inittype = initinfo
3010 if inittype not in (PY_COMPILED, PY_SOURCE):
3020 if initfile: initfile.close()
3030 raise ImportError, \
3040 "Bad type (%r) for __init__ module in package %s" % (
3050 inittype, name)
3060 path = [filename]
3070 file = initfile
3080 realfilename = initfilename
3090 type = inittype
310n/a
3110 if type == FROZEN_MODULE:
3120 code = self.hooks.get_frozen_object(name)
3130 elif type == PY_COMPILED:
3140 import marshal
3150 file.seek(8)
3160 code = marshal.load(file)
3170 elif type == PY_SOURCE:
3180 data = file.read()
3190 code = compile(data, realfilename, 'exec')
320n/a else:
3210 return ModuleLoader.load_module(self, name, stuff)
322n/a
3230 m = self.hooks.add_module(name)
3240 if path:
3250 m.__path__ = path
3260 m.__file__ = filename
3270 try:
3280 exec code in m.__dict__
3290 except:
3300 d = self.hooks.modules_dict()
3310 if name in d:
3320 del d[name]
3330 raise
3340 return m
335n/a
336n/a
3372class BasicModuleImporter(_Verbose):
338n/a
339n/a """Basic module importer; uses module loader.
340n/a
341n/a This provides basic import facilities but no package imports.
342n/a
3431 """
344n/a
3451 def __init__(self, loader = None, verbose = VERBOSE):
3460 _Verbose.__init__(self, verbose)
3470 self.loader = loader or ModuleLoader(None, verbose)
3480 self.modules = self.loader.modules_dict()
349n/a
3501 def get_loader(self):
3510 return self.loader
352n/a
3531 def set_loader(self, loader):
3540 self.loader = loader
355n/a
3561 def get_hooks(self):
3570 return self.loader.get_hooks()
358n/a
3591 def set_hooks(self, hooks):
3600 return self.loader.set_hooks(hooks)
361n/a
3621 def import_module(self, name, globals={}, locals={}, fromlist=[]):
3630 name = str(name)
3640 if name in self.modules:
3650 return self.modules[name] # Fast path
3660 stuff = self.loader.find_module(name)
3670 if not stuff:
3680 raise ImportError, "No module named %s" % name
3690 return self.loader.load_module(name, stuff)
370n/a
3711 def reload(self, module, path = None):
3720 name = str(module.__name__)
3730 stuff = self.loader.find_module(name, path)
3740 if not stuff:
3750 raise ImportError, "Module %s not found for reload" % name
3760 return self.loader.load_module(name, stuff)
377n/a
3781 def unload(self, module):
3790 del self.modules[str(module.__name__)]
380n/a # XXX Should this try to clear the module's namespace?
381n/a
3821 def install(self):
3830 self.save_import_module = __builtin__.__import__
3840 self.save_reload = __builtin__.reload
3850 if not hasattr(__builtin__, 'unload'):
3860 __builtin__.unload = None
3870 self.save_unload = __builtin__.unload
3880 __builtin__.__import__ = self.import_module
3890 __builtin__.reload = self.reload
3900 __builtin__.unload = self.unload
391n/a
3921 def uninstall(self):
3930 __builtin__.__import__ = self.save_import_module
3940 __builtin__.reload = self.save_reload
3950 __builtin__.unload = self.save_unload
3960 if not __builtin__.unload:
3970 del __builtin__.unload
398n/a
399n/a
4002class ModuleImporter(BasicModuleImporter):
401n/a
4021 """A module importer that supports packages."""
403n/a
4041 def import_module(self, name, globals=None, locals=None, fromlist=None,
4051 level=-1):
4060 parent = self.determine_parent(globals, level)
4070 q, tail = self.find_head_package(parent, str(name))
4080 m = self.load_tail(q, tail)
4090 if not fromlist:
4100 return q
4110 if hasattr(m, "__path__"):
4120 self.ensure_fromlist(m, fromlist)
4130 return m
414n/a
4151 def determine_parent(self, globals, level=-1):
4160 if not globals or not level:
4170 return None
4180 pkgname = globals.get('__package__')
4190 if pkgname is not None:
4200 if not pkgname and level > 0:
4210 raise ValueError, 'Attempted relative import in non-package'
422n/a else:
423n/a # __package__ not set, figure it out and set it
4240 modname = globals.get('__name__')
4250 if modname is None:
4260 return None
4270 if "__path__" in globals:
428n/a # __path__ is set so modname is already the package name
4290 pkgname = modname
430n/a else:
431n/a # normal module, work out package name if any
4320 if '.' not in modname:
4330 if level > 0:
4340 raise ValueError, ('Attempted relative import in '
435n/a 'non-package')
4360 globals['__package__'] = None
4370 return None
4380 pkgname = modname.rpartition('.')[0]
4390 globals['__package__'] = pkgname
4400 if level > 0:
4410 dot = len(pkgname)
4420 for x in range(level, 1, -1):
4430 try:
4440 dot = pkgname.rindex('.', 0, dot)
4450 except ValueError:
4460 raise ValueError('attempted relative import beyond '
447n/a 'top-level package')
4480 pkgname = pkgname[:dot]
4490 try:
4500 return sys.modules[pkgname]
4510 except KeyError:
4520 if level < 1:
4530 warn("Parent module '%s' not found while handling "
4540 "absolute import" % pkgname, RuntimeWarning, 1)
4550 return None
456n/a else:
4570 raise SystemError, ("Parent module '%s' not loaded, cannot "
4580 "perform relative import" % pkgname)
459n/a
4601 def find_head_package(self, parent, name):
4610 if '.' in name:
4620 i = name.find('.')
4630 head = name[:i]
4640 tail = name[i+1:]
465n/a else:
4660 head = name
4670 tail = ""
4680 if parent:
4690 qname = "%s.%s" % (parent.__name__, head)
470n/a else:
4710 qname = head
4720 q = self.import_it(head, qname, parent)
4730 if q: return q, tail
4740 if parent:
4750 qname = head
4760 parent = None
4770 q = self.import_it(head, qname, parent)
4780 if q: return q, tail
4790 raise ImportError, "No module named '%s'" % qname
480n/a
4811 def load_tail(self, q, tail):
4820 m = q
4830 while tail:
4840 i = tail.find('.')
4850 if i < 0: i = len(tail)
4860 head, tail = tail[:i], tail[i+1:]
4870 mname = "%s.%s" % (m.__name__, head)
4880 m = self.import_it(head, mname, m)
4890 if not m:
4900 raise ImportError, "No module named '%s'" % mname
4910 return m
492n/a
4931 def ensure_fromlist(self, m, fromlist, recursive=0):
4940 for sub in fromlist:
4950 if sub == "*":
4960 if not recursive:
4970 try:
4980 all = m.__all__
4990 except AttributeError:
5000 pass
501n/a else:
5020 self.ensure_fromlist(m, all, 1)
5030 continue
5040 if sub != "*" and not hasattr(m, sub):
5050 subname = "%s.%s" % (m.__name__, sub)
5060 submod = self.import_it(sub, subname, m)
5070 if not submod:
5080 raise ImportError, "No module named '%s'" % subname
509n/a
5101 def import_it(self, partname, fqname, parent, force_load=0):
5110 if not partname:
512n/a # completely empty module name should only happen in
513n/a # 'from . import' or __import__("")
5140 return parent
5150 if not force_load:
5160 try:
5170 return self.modules[fqname]
5180 except KeyError:
5190 pass
5200 try:
5210 path = parent and parent.__path__
5220 except AttributeError:
5230 return None
5240 partname = str(partname)
5250 stuff = self.loader.find_module(partname, path)
5260 if not stuff:
5270 return None
5280 fqname = str(fqname)
5290 m = self.loader.load_module(fqname, stuff)
5300 if parent:
5310 setattr(parent, partname, m)
5320 return m
533n/a
5341 def reload(self, module):
5350 name = str(module.__name__)
5360 if '.' not in name:
5370 return self.import_it(name, name, None, force_load=1)
5380 i = name.rfind('.')
5390 pname = name[:i]
5400 parent = self.modules[pname]
5410 return self.import_it(name[i+1:], name, parent, force_load=1)
542n/a
543n/a
5441default_importer = None
5451current_importer = None
546n/a
5471def install(importer = None):
548n/a global current_importer
5490 current_importer = importer or default_importer or ModuleImporter()
5500 current_importer.install()
551n/a
5521def uninstall():
553n/a global current_importer
5540 current_importer.uninstall()