Blame lib/dbtexmf/dblatex/grubber/plugins.py

Packit Service 76cb02
# This file is part of Rubber and thus covered by the GPL
Packit Service 76cb02
# (c) Emmanuel Beffara, 2002--2006
Packit Service 76cb02
"""
Packit Service 76cb02
Mechanisms to dynamically load extra modules to help the LaTeX compilation.
Packit Service 76cb02
All the modules must be derived from the TexModule class.
Packit Service 76cb02
"""
Packit Service 76cb02
import imp
Packit Service 76cb02
Packit Service 76cb02
from os.path import *
Packit Service 76cb02
from msg import _, msg
Packit Service 76cb02
Packit Service 76cb02
import sys
Packit Service 76cb02
Packit Service 76cb02
class TexModule (object):
Packit Service 76cb02
    """
Packit Service 76cb02
    This is the base class for modules. Each module should define a class
Packit Service 76cb02
    named 'Module' that derives from this one. The default implementation
Packit Service 76cb02
    provides all required methods with no effects.
Packit Service 76cb02
    """
Packit Service 76cb02
    def __init__ (self, env, dict):
Packit Service 76cb02
        """
Packit Service 76cb02
        The constructor receives two arguments: 'env' is the compiling
Packit Service 76cb02
        environment, 'dict' is a dictionary that describes the command that
Packit Service 76cb02
        caused the module to load.
Packit Service 76cb02
        """
Packit Service 76cb02
Packit Service 76cb02
    def pre_compile (self):
Packit Service 76cb02
        """
Packit Service 76cb02
        This method is called before the first LaTeX compilation. It is
Packit Service 76cb02
        supposed to build any file that LaTeX would require to compile the
Packit Service 76cb02
        document correctly. The method must return true on failure.
Packit Service 76cb02
        """
Packit Service 76cb02
        return 0
Packit Service 76cb02
Packit Service 76cb02
    def post_compile (self):
Packit Service 76cb02
        """
Packit Service 76cb02
        This method is called after each LaTeX compilation. It is supposed to
Packit Service 76cb02
        process the compilation results and possibly request a new
Packit Service 76cb02
        compilation. The method must return true on failure.
Packit Service 76cb02
        """
Packit Service 76cb02
        return 0
Packit Service 76cb02
Packit Service 76cb02
    def last_compile (self):
Packit Service 76cb02
        """
Packit Service 76cb02
        This method is called after the last LaTeX compilation.
Packit Service 76cb02
        It is supposed to terminate the compilation for its specific needs.
Packit Service 76cb02
        The method must return true on failure.
Packit Service 76cb02
        """
Packit Service 76cb02
        return 0
Packit Service 76cb02
Packit Service 76cb02
    def clean (self):
Packit Service 76cb02
        """
Packit Service 76cb02
        This method is called when cleaning the compiled files. It is supposed
Packit Service 76cb02
        to remove all the files that this modules generates.
Packit Service 76cb02
        """
Packit Service 76cb02
Packit Service 76cb02
    def command (self, cmd, args):
Packit Service 76cb02
        """
Packit Service 76cb02
        This is called when a directive for the module is found in the source.
Packit Service 76cb02
        The method can raise 'AttributeError' when the directive does not
Packit Service 76cb02
        exist and 'TypeError' if the syntax is wrong. By default, when called
Packit Service 76cb02
        with argument "foo" it calls the method "do_foo" if it exists, and
Packit Service 76cb02
        fails otherwise.
Packit Service 76cb02
        """
Packit Service 76cb02
        getattr(self, "do_" + cmd)(*args)
Packit Service 76cb02
Packit Service 76cb02
    def get_errors (self):
Packit Service 76cb02
        """
Packit Service 76cb02
        This is called if something has failed during an operation performed
Packit Service 76cb02
        by this module. The method returns a generator with items of the same
Packit Service 76cb02
        form as in LaTeXDep.get_errors.
Packit Service 76cb02
        """
Packit Service 76cb02
        if None:
Packit Service 76cb02
            yield None
