blob: b88beb408ca996ba22015a072813461931e62a3f [file] [log] [blame]
Sean Reifscheider99cafb92007-08-28 09:07:54 +00001
2:mod:`imputil` --- Import utilities
3=====================================================
4
5.. module:: imputil
6 :synopsis: Manage and augment the import process
7
8
9.. index:: statement: import
10
11This module provides a very handy and useful mechanism for custom
12:keyword:`import` hooks. Compared to the standard library's ihooks.py,
13imputil.py takes a dramatically simpler and more straight-forward approach
14to custom :keyword:`import` functions.
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
46 parent specifies a parent module to define a context for importing. It
47 may be None, indicating no particular context for the search.
48
49 modname specifies a single module (not dotted) within the parent.
50
51 fqname specifies the fully-qualified module name. This is a
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
57 This method should return None, or a 3-tuple.
58
59 * If the module was not found, then None should be returned.
60
61 * The first item of the 2- or 3-tuple should be the integer 0 or 1,
62 specifying whether the module that was found is a package or not.
63
64 * The second item is the code object for the module (it will be
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).
67
68 * The third item is a dictionary of name/value pairs that will be
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.
74
75
76.. class:: BuiltinImporter()
77
78 Emulate the import mechanism for builtin and frozen modules. This is a
79 sub-class of the Importer module.
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
99Examples
100--------
101
102This is a re-implementation of hierarchical module import.
103
104This 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
109
110 import sys, imp, __builtin__
111
112 # Replacement for __import__()
113 def import_hook(name, globals=None, locals=None, fromlist=None):
114 parent = determine_parent(globals)
115 q, tail = find_head_package(parent, name)
116 m = load_tail(q, tail)
117 if not fromlist:
118 return q
119 if hasattr(m, "__path__"):
120 ensure_fromlist(m, fromlist)
121 return m
122
123 def determine_parent(globals):
124 if not globals or not globals.has_key("__name__"):
125 return None
126 pname = globals['__name__']
127 if globals.has_key("__path__"):
128 parent = sys.modules[pname]
129 assert globals is parent.__dict__
130 return parent
131 if '.' in pname:
132 i = pname.rfind('.')
133 pname = pname[:i]
134 parent = sys.modules[pname]
135 assert parent.__name__ == pname
136 return parent
137 return None
138
139 def find_head_package(parent, name):
140 if '.' in name:
141 i = name.find('.')
142 head = name[:i]
143 tail = name[i+1:]
144 else:
145 head = name
146 tail = ""
147 if parent:
148 qname = "%s.%s" % (parent.__name__, head)
149 else:
150 qname = head
151 q = import_module(head, qname, parent)
152 if q: return q, tail
153 if parent:
154 qname = head
155 parent = None
156 q = import_module(head, qname, parent)
157 if q: return q, tail
158 raise ImportError, "No module named " + qname
159
160 def load_tail(q, tail):
161 m = q
162 while tail:
163 i = tail.find('.')
164 if i < 0: i = len(tail)
165 head, tail = tail[:i], tail[i+1:]
166 mname = "%s.%s" % (m.__name__, head)
167 m = import_module(head, mname, m)
168 if not m:
169 raise ImportError, "No module named " + mname
170 return m
171
172 def ensure_fromlist(m, fromlist, recursive=0):
173 for sub in fromlist:
174 if sub == "*":
175 if not recursive:
176 try:
177 all = m.__all__
178 except AttributeError:
179 pass
180 else:
181 ensure_fromlist(m, all, 1)
182 continue
183 if sub != "*" and not hasattr(m, sub):
184 subname = "%s.%s" % (m.__name__, sub)
185 submod = import_module(sub, subname, m)
186 if not submod:
187 raise ImportError, "No module named " + subname
188
189 def import_module(partname, fqname, parent):
190 try:
191 return sys.modules[fqname]
192 except KeyError:
193 pass
194 try:
195 fp, pathname, stuff = imp.find_module(partname,
196 parent and parent.__path__)
197 except ImportError:
198 return None
199 try:
200 m = imp.load_module(fqname, fp, pathname, stuff)
201 finally:
202 if fp: fp.close()
203 if parent:
204 setattr(parent, partname, m)
205 return m
206
207
208 # Replacement for reload()
209 def reload_hook(module):
210 name = module.__name__
211 if '.' not in name:
212 return import_module(name, name, None)
213 i = name.rfind('.')
214 pname = name[:i]
215 parent = sys.modules[pname]
216 return import_module(name[i+1:], name, parent)
217
218
219 # Save the original hooks
220 original_import = __builtin__.__import__
221 original_reload = __builtin__.reload
222
223 # Now install our hooks
224 __builtin__.__import__ = import_hook
225 __builtin__.reload = reload_hook
226
227.. index::
228 module: knee
229
230Also see the :mod:`importers` module (which can be found
231in :file:`Demo/imputil/` in the Python source distribution) for additional
232examples.
233