1
2:mod:`imputil` --- Import utilities
3=====================================================
4
5.. module:: imputil
6   :synopsis: Manage and augment the import process.
7   :deprecated:
8
9.. deprecated:: 2.6
10   The :mod:`imputil` module has been removed in Python 3.
11
12
13.. index:: statement: import
14
15This module provides a very handy and useful mechanism for custom
16:keyword:`import` hooks. Compared to the older :mod:`ihooks` module,
17:mod:`imputil` takes a dramatically simpler and more straight-forward
18approach to custom :keyword:`import` functions.
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
50      *parent* specifies a parent module to define a context for importing.
51      It may be ``None``, indicating no particular context for the search.
52
53      *modname* specifies a single module (not dotted) within the parent.
54
55      *fqname* specifies the fully-qualified module name. This is a
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
61      This method should return ``None``, or a 3-tuple.
62
63        * If the module was not found, then ``None`` should be returned.
64
65        * The first item of the 2- or 3-tuple should be the integer 0 or 1,
66          specifying whether the module that was found is a package or not.
67
68        * The second item is the code object for the module (it will be
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).
71
72        * The third item is a dictionary of name/value pairs that will be
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.
78
79
80.. class:: BuiltinImporter()
81
82   Emulate the import mechanism for built-in and frozen modules.  This is a
83   sub-class of the :class:`Importer` class.
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
103Examples
104--------
105
106This is a re-implementation of hierarchical module import.
107
108This 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 clunkier predecessor of this module, "ni".)
112
113::
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
235Also see the :mod:`importers` module (which can be found
236in :file:`Demo/imputil/` in the Python source distribution) for additional
237examples.
238
239