Packit Service 76cb02
Packit Service 76cb02
Packit Service 76cb02
class Plugins (object):
Packit Service 76cb02
    """
Packit Service 76cb02
    This class gathers operations related to the management of external Python
Packit Service 76cb02
    modules. Modules are requested through the `register' method, and
Packit Service 76cb02
    they are searched for first in the current directory, then in the
Packit Service 76cb02
    (possibly) specified Python package (using Python's path).
Packit Service 76cb02
    """
Packit Service 76cb02
    def __init__ (self, path=None):
Packit Service 76cb02
        """
Packit Service 76cb02
        Initialize the module set, possibly setting a path name in which
Packit Service 76cb02
        modules will be searched for.
Packit Service 76cb02
        """
Packit Service 76cb02
        self.modules = {}
Packit Service 76cb02
        if not path:
Packit Service 76cb02
            self.path = [dirname(__file__)]
Packit Service 76cb02
            sys.path.append(self.path[0])
Packit Service 76cb02
        else:
Packit Service 76cb02
            self.path = path
Packit Service 76cb02
Packit Service 76cb02
    def __getitem__ (self, name):
Packit Service 76cb02
        """
Packit Service 76cb02
        Return the module object of the given name.
Packit Service 76cb02
        """
Packit Service 76cb02
        return self.modules[name]
Packit Service 76cb02
Packit Service 76cb02
    def register (self, name):
Packit Service 76cb02
        """
Packit Service 76cb02
        Attempt to register a module with the specified name. If an
Packit Service 76cb02
        appropriate module is found, load it and store it in the object's
Packit Service 76cb02
        dictionary. Return 0 if no module was found, 1 if a module was found
Packit Service 76cb02
        and loaded, and 2 if the module was found but already loaded.
Packit Service 76cb02
        """
Packit Service 76cb02
        if self.modules.has_key(name):
Packit Service 76cb02
            return 2
Packit Service 76cb02
        try:
Packit Service 76cb02
            file, path, descr = imp.find_module(name, [""])
Packit Service 76cb02
        except ImportError:
Packit Service 76cb02
            if not self.path:
Packit Service 76cb02
                return 0
Packit Service 76cb02
            try:
Packit Service 76cb02
                file, path, descr = imp.find_module(name, self.path)
Packit Service 76cb02
            except ImportError:
Packit Service 76cb02
                return 0
Packit Service 76cb02
        module = imp.load_module(name, file, path, descr)
Packit Service 76cb02
        file.close()
Packit Service 76cb02
        self.modules[name] = module
Packit Service 76cb02
        return 1
Packit Service 76cb02
Packit Service 76cb02
    def clear(self):
Packit Service 76cb02
        """
Packit Service 76cb02
        Empty the module table, unregistering every module registered. No
Packit Service 76cb02
        modules are unloaded, however, but this has no other effect than
Packit Service 76cb02
        speeding the registration if the modules are loaded again.
Packit Service 76cb02
        """
Packit Service 76cb02
        self.modules.clear()
Packit Service 76cb02
Packit Service 76cb02
Packit Service 76cb02
class Modules (Plugins):
Packit Service 76cb02
    """
Packit Service 76cb02
    This class gathers all operations related to the management of modules.
Packit Service 76cb02
    The modules are    searched for first in the current directory, then as
Packit Service 76cb02
    scripts in the 'modules' directory in the program's data directort, then
Packit Service 76cb02
    as a Python module in the package `rubber.latex'.
Packit Service 76cb02
    """
Packit Service 76cb02
    def __init__ (self, env):
Packit Service 76cb02
        #Plugins.__init__(self, rubber.rules.latex.__path__)
Packit Service 76cb02
        Plugins.__init__(self)
Packit Service 76cb02
        self.env = env
Packit Service 76cb02
        self.objects = {}
Packit Service 76cb02
        self.commands = {}
Packit Service 76cb02
Packit Service 76cb02
    def __getitem__ (self, name):
Packit Service 76cb02
        """
Packit Service 76cb02
        Return the module object of the given name.
Packit Service 76cb02
        """
Packit Service 76cb02
        return self.objects[name]
