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