summaryrefslogtreecommitdiffstats
path: root/Doc/library/imputil.rst
diff options
context:
space:
mode:
Diffstat (limited to 'Doc/library/imputil.rst')
-rw-r--r--Doc/library/imputil.rst234
1 files changed, 234 insertions, 0 deletions
diff --git a/Doc/library/imputil.rst b/Doc/library/imputil.rst
new file mode 100644
index 0000000..34117fa
--- /dev/null
+++ b/Doc/library/imputil.rst
@@ -0,0 +1,234 @@
+
+:mod:`imputil` --- Import utilities
+=====================================================
+
+.. module:: imputil
+ :synopsis: Manage and augment the import process.
+
+
+.. index:: statement: import
+
+This module provides a very handy and useful mechanism for custom
+:keyword:`import` hooks. Compared to the older :mod:`ihooks` module,
+:mod:`imputil` takes a dramatically simpler and more straight-forward
+approach to custom :keyword:`import` functions.
+
+
+.. class:: ImportManager([fs_imp])
+
+ Manage the import process.
+
+ .. method:: ImportManager.install([namespace])
+
+ Install this ImportManager into the specified namespace.
+
+ .. method:: ImportManager.uninstall()
+
+ Restore the previous import mechanism.
+
+ .. method:: ImportManager.add_suffix(suffix, importFunc)
+
+ Undocumented.
+
+
+.. class:: Importer()
+
+ Base class for replacing standard import functions.
+
+ .. method:: Importer.import_top(name)
+
+ Import a top-level module.
+
+ .. method:: Importer.get_code(parent, modname, fqname)
+
+ Find and retrieve the code for the given module.
+
+ *parent* specifies a parent module to define a context for importing.
+ It may be ``None``, indicating no particular context for the search.
+
+ *modname* specifies a single module (not dotted) within the parent.
+
+ *fqname* specifies the fully-qualified module name. This is a
+ (potentially) dotted name from the "root" of the module namespace
+ down to the modname.
+
+ If there is no parent, then modname==fqname.
+
+ This method should return ``None``, or a 3-tuple.
+
+ * If the module was not found, then ``None`` should be returned.
+
+ * The first item of the 2- or 3-tuple should be the integer 0 or 1,
+ specifying whether the module that was found is a package or not.
+
+ * The second item is the code object for the module (it will be
+ executed within the new module's namespace). This item can also
+ be a fully-loaded module object (e.g. loaded from a shared lib).
+
+ * The third item is a dictionary of name/value pairs that will be
+ inserted into new module before the code object is executed. This
+ is provided in case the module's code expects certain values (such
+ as where the module was found). When the second item is a module
+ object, then these names/values will be inserted *after* the module
+ has been loaded/initialized.
+
+
+.. class:: BuiltinImporter()
+
+ Emulate the import mechanism for builtin and frozen modules. This is a
+ sub-class of the :class:`Importer` class.
+
+ .. method:: BuiltinImporter.get_code(parent, modname, fqname)
+
+ Undocumented.
+
+.. function:: py_suffix_importer(filename, finfo, fqname)
+
+ Undocumented.
+
+.. class:: DynLoadSuffixImporter([desc])
+
+ Undocumented.
+
+ .. method:: DynLoadSuffixImporter.import_file(filename, finfo, fqname)
+
+ Undocumented.
+
+.. _examples-imputil:
+
+Examples
+--------
+
+This is a re-implementation of hierarchical module import.
+
+This code is intended to be read, not executed. However, it does work
+-- all you need to do to enable it is "import knee".
+
+(The name is a pun on the klunkier predecessor of this module, "ni".)
+
+::
+
+ import sys, imp, __builtin__
+
+ # Replacement for __import__()
+ def import_hook(name, globals=None, locals=None, fromlist=None):
+ parent = determine_parent(globals)
+ q, tail = find_head_package(parent, name)
+ m = load_tail(q, tail)
+ if not fromlist:
+ return q
+ if hasattr(m, "__path__"):
+ ensure_fromlist(m, fromlist)
+ return m
+
+ def determine_parent(globals):
+ if not globals or not globals.has_key("__name__"):
+ return None
+ pname = globals['__name__']
+ if globals.has_key("__path__"):
+ parent = sys.modules[pname]
+ assert globals is parent.__dict__
+ return parent
+ if '.' in pname:
+ i = pname.rfind('.')
+ pname = pname[:i]
+ parent = sys.modules[pname]
+ assert parent.__name__ == pname
+ return parent
+ return None
+
+ def find_head_package(parent, name):
+ if '.' in name:
+ i = name.find('.')
+ head = name[:i]
+ tail = name[i+1:]
+ else:
+ head = name
+ tail = ""
+ if parent:
+ qname = "%s.%s" % (parent.__name__, head)
+ else:
+ qname = head
+ q = import_module(head, qname, parent)
+ if q: return q, tail
+ if parent:
+ qname = head
+ parent = None
+ q = import_module(head, qname, parent)
+ if q: return q, tail
+ raise ImportError, "No module named " + qname
+
+ def load_tail(q, tail):
+ m = q
+ while tail:
+ i = tail.find('.')
+ if i < 0: i = len(tail)
+ head, tail = tail[:i], tail[i+1:]
+ mname = "%s.%s" % (m.__name__, head)
+ m = import_module(head, mname, m)
+ if not m:
+ raise ImportError, "No module named " + mname
+ return m
+
+ def ensure_fromlist(m, fromlist, recursive=0):
+ for sub in fromlist:
+ if sub == "*":
+ if not recursive:
+ try:
+ all = m.__all__
+ except AttributeError:
+ pass
+ else:
+ ensure_fromlist(m, all, 1)
+ continue
+ if sub != "*" and not hasattr(m, sub):
+ subname = "%s.%s" % (m.__name__, sub)
+ submod = import_module(sub, subname, m)
+ if not submod:
+ raise ImportError, "No module named " + subname
+
+ def import_module(partname, fqname, parent):
+ try:
+ return sys.modules[fqname]
+ except KeyError:
+ pass
+ try:
+ fp, pathname, stuff = imp.find_module(partname,
+ parent and parent.__path__)
+ except ImportError:
+ return None
+ try:
+ m = imp.load_module(fqname, fp, pathname, stuff)
+ finally:
+ if fp: fp.close()
+ if parent:
+ setattr(parent, partname, m)
+ return m
+
+
+ # Replacement for reload()
+ def reload_hook(module):
+ name = module.__name__
+ if '.' not in name:
+ return import_module(name, name, None)
+ i = name.rfind('.')
+ pname = name[:i]
+ parent = sys.modules[pname]
+ return import_module(name[i+1:], name, parent)
+
+
+ # Save the original hooks
+ original_import = __builtin__.__import__
+ original_reload = __builtin__.reload
+
+ # Now install our hooks
+ __builtin__.__import__ = import_hook
+ __builtin__.reload = reload_hook
+
+.. index::
+ module: knee
+
+Also see the :mod:`importers` module (which can be found
+in :file:`Demo/imputil/` in the Python source distribution) for additional
+examples.
+