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 | |