"""Import hook support.

Consistent use of this module will make it possible to change the
different mechanisms involved in loading modules independently.

While the built-in module imp exports interfaces to the built-in
module searching and loading algorithm, and it is possible to replace
the built-in function __import__ in order to change the semantics of
the import statement, until now it has been difficult to combine the
effect of different __import__ hacks, like loading modules from URLs
(rimport.py), implementing a hierarchical module namespace (newimp.py)
or restricted execution (rexec.py).

This module defines three new concepts:

(1) A "file system hooks" class provides an interface to a filesystem.

One hooks class is defined (Hooks), which uses the interface provided
by standard modules os and os.path.  It should be used as the base
class for other hooks classes.

(2) A "module loader" class provides an interface to to search for a
module in a search path and to load it.  It defines a method which
searches for a module in a single directory; by overriding this method
one can redefine the details of the search.  If the directory is None,
built-in and frozen modules are searched instead.

Two module loader class are defined, both implementing the search
strategy used by the built-in __import__ function: ModuleLoader uses
the imp module's find_module interface, while HookableModuleLoader
uses a file system hooks class to interact with the file system.  Both
use the imp module's load_* interfaces to actually load the module.

(3) A "module importer" class provides an interface to import a
module, as well as interfaces to reload and unload a module.  It also
provides interfaces to install and uninstall itself instead of the
default __import__ and reload (and unload) functions.

One module importer class is defined (ModuleImporter), which uses a
module loader instance passed in (by default HookableModuleLoader is
instantiated).

The classes defined here should be used as base classes for extended
functionality along those lines.

If a module mporter class supports dotted names, its import_module()
must return a different value depending on whether it is called on
behalf of a "from ... import ..." statement or not.  (This is caused
by the way the __import__ hook is used by the Python interpreter.)  It
would also do wise to install a different version of reload().

XXX Should the imp.load_* functions also be called via the hooks
instance?

"""


import __builtin__
import imp
import os
import sys


from imp import C_EXTENSION, PY_SOURCE, PY_COMPILED
BUILTIN_MODULE = 32
FROZEN_MODULE = 33


class _Verbose:

    def __init__(self, verbose = 0):
	self.verbose = verbose

    def get_verbose(self):
	return self.verbose

    def set_verbose(self, verbose):
	self.verbose = verbose

    # XXX The following is an experimental interface

    def note(self, *args):
	if self.verbose:
	    apply(self.message, args)

    def message(self, format, *args):
	print format%args


class BasicModuleLoader(_Verbose):

    """Basic module loader.

    This provides the same functionality as built-in import.  It
    doesn't deal with checking sys.modules -- all it provides is
    find_module() and a load_module(), as well as find_module_in_dir()
    which searches just one directory, and can be overridden by a
    derived class to change the module search algorithm when the basic
    dependency on sys.path is unchanged.

    The interface is a little more convenient than imp's:
    find_module(name, [path]) returns None or 'stuff', and
    load_module(name, stuff) loads the module.

    """

    def find_module(self, name, path = None):
	if path is None: 
	    path = [None] + self.default_path()
	for dir in path:
	    stuff = self.find_module_in_dir(name, dir)
	    if stuff: return stuff
	return None

    def default_path(self):
	return sys.path

    def find_module_in_dir(self, name, dir):
	if dir is None:
	    return self.find_builtin_module(name)
	else:
	    try:
		return imp.find_module(name, [dir])
	    except ImportError:
		return None

    def find_builtin_module(self, name):
	if imp.is_builtin(name):
	    return None, '', ('', '', BUILTIN_MODULE)
	if imp.is_frozen(name):
	    return None, '', ('', '', FROZEN_MODULE)
	return None

    def load_module(self, name, stuff):
	file, filename, (suff, mode, type) = stuff
	try:
	    if type == BUILTIN_MODULE:
		return imp.init_builtin(name)
	    if type == FROZEN_MODULE:
		return imp.init_frozen(name)
	    if type == C_EXTENSION:
		return imp.load_dynamic(name, filename, file)
	    if type == PY_SOURCE:
		return imp.load_source(name, filename, file)
	    if type == PY_COMPILED:
		return imp.load_compiled(name, filename, file)
	finally:
	    if file: file.close()
	raise ImportError, "Unrecognized module type (%s) for %s" % \
			   (`type`, name)


class Hooks(_Verbose):

    """Hooks into the filesystem and interpreter.

    By deriving a subclass you can redefine your filesystem interface,
    e.g. to merge it with the URL space.

    This base class behaves just like the native filesystem.

    """

    # imp interface
    def get_suffixes(self): return imp.get_suffixes()
    def new_module(self, name): return imp.new_module(name)
    def is_builtin(self, name): return imp.is_builtin(name)
    def init_builtin(self, name): return imp.init_builtin(name)
    def is_frozen(self, name): return imp.is_frozen(name)
    def init_frozen(self, name): return imp.init_frozen(name)
    def get_frozen_object(self, name): return imp.get_frozen_object(name)
    def load_source(self, name, filename, file=None):
	return imp.load_source(name, filename, file)
    def load_compiled(self, name, filename, file=None):
	return imp.load_compiled(name, filename, file)
    def load_dynamic(self, name, filename, file=None):
	return imp.load_dynamic(name, filename, file)

    def add_module(self, name):
	d = self.modules_dict()
	if d.has_key(name): return d[name]
	d[name] = m = self.new_module(name)
	return m

    # sys interface
    def modules_dict(self): return sys.modules
    def default_path(self): return sys.path

    def path_split(self, x): return os.path.split(x)
    def path_join(self, x, y): return os.path.join(x, y)
    def path_isabs(self, x): return os.path.isabs(x)
    # etc.

    def path_exists(self, x): return os.path.exists(x)
    def path_isdir(self, x): return os.path.isdir(x)
    def path_isfile(self, x): return os.path.isfile(x)
    def path_islink(self, x): return os.path.islink(x)
    # etc.

    def openfile(self, *x): return apply(open, x)
    openfile_error = IOError
    def listdir(self, x): return os.listdir(x)
    listdir_error = os.error
    # etc.


