blob: c05ae1a750501dbcdb4fe9eda617ebdb5f8eaaed [file] [log] [blame]
Thomas Woutersed03b412007-08-28 21:37:11 +00001
2:mod:`imputil` --- Import utilities
Georg Brandl55ac8f02007-09-01 13:51:09 +00003===================================
Thomas Woutersed03b412007-08-28 21:37:11 +00004
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 older :mod:`ihooks` module,
13:mod:`imputil` takes a dramatically simpler and more straight-forward
14approach to 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.
47 It 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 :class:`Importer` class.
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
Georg Brandl1a3284e2007-12-02 09:40:06 +0000111 import sys, imp, builtins
Thomas Woutersed03b412007-08-28 21:37:11 +0000112
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):
Collin Winterc79461b2007-09-01 23:34:30 +0000125 if not globals or not "__name__" in globals:
Thomas Woutersed03b412007-08-28 21:37:11 +0000126 return None
127 pname = globals['__name__']
Collin Winterc79461b2007-09-01 23:34:30 +0000128 if "__path__" in globals:
Thomas Woutersed03b412007-08-28 21:37:11 +0000129 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
Collin Winterc79461b2007-09-01 23:34:30 +0000159 raise ImportError("No module named " + qname)
Thomas Woutersed03b412007-08-28 21:37:11 +0000160
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:
Collin Winterc79461b2007-09-01 23:34:30 +0000170 raise ImportError("No module named " + mname)
Thomas Woutersed03b412007-08-28 21:37:11 +0000171 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:
Collin Winterc79461b2007-09-01 23:34:30 +0000188 raise ImportError("No module named " + subname)
Thomas Woutersed03b412007-08-28 21:37:11 +0000189
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
Georg Brandl1a3284e2007-12-02 09:40:06 +0000221 original_import = builtins.__import__
222 original_reload = builtins.reload
Thomas Woutersed03b412007-08-28 21:37:11 +0000223
224 # Now install our hooks
Georg Brandl1a3284e2007-12-02 09:40:06 +0000225 builtins.__import__ = import_hook
226 builtins.reload = reload_hook
Thomas Woutersed03b412007-08-28 21:37:11 +0000227
228.. index::
229 module: knee
230
231Also see the :mod:`importers` module (which can be found
232in :file:`Demo/imputil/` in the Python source distribution) for additional
233examples.
234