Packit Service 76cb02
Packit Service 76cb02
    def has_key (self, name):
Packit Service 76cb02
        """
Packit Service 76cb02
        Check if a given module is loaded.
Packit Service 76cb02
        """
Packit Service 76cb02
        return self.objects.has_key(name)
Packit Service 76cb02
Packit Service 76cb02
    def register (self, name, dict={}):
Packit Service 76cb02
        """
Packit Service 76cb02
        Attempt to register a package with the specified name. If a module is
Packit Service 76cb02
        found, create an object from the module's class called `Module',
Packit Service 76cb02
        passing it the environment and `dict' as arguments, and execute all
Packit Service 76cb02
        delayed commands for this module. The dictionary describes the
Packit Service 76cb02
        command that caused the registration.
Packit Service 76cb02
        """
Packit Service 76cb02
        if self.has_key(name):
Packit Service 76cb02
            msg.debug(_("module %s already registered") % name)
Packit Service 76cb02
            return 2
Packit Service 76cb02
Packit Service 76cb02
        # First look for a script
Packit Service 76cb02
Packit Service 76cb02
        moddir = ""
Packit Service 76cb02
        mod = None
Packit Service 76cb02
        for path in "", join(moddir, "modules"):
Packit Service 76cb02
            file = join(path, name + ".rub")
Packit Service 76cb02
            if exists(file):
Packit Service 76cb02
                mod = ScriptModule(self.env, file)
Packit Service 76cb02
                msg.log(_("script module %s registered") % name)
Packit Service 76cb02
                break
Packit Service 76cb02
Packit Service 76cb02
        # Then look for a Python module
Packit Service 76cb02
Packit Service 76cb02
        if not mod:
Packit Service 76cb02
            if Plugins.register(self, name) == 0:
Packit Service 76cb02
                msg.debug(_("no support found for %s") % name)
Packit Service 76cb02
                return 0
Packit Service 76cb02
            mod = self.modules[name].Module(self.env, dict)
Packit Service 76cb02
            msg.log(_("built-in module %s registered") % name)
Packit Service 76cb02
Packit Service 76cb02
        # Run any delayed commands.
Packit Service 76cb02
Packit Service 76cb02
        if self.commands.has_key(name):
Packit Service 76cb02
            for (cmd, args, vars) in self.commands[name]:
Packit Service 76cb02
                msg.push_pos(vars)
Packit Service 76cb02
                try:
Packit Service 76cb02
                    mod.command(cmd, args)
Packit Service 76cb02
                except AttributeError:
Packit Service 76cb02
                    msg.warn(_("unknown directive '%s.%s'") % (name, cmd))
Packit Service 76cb02
                except TypeError:
Packit Service 76cb02
                    msg.warn(_("wrong syntax for '%s.%s'") % (name, cmd))
Packit Service 76cb02
                msg.pop_pos()
Packit Service 76cb02
            del self.commands[name]
Packit Service 76cb02
Packit Service 76cb02
        self.objects[name] = mod
Packit Service 76cb02
        return 1
Packit Service 76cb02
Packit Service 76cb02
    def clear (self):
Packit Service 76cb02
        """
Packit Service 76cb02
        Unregister all modules.
Packit Service 76cb02
        """
Packit Service 76cb02
        Plugins.clear(self)
Packit Service 76cb02
        self.objects = {}
Packit Service 76cb02
        self.commands = {}
Packit Service 76cb02
Packit Service 76cb02
    def command (self, mod, cmd, args):
Packit Service 76cb02
        """
Packit Service 76cb02
        Send a command to a particular module. If this module is not loaded,
Packit Service 76cb02
        store the command so that it will be sent when the module is register.
Packit Service 76cb02
        """
Packit Service 76cb02
        if self.objects.has_key(mod):
Packit Service 76cb02
            self.objects[mod].command(cmd, args)
Packit Service 76cb02
        else:
Packit Service 76cb02
            if not self.commands.has_key(mod):
Packit Service 76cb02
                self.commands[mod] = []
Packit Service 76cb02
            self.commands[mod].append((cmd, args, self.env.vars.copy()))
Packit Service 76cb02