class ModuleLoader(BasicModuleLoader):

    """Default module loader; uses file system hooks.

    By defining suitable hooks, you might be able to load modules from
    other sources than the file system, e.g. from compressed or
    encrypted files, tar files or (if you're brave!) URLs.

    """

    def __init__(self, hooks = None, verbose = 0):
	BasicModuleLoader.__init__(self, verbose)
	self.hooks = hooks or Hooks(verbose)

    def default_path(self):
	return self.hooks.default_path()

    def modules_dict(self):
	return self.hooks.modules_dict()

    def get_hooks(self):
	return self.hooks

    def set_hooks(self, hooks):
	self.hooks = hooks

    def find_builtin_module(self, name):
	if self.hooks.is_builtin(name):
	    return None, '', ('', '', BUILTIN_MODULE)
	if self.hooks.is_frozen(name):
	    return None, '', ('', '', FROZEN_MODULE)
	return None

    def find_module_in_dir(self, name, dir):
	if dir is None:
	    return self.find_builtin_module(name)
	for info in self.hooks.get_suffixes():
	    suff, mode, type = info
	    fullname = self.hooks.path_join(dir, name+suff)
	    try:
		fp = self.hooks.openfile(fullname, mode)
		return fp, fullname, info
	    except self.hooks.openfile_error:
		pass
	return None

    def load_module(self, name, stuff):
	file, filename, (suff, mode, type) = stuff
	if type == BUILTIN_MODULE:
	    return self.hooks.init_builtin(name)
	if type == FROZEN_MODULE:
	    return self.hooks.init_frozen(name)
	if type == C_EXTENSION:
	    m = self.hooks.load_dynamic(name, filename, file)
	elif type == PY_SOURCE:
	    m = self.hooks.load_source(name, filename, file)
	elif type == PY_COMPILED:
	    m = self.hooks.load_compiled(name, filename, file)
	else:
	    raise ImportError, "Unrecognized module type (%s) for %s" % \
		  (`type`, name)
	m.__file__ = filename
	return m


class FancyModuleLoader(ModuleLoader):

    """Fancy module loader -- parses and execs the code itself."""

    def load_module(self, name, stuff):
	file, filename, (suff, mode, type) = stuff
	if type == FROZEN_MODULE:
	    code = self.hooks.get_frozen_object(name)
	elif type == PY_COMPILED:
	    import marshal
	    file.seek(8)
	    code = marshal.load(file)
	elif type == PY_SOURCE:
	    data = file.read()
	    code = compile(data, filename, 'exec')
	else:
	    return ModuleLoader.load_module(self, name, stuff)
	m = self.hooks.add_module(name)
	m.__file__ = filename
	exec code in m.__dict__
	return m


class ModuleImporter(_Verbose):

    """Default module importer; uses module loader.

    This provides the same functionality as built-in import, when
    combined with ModuleLoader.

    """

    def __init__(self, loader = None, verbose = 0):
	_Verbose.__init__(self, verbose)
	self.loader = loader or ModuleLoader(None, verbose)
	self.modules = self.loader.modules_dict()

    def get_loader(self):
	return self.loader

    def set_loader(self, loader):
	self.loader = loader

    def get_hooks(self):
	return self.loader.get_hooks()

    def set_hooks(self, hooks):
	return self.loader.set_hooks(hooks)

    def import_module(self, name, globals={}, locals={}, fromlist=[]):
	if self.modules.has_key(name):
	    return self.modules[name] # Fast path
	stuff = self.loader.find_module(name)
	if not stuff:
	    raise ImportError, "No module named %s" % name
	return self.loader.load_module(name, stuff)

    def reload(self, module, path = None):
	name = module.__name__
	stuff = self.loader.find_module(name, path)
	if not stuff:
	    raise ImportError, "Module %s not found for reload" % name
	return self.loader.load_module(name, stuff)

    def unload(self, module):
	del self.modules[module.__name__]
	# XXX Should this try to clear the module's namespace?

    def install(self):
	self.save_import_module = __builtin__.__import__
	self.save_reload = __builtin__.reload
	if not hasattr(__builtin__, 'unload'):
	    __builtin__.unload = None
	self.save_unload = __builtin__.unload
	__builtin__.__import__ = self.import_module
	__builtin__.reload = self.reload
	__builtin__.unload = self.unload

    def uninstall(self):
	__builtin__.__import__ = self.save_import_module
	__builtin__.reload = self.save_reload
	__builtin__.unload = self.save_unload
	if not __builtin__.unload:
	    del __builtin__.unload


default_importer = None
current_importer = None

def install(importer = None):
    global current_importer
    current_importer = importer or default_importer or ModuleImporter()
    current_importer.install()

def uninstall():
    global current_importer
    current_importer.uninstall()
