| Sean Reifscheider | 99cafb9 | 2007-08-28 09:07:54 +0000 | [diff] [blame] | 1 |  | 
|  | 2 | :mod:`imputil` --- Import utilities | 
|  | 3 | ===================================================== | 
|  | 4 |  | 
|  | 5 | .. module:: imputil | 
| Georg Brandl | 23b8ddc | 2007-08-28 10:48:18 +0000 | [diff] [blame] | 6 | :synopsis: Manage and augment the import process. | 
| Brett Cannon | 80bb9d9 | 2008-05-08 18:15:14 +0000 | [diff] [blame] | 7 | :deprecated: | 
|  | 8 |  | 
|  | 9 | .. deprecated:: 2.6 | 
| Brett Cannon | a975cd4 | 2008-05-11 01:06:54 +0000 | [diff] [blame^] | 10 | The :mod:`imputil` module has been removed in Python 3.0. | 
| Sean Reifscheider | 99cafb9 | 2007-08-28 09:07:54 +0000 | [diff] [blame] | 11 |  | 
|  | 12 |  | 
|  | 13 | .. index:: statement: import | 
|  | 14 |  | 
|  | 15 | This module provides a very handy and useful mechanism for custom | 
| Georg Brandl | 23b8ddc | 2007-08-28 10:48:18 +0000 | [diff] [blame] | 16 | :keyword:`import` hooks. Compared to the older :mod:`ihooks` module, | 
|  | 17 | :mod:`imputil` takes a dramatically simpler and more straight-forward | 
|  | 18 | approach to custom :keyword:`import` functions. | 
| Sean Reifscheider | 99cafb9 | 2007-08-28 09:07:54 +0000 | [diff] [blame] | 19 |  | 
|  | 20 |  | 
|  | 21 | .. class:: ImportManager([fs_imp]) | 
|  | 22 |  | 
|  | 23 | Manage the import process. | 
|  | 24 |  | 
|  | 25 | .. method:: ImportManager.install([namespace]) | 
|  | 26 |  | 
|  | 27 | Install this ImportManager into the specified namespace. | 
|  | 28 |  | 
|  | 29 | .. method:: ImportManager.uninstall() | 
|  | 30 |  | 
|  | 31 | Restore the previous import mechanism. | 
|  | 32 |  | 
|  | 33 | .. method:: ImportManager.add_suffix(suffix, importFunc) | 
|  | 34 |  | 
|  | 35 | Undocumented. | 
|  | 36 |  | 
|  | 37 |  | 
|  | 38 | .. class:: Importer() | 
|  | 39 |  | 
|  | 40 | Base class for replacing standard import functions. | 
|  | 41 |  | 
|  | 42 | .. method:: Importer.import_top(name) | 
|  | 43 |  | 
|  | 44 | Import a top-level module. | 
|  | 45 |  | 
|  | 46 | .. method:: Importer.get_code(parent, modname, fqname) | 
|  | 47 |  | 
|  | 48 | Find and retrieve the code for the given module. | 
|  | 49 |  | 
| Georg Brandl | 23b8ddc | 2007-08-28 10:48:18 +0000 | [diff] [blame] | 50 | *parent* specifies a parent module to define a context for importing. | 
|  | 51 | It may be ``None``, indicating no particular context for the search. | 
| Sean Reifscheider | 99cafb9 | 2007-08-28 09:07:54 +0000 | [diff] [blame] | 52 |  | 
| Georg Brandl | 23b8ddc | 2007-08-28 10:48:18 +0000 | [diff] [blame] | 53 | *modname* specifies a single module (not dotted) within the parent. | 
| Sean Reifscheider | 99cafb9 | 2007-08-28 09:07:54 +0000 | [diff] [blame] | 54 |  | 
| Georg Brandl | 23b8ddc | 2007-08-28 10:48:18 +0000 | [diff] [blame] | 55 | *fqname* specifies the fully-qualified module name. This is a | 
| Sean Reifscheider | 99cafb9 | 2007-08-28 09:07:54 +0000 | [diff] [blame] | 56 | (potentially) dotted name from the "root" of the module namespace | 
|  | 57 | down to the modname. | 
|  | 58 |  | 
|  | 59 | If there is no parent, then modname==fqname. | 
|  | 60 |  | 
| Georg Brandl | 23b8ddc | 2007-08-28 10:48:18 +0000 | [diff] [blame] | 61 | This method should return ``None``, or a 3-tuple. | 
| Sean Reifscheider | 99cafb9 | 2007-08-28 09:07:54 +0000 | [diff] [blame] | 62 |  | 
| Georg Brandl | 23b8ddc | 2007-08-28 10:48:18 +0000 | [diff] [blame] | 63 | * If the module was not found, then ``None`` should be returned. | 
| Sean Reifscheider | 99cafb9 | 2007-08-28 09:07:54 +0000 | [diff] [blame] | 64 |  | 
|  | 65 | * The first item of the 2- or 3-tuple should be the integer 0 or 1, | 
| Georg Brandl | 23b8ddc | 2007-08-28 10:48:18 +0000 | [diff] [blame] | 66 | specifying whether the module that was found is a package or not. | 
| Sean Reifscheider | 99cafb9 | 2007-08-28 09:07:54 +0000 | [diff] [blame] | 67 |  | 
|  | 68 | * The second item is the code object for the module (it will be | 
| Georg Brandl | 23b8ddc | 2007-08-28 10:48:18 +0000 | [diff] [blame] | 69 | executed within the new module's namespace). This item can also | 
|  | 70 | be a fully-loaded module object (e.g. loaded from a shared lib). | 
| Sean Reifscheider | 99cafb9 | 2007-08-28 09:07:54 +0000 | [diff] [blame] | 71 |  | 
|  | 72 | * The third item is a dictionary of name/value pairs that will be | 
| Georg Brandl | 23b8ddc | 2007-08-28 10:48:18 +0000 | [diff] [blame] | 73 | inserted into new module before the code object is executed. This | 
|  | 74 | is provided in case the module's code expects certain values (such | 
|  | 75 | as where the module was found). When the second item is a module | 
|  | 76 | object, then these names/values will be inserted *after* the module | 
|  | 77 | has been loaded/initialized. | 
| Sean Reifscheider | 99cafb9 | 2007-08-28 09:07:54 +0000 | [diff] [blame] | 78 |  | 
|  | 79 |  | 
|  | 80 | .. class:: BuiltinImporter() | 
|  | 81 |  | 
|  | 82 | Emulate the import mechanism for builtin and frozen modules.  This is a | 
| Georg Brandl | 23b8ddc | 2007-08-28 10:48:18 +0000 | [diff] [blame] | 83 | sub-class of the :class:`Importer` class. | 
| Sean Reifscheider | 99cafb9 | 2007-08-28 09:07:54 +0000 | [diff] [blame] | 84 |  | 
|  | 85 | .. method:: BuiltinImporter.get_code(parent, modname, fqname) | 
|  | 86 |  | 
|  | 87 | Undocumented. | 
|  | 88 |  | 
|  | 89 | .. function:: py_suffix_importer(filename, finfo, fqname) | 
|  | 90 |  | 
|  | 91 | Undocumented. | 
|  | 92 |  | 
|  | 93 | .. class:: DynLoadSuffixImporter([desc]) | 
|  | 94 |  | 
|  | 95 | Undocumented. | 
|  | 96 |  | 
|  | 97 | .. method:: DynLoadSuffixImporter.import_file(filename, finfo, fqname) | 
|  | 98 |  | 
|  | 99 | Undocumented. | 
|  | 100 |  | 
|  | 101 | .. _examples-imputil: | 
|  | 102 |  | 
|  | 103 | Examples | 
|  | 104 | -------- | 
|  | 105 |  | 
|  | 106 | This is a re-implementation of hierarchical module import. | 
|  | 107 |  | 
|  | 108 | This code is intended to be read, not executed.  However, it does work | 
|  | 109 | -- all you need to do to enable it is "import knee". | 
|  | 110 |  | 
|  | 111 | (The name is a pun on the klunkier predecessor of this module, "ni".) | 
|  | 112 |  | 
| Georg Brandl | 23b8ddc | 2007-08-28 10:48:18 +0000 | [diff] [blame] | 113 | :: | 
| Sean Reifscheider | 99cafb9 | 2007-08-28 09:07:54 +0000 | [diff] [blame] | 114 |  | 
|  | 115 | import sys, imp, __builtin__ | 
|  | 116 |  | 
|  | 117 | # Replacement for __import__() | 
|  | 118 | def import_hook(name, globals=None, locals=None, fromlist=None): | 
|  | 119 | parent = determine_parent(globals) | 
|  | 120 | q, tail = find_head_package(parent, name) | 
|  | 121 | m = load_tail(q, tail) | 
|  | 122 | if not fromlist: | 
|  | 123 | return q | 
|  | 124 | if hasattr(m, "__path__"): | 
|  | 125 | ensure_fromlist(m, fromlist) | 
|  | 126 | return m | 
|  | 127 |  | 
|  | 128 | def determine_parent(globals): | 
|  | 129 | if not globals or  not globals.has_key("__name__"): | 
|  | 130 | return None | 
|  | 131 | pname = globals['__name__'] | 
|  | 132 | if globals.has_key("__path__"): | 
|  | 133 | parent = sys.modules[pname] | 
|  | 134 | assert globals is parent.__dict__ | 
|  | 135 | return parent | 
|  | 136 | if '.' in pname: | 
|  | 137 | i = pname.rfind('.') | 
|  | 138 | pname = pname[:i] | 
|  | 139 | parent = sys.modules[pname] | 
|  | 140 | assert parent.__name__ == pname | 
|  | 141 | return parent | 
|  | 142 | return None | 
|  | 143 |  | 
|  | 144 | def find_head_package(parent, name): | 
|  | 145 | if '.' in name: | 
|  | 146 | i = name.find('.') | 
|  | 147 | head = name[:i] | 
|  | 148 | tail = name[i+1:] | 
|  | 149 | else: | 
|  | 150 | head = name | 
|  | 151 | tail = "" | 
|  | 152 | if parent: | 
|  | 153 | qname = "%s.%s" % (parent.__name__, head) | 
|  | 154 | else: | 
|  | 155 | qname = head | 
|  | 156 | q = import_module(head, qname, parent) | 
|  | 157 | if q: return q, tail | 
|  | 158 | if parent: | 
|  | 159 | qname = head | 
|  | 160 | parent = None | 
|  | 161 | q = import_module(head, qname, parent) | 
|  | 162 | if q: return q, tail | 
|  | 163 | raise ImportError, "No module named " + qname | 
|  | 164 |  | 
|  | 165 | def load_tail(q, tail): | 
|  | 166 | m = q | 
|  | 167 | while tail: | 
|  | 168 | i = tail.find('.') | 
|  | 169 | if i < 0: i = len(tail) | 
|  | 170 | head, tail = tail[:i], tail[i+1:] | 
|  | 171 | mname = "%s.%s" % (m.__name__, head) | 
|  | 172 | m = import_module(head, mname, m) | 
|  | 173 | if not m: | 
|  | 174 | raise ImportError, "No module named " + mname | 
|  | 175 | return m | 
|  | 176 |  | 
|  | 177 | def ensure_fromlist(m, fromlist, recursive=0): | 
|  | 178 | for sub in fromlist: | 
|  | 179 | if sub == "*": | 
|  | 180 | if not recursive: | 
|  | 181 | try: | 
|  | 182 | all = m.__all__ | 
|  | 183 | except AttributeError: | 
|  | 184 | pass | 
|  | 185 | else: | 
|  | 186 | ensure_fromlist(m, all, 1) | 
|  | 187 | continue | 
|  | 188 | if sub != "*" and not hasattr(m, sub): | 
|  | 189 | subname = "%s.%s" % (m.__name__, sub) | 
|  | 190 | submod = import_module(sub, subname, m) | 
|  | 191 | if not submod: | 
|  | 192 | raise ImportError, "No module named " + subname | 
|  | 193 |  | 
|  | 194 | def import_module(partname, fqname, parent): | 
|  | 195 | try: | 
|  | 196 | return sys.modules[fqname] | 
|  | 197 | except KeyError: | 
|  | 198 | pass | 
|  | 199 | try: | 
|  | 200 | fp, pathname, stuff = imp.find_module(partname, | 
|  | 201 | parent and parent.__path__) | 
|  | 202 | except ImportError: | 
|  | 203 | return None | 
|  | 204 | try: | 
|  | 205 | m = imp.load_module(fqname, fp, pathname, stuff) | 
|  | 206 | finally: | 
|  | 207 | if fp: fp.close() | 
|  | 208 | if parent: | 
|  | 209 | setattr(parent, partname, m) | 
|  | 210 | return m | 
|  | 211 |  | 
|  | 212 |  | 
|  | 213 | # Replacement for reload() | 
|  | 214 | def reload_hook(module): | 
|  | 215 | name = module.__name__ | 
|  | 216 | if '.' not in name: | 
|  | 217 | return import_module(name, name, None) | 
|  | 218 | i = name.rfind('.') | 
|  | 219 | pname = name[:i] | 
|  | 220 | parent = sys.modules[pname] | 
|  | 221 | return import_module(name[i+1:], name, parent) | 
|  | 222 |  | 
|  | 223 |  | 
|  | 224 | # Save the original hooks | 
|  | 225 | original_import = __builtin__.__import__ | 
|  | 226 | original_reload = __builtin__.reload | 
|  | 227 |  | 
|  | 228 | # Now install our hooks | 
|  | 229 | __builtin__.__import__ = import_hook | 
|  | 230 | __builtin__.reload = reload_hook | 
|  | 231 |  | 
|  | 232 | .. index:: | 
|  | 233 | module: knee | 
|  | 234 |  | 
|  | 235 | Also see the :mod:`importers` module (which can be found | 
|  | 236 | in :file:`Demo/imputil/` in the Python source distribution) for additional | 
|  | 237 | examples. | 
|  | 238 |  |