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