Blame lib/dbtexmf/core/dbtex.py

Packit 0f19cf
#
Packit 0f19cf
# DbTex base class handling the compilation of a DocBook file via
Packit 0f19cf
# XSL Transformation and some TeX engine compilation.
Packit 0f19cf
#
Packit Service f3de8e
from __future__ import print_function
Packit Service f3de8e
Packit 0f19cf
import sys
Packit 0f19cf
import os
Packit 0f19cf
import re
Packit 0f19cf
import shlex
Packit 0f19cf
import tempfile
Packit 0f19cf
import shutil
Packit 0f19cf
import glob
Packit 0f19cf
import imp
Packit 0f19cf
from optparse import OptionParser
Packit Service f3de8e
from io import open
Packit 0f19cf
Packit 0f19cf
from dbtexmf.core.txtparser import texinputs_parse, texstyle_parse
Packit 0f19cf
from dbtexmf.core.confparser import DbtexConfig
Packit 0f19cf
from dbtexmf.xslt import xslt
Packit 0f19cf
import dbtexmf.core.logger as logger
Packit 0f19cf
from dbtexmf.core.error import signal_error, failed_exit, dump_stack
Packit 0f19cf
Packit Service f3de8e
try:
Packit Service f3de8e
    from urllib import pathname2url
Packit Service f3de8e
except ImportError:
Packit Service f3de8e
    from urllib.request import pathname2url
Packit Service f3de8e
Packit 0f19cf
Packit 0f19cf
def suffix_replace(path, oldext, newext=""):
Packit 0f19cf
    (root, ext) = os.path.splitext(path)
Packit 0f19cf
    if ext == oldext:
Packit 0f19cf
        return (root+newext)
Packit 0f19cf
    else:
Packit 0f19cf
        return (path+newext)
Packit 0f19cf
Packit 0f19cf
def path_to_uri(path):
Packit 0f19cf
    if os.name == 'nt':
Packit Service f3de8e
        return 'file:' + pathname2url(path).replace('|', ':', 1)
Packit 0f19cf
    else:
Packit Service f3de8e
        return pathname2url(path)
Packit 0f19cf
Packit 0f19cf
Packit 0f19cf
class Document:
Packit 0f19cf
    """
Packit 0f19cf
    Wrapper structure of the files built during the compilation per document
Packit 0f19cf
    """
Packit 0f19cf
    def __init__(self, filename, binfmt="pdf"):
Packit 0f19cf
        self.inputname = filename
Packit 0f19cf
        self.basename = os.path.splitext(filename)[0]
Packit 0f19cf
        self.rawfile = self.basename + ".rtex"
Packit 0f19cf
        self.texfile = self.basename + ".tex"
Packit 0f19cf
        self.binfile = self.basename + "." + binfmt
Packit 0f19cf
Packit 0f19cf
    def has_subext(self, ext):
Packit 0f19cf
        return (os.path.splitext(self.basename)[1] == ext)
Packit 0f19cf
Packit Service f3de8e
    def __eq__(self, other):
Packit Service f3de8e
        if self.rawfile == other:
Packit Service f3de8e
            return True
Packit Service f3de8e
        if self.texfile == other:
Packit Service f3de8e
            return True
Packit Service f3de8e
        if self.binfile == other:
Packit Service f3de8e
            return True
Packit Service f3de8e
        return False
Packit Service f3de8e
Packit Service f3de8e
    def __ne__(self, other):
Packit Service f3de8e
        return not self.__eq__(other)
Packit Service f3de8e
Packit Service f3de8e
    def __lt__(self, other):
Packit Service f3de8e
        return self.__ne__(other)
Packit Service f3de8e
Packit Service f3de8e
    def __le__(self, other):
Packit Service f3de8e
        return False
Packit Service f3de8e
Packit Service f3de8e
    def __gt__(self, other):
Packit Service f3de8e
        return False
Packit Service f3de8e
Packit Service f3de8e
    def __ge__(self, other):
Packit Service f3de8e
        return False
Packit 0f19cf
Packit 0f19cf
Packit 0f19cf
class DbTex:
Packit 0f19cf
    USE_MKLISTINGS = 1
Packit 0f19cf
Packit 0f19cf
    xsl_header = \
Packit Service f3de8e
u"""
Packit 0f19cf
Packit 0f19cf
                xmlns:m="http://www.w3.org/1998/Math/MathML"
Packit 0f19cf
                version="1.0">
Packit 0f19cf
                \n"""
Packit 0f19cf
Packit 0f19cf
    def __init__(self, base=""):
Packit 0f19cf
        self.name = None
Packit 0f19cf
        self.debug = 0
Packit 0f19cf
        self.verbose = 0
Packit 0f19cf
        if base:
Packit 0f19cf
            self.set_base(base)
Packit 0f19cf
        self.xslopts = []
Packit 0f19cf
        self.xslparams = []
Packit 0f19cf
        self.xslusers = []
Packit 0f19cf
        self.flags = self.USE_MKLISTINGS
Packit 0f19cf
        self.stdindir = ""
Packit 0f19cf
        self.inputdir = ""
Packit 0f19cf
        self.input = ""
Packit 0f19cf
        self.input_format = "xml"
Packit 0f19cf
        self.outputdir = ""
Packit 0f19cf
        self.output = ""
Packit 0f19cf
        self.format = "pdf"
Packit 0f19cf
        self.tmpdir = ""
Packit 0f19cf
        self.tmpdir_user = None
Packit 0f19cf
        self.fig_paths = []
Packit 0f19cf
        self.bib_paths = []
Packit 0f19cf
        self.bst_paths = []
Packit 0f19cf
        self.texinputs = []
Packit 0f19cf
        self.texbatch = 1
Packit 0f19cf
        self.texpost = ""
Packit 0f19cf
        self.fig_format = ""
Packit 0f19cf
        self.backend = ""
Packit 0f19cf
Packit 0f19cf
        # Temporary files
Packit 0f19cf
        self.documents = []
Packit 0f19cf
        self.interms = []
Packit 0f19cf
        self.included = []
Packit 0f19cf
        self.basefile = ""
Packit 0f19cf
        self.rawfile = ""
Packit 0f19cf
Packit 0f19cf
        # Engines to use
Packit 0f19cf
        self.runtex = None
Packit 0f19cf
        self.rawtex = None
Packit 0f19cf
        self.xsltproc = None
Packit 0f19cf
        self.sgmlxml = None
Packit 0f19cf
Packit 0f19cf
    def set_base(self, topdir):
Packit 0f19cf
        self.topdir = os.path.realpath(topdir)
Packit 0f19cf
        self.xslmain = os.path.join(self.topdir, "xsl", "docbook.xsl")
Packit 0f19cf
        self.xsllist = os.path.join(self.topdir, "xsl", "common", "mklistings.xsl")
Packit 0f19cf
        self.xslset = os.path.join(self.topdir, "xsl", "common", "mkdoclist.xsl")
Packit 0f19cf
        self.texdir = os.path.join(self.topdir, "texstyle")
Packit 0f19cf
        self.texlocal = ""
Packit 0f19cf
        self.confdir = os.path.join(self.topdir, "confstyle")
Packit 0f19cf
Packit 0f19cf
    def update_texinputs(self):
Packit 0f19cf
        sep = os.pathsep
Packit 0f19cf
        # Get a uniform list of paths (not a list of lists)
Packit 0f19cf
        ti = []
Packit 0f19cf
        for t in self.texinputs:
Packit 0f19cf
            ti += t.split(sep)
Packit 0f19cf
Packit 0f19cf
        # Systematically put the package style in TEXINPUTS
Packit 0f19cf
        ti_opts = ti + [self.texdir + "//"]
Packit 0f19cf
Packit 0f19cf
        # The original environment variable 
Packit 0f19cf
        texinputs = os.getenv("TEXINPUTS") or ""
Packit 0f19cf
        ti_env = texinputs.split(sep)
Packit 0f19cf
Packit 0f19cf
        # Find where system default is in the paths
Packit 0f19cf
        try:
Packit 0f19cf
            syspos = ti_env.index('')
Packit 0f19cf
        except:
Packit 0f19cf
            # By default system has precedence (i.e. is the first one)
Packit 0f19cf
            ti_env = [''] + ti_env
Packit 0f19cf
            syspos = 0
Packit 0f19cf
Packit 0f19cf
        ti_before = ti_env[:syspos]
Packit 0f19cf
        ti_after = ti_env[syspos+1:]
Packit 0f19cf
Packit 0f19cf
        # Paths passed by options have no precedence over the system 
Packit 0f19cf
        ti_after = ti_opts + ti_after
Packit 0f19cf
Packit 0f19cf
        # Texlocal has precedence over the standard (and added) paths
Packit 0f19cf
        if self.texlocal:
Packit 0f19cf
            ti_before = [ self.texlocal + "//" ] + ti_before
Packit 0f19cf
        
Packit 0f19cf
        # Export the whole paths
Packit 0f19cf
        texinputs = sep.join(ti_before + [''] + ti_after)
Packit 0f19cf
        os.environ["TEXINPUTS"] = texinputs
Packit 0f19cf
Packit 0f19cf
    def set_xslt(self, xsltmod=None):
Packit 0f19cf
        # Set the XSLT to use. Set a default XSLT if none specified.
Packit 0f19cf
        # One can replace an already defined XSLT if explicitely required.
Packit 0f19cf
        if not(xsltmod):
Packit 0f19cf
            if self.xsltproc:
Packit 0f19cf
                return
Packit 0f19cf
            xsltmod = "xsltproc"
Packit 0f19cf
        self.xsltproc = xslt.load(xsltmod)
Packit 0f19cf
Packit 0f19cf
    def set_backend(self):
Packit 0f19cf
        # Set the backend to use or retrieve the default one
Packit 0f19cf
        if self.backend:
Packit 0f19cf
            self.runtex.set_backend(self.backend)
Packit 0f19cf
        else:
Packit 0f19cf
            self.backend = self.runtex.get_backend()
Packit 0f19cf
Packit 0f19cf
    def set_format(self, format):
Packit 0f19cf
        if not(format in ("rtex", "tex", "dvi", "ps", "pdf")):
Packit 0f19cf
            raise ValueError("unknown format '%s'" % format)
Packit 0f19cf
        else:
Packit 0f19cf
            self.format = format
Packit 0f19cf
Packit 0f19cf
    def unset_flags(self, what):
Packit 0f19cf
        self.flags &= ~what
Packit 0f19cf
Packit 0f19cf
    def get_version(self):
Packit Service f3de8e
        f = open(os.path.join(self.topdir, "xsl", "version.xsl"), "rt", encoding="latin-1")
Packit 0f19cf
        versions = re.findall("<xsl:variable[^>]*>([^<]*)<", f.read())
Packit 0f19cf
        f.close()
Packit 0f19cf
        if versions:
Packit 0f19cf
            return versions[0].strip()
Packit 0f19cf
        else:
Packit 0f19cf
            return "unknown"
Packit 0f19cf
Packit 0f19cf
    def build_stylesheet(self, wrapper="custom.xsl"):
Packit 0f19cf
        if not(self.xslparams or self.xslusers):
Packit 0f19cf
            self.xslbuild = self.xslmain
Packit 0f19cf
            return
Packit 0f19cf
Packit Service f3de8e
        f = open(wrapper, "wt", encoding="latin-1")
Packit 0f19cf
        f.write(self.xsl_header)
Packit Service f3de8e
        f.write(u'<xsl:import href="%s"/>\n' % path_to_uri(self.xslmain))
Packit 0f19cf
        for xsluser in self.xslusers:
Packit Service f3de8e
            f.write(u'<xsl:import href="%s"/>\n' % path_to_uri(xsluser))
Packit 0f19cf
Packit 0f19cf
        # Reverse to set the latest parameter first (case of overriding)
Packit 0f19cf
        self.xslparams.reverse()
Packit 0f19cf
        for param in self.xslparams:
Packit 0f19cf
            v = param.split("=", 1)
Packit 0f19cf
            f.write('<xsl:param name="%s">' % v[0])
Packit 0f19cf
            if len(v) == 2:
Packit 0f19cf
                f.write('%s' % v[1])
Packit 0f19cf
            f.write('</xsl:param>\n')
Packit 0f19cf
Packit 0f19cf
        f.write('</xsl:stylesheet>\n')
Packit 0f19cf
        f.close()
Packit 0f19cf
        self.xslbuild = os.path.realpath(wrapper)
Packit 0f19cf
Packit 0f19cf
    def make_xml(self):
Packit 0f19cf
        self.log.info("Build the XML file...")
Packit 0f19cf
        xmlfile = self.basefile + ".xml"
Packit 0f19cf
        self.sgmlxml.run(self.input, xmlfile)
Packit 0f19cf
        self.input = xmlfile
Packit 0f19cf
Packit 0f19cf
    def make_listings(self):
Packit 0f19cf
        self.listings = os.path.join(self.tmpdir, "listings.xml")
Packit 0f19cf
        if (self.flags & self.USE_MKLISTINGS):
Packit 0f19cf
            self.log.info("Build the listings...")
Packit 0f19cf
            param = {"current.dir": self.inputdir}
Packit 0f19cf
            self.xsltproc.use_catalogs = 0
Packit 0f19cf
            self.xsltproc.run(self.xsllist, self.input,
Packit 0f19cf
                              self.listings, opts=self.xslopts, params=param)
Packit 0f19cf
        else:
Packit 0f19cf
            self.log.info("No external file support")
Packit Service f3de8e
            f = open(self.listings, "wt", encoding="latin-1")
Packit Service f3de8e
            f.write(u"<listings/>\n")
Packit 0f19cf
            f.close()
Packit 0f19cf
Packit 0f19cf
    def _single_setup(self):
Packit 0f19cf
        # If not specified the output name can be deduced from the input one:
Packit 0f19cf
        # /path/to/input.{xml|sgml} -> /path/to/input.{tex|pdf|dvi|ps}
Packit 0f19cf
        if not(self.output):
Packit 0f19cf
            output = suffix_replace(self.input, "."+self.input_format,
Packit 0f19cf
                                    ".%s" % self.format)
Packit 0f19cf
            self.output = output
Packit 0f19cf
Packit 0f19cf
        self.documents.append(Document(self.basefile + \
Packit 0f19cf
                                       "." + self.input_format,
Packit 0f19cf
                                       binfmt=self.format))
Packit 0f19cf
Packit 0f19cf
    def _multiple_setup(self, doclist):
Packit 0f19cf
        # If not specified, output the chunked books in the working dir
Packit 0f19cf
        if not(self.outputdir):
Packit 0f19cf
            self.log.info("No specified output dir (-O). "\
Packit 0f19cf
                          "Use the working directory")
Packit 0f19cf
            self.outputdir = self.cwdir
Packit 0f19cf
Packit Service f3de8e
        f = open(doclist, "rt", encoding="latin-1")
Packit 0f19cf
        books = f.readlines()
Packit 0f19cf
        f.close()
Packit 0f19cf
Packit 0f19cf
        for b in books:
Packit 0f19cf
            d = Document(b.strip() + ".tex", binfmt=self.format)
Packit 0f19cf
            self.documents.append(d)
Packit 0f19cf
Packit 0f19cf
    def build_doclist(self):
Packit 0f19cf
        # The stylesheet must include the building stylesheets to have the
Packit 0f19cf
        # actual parameter values (e.g. set.book.num) needed to give the book
Packit 0f19cf
        # set list
Packit 0f19cf
        self.log.info("Build the book set list...")
Packit 0f19cf
        xslset = "doclist.xsl"
Packit Service f3de8e
        f = open(xslset, "wt", encoding="latin-1")
Packit 0f19cf
        f.write(self.xsl_header)
Packit Service f3de8e
        f.write(u'<xsl:import href="%s"/>\n' % path_to_uri(self.xslbuild))
Packit Service f3de8e
        f.write(u'<xsl:import href="%s"/>\n' % path_to_uri(self.xslset))
Packit Service f3de8e
        f.write(u'</xsl:stylesheet>\n')
Packit 0f19cf
        f.close()
Packit 0f19cf
Packit 0f19cf
        doclist = os.path.join(self.tmpdir, "doclist.txt")
Packit 0f19cf
        self.xsltproc.use_catalogs = 0
Packit 0f19cf
        self.xsltproc.run(xslset, self.input, doclist, opts=self.xslopts)
Packit 0f19cf
Packit 0f19cf
        # If <doclist> is missing or is empty, there's no set, or only one
Packit 0f19cf
        # book from the set is compiled
Packit 0f19cf
        if os.path.isfile(doclist) and os.path.getsize(doclist) > 0:
Packit 0f19cf
            self._multiple_setup(doclist)
Packit 0f19cf
        else:
Packit 0f19cf
            self._single_setup()
Packit 0f19cf
Packit 0f19cf
    def make_rawtex(self):
Packit 0f19cf
        if len(self.documents) == 1:
Packit 0f19cf
            self.rawfile = self.documents[0].rawfile
Packit 0f19cf
        else:
Packit 0f19cf
            self.rawfile = "output.rtex"
Packit 0f19cf
Packit 0f19cf
        param = {"listings.xml": self.listings,
Packit 0f19cf
                 "current.dir": self.inputdir}
Packit 0f19cf
        self.xsltproc.use_catalogs = 1
Packit 0f19cf
        self.xsltproc.run(self.xslbuild, self.input,
Packit 0f19cf
                          self.rawfile, opts=self.xslopts, params=param)
Packit 0f19cf
Packit 0f19cf
        # Now, find the intermediate raw files
Packit 0f19cf
        rawfiles = glob.glob("*.rtex")
Packit 0f19cf
        for rawfile in rawfiles:
Packit 0f19cf
            if not(rawfile in self.documents):
Packit 0f19cf
                d = Document(rawfile, binfmt=self.format)
Packit 0f19cf
                if d.has_subext(".input"):
Packit 0f19cf
                    self.included.append(d)
Packit 0f19cf
                else:
Packit 0f19cf
                    self.interms.append(d)
Packit 0f19cf
Packit 0f19cf
    def make_tex(self):
Packit 0f19cf
        self.rawtex.set_format(self.format, self.backend)
Packit 0f19cf
        if self.fig_format:
Packit 0f19cf
            self.rawtex.fig_format(self.fig_format)
Packit 0f19cf
Packit 0f19cf
        # By default figures are relative to the source file directory
Packit 0f19cf
        self.rawtex.set_fig_paths([self.inputdir] + self.fig_paths)
Packit 0f19cf
Packit 0f19cf
        for d in self.documents + self.interms + self.included:
Packit 0f19cf
            self.rawtex.parse(d.rawfile, d.texfile)
Packit 0f19cf
Packit 0f19cf
    def make_bin(self):
Packit 0f19cf
        self.runtex.texpost = self.texpost
Packit 0f19cf
        self.runtex.set_fig_paths([self.inputdir] + self.fig_paths)
Packit 0f19cf
        self.runtex.set_bib_paths([self.inputdir] + self.bib_paths,
Packit 0f19cf
                                  [self.inputdir] + self.bst_paths)
Packit 0f19cf
Packit 0f19cf
        # Build the intermediate files and (after) the main documents
Packit 0f19cf
        for d in self.interms + self.documents:
Packit 0f19cf
            self.log.info("Build %s" % d.binfile)
Packit 0f19cf
            self.runtex.compile(d.texfile, d.binfile, self.format,
Packit 0f19cf
                                batch=self.texbatch)
Packit 0f19cf
            # Only reinit, to not lose the produced working files
Packit 0f19cf
            # used to track the dependencies on other documents
Packit 0f19cf
            self.runtex.reinit()
Packit 0f19cf
Packit 0f19cf
    def compile(self):
Packit 0f19cf
        self.set_xslt()
Packit 0f19cf
        self.set_backend()
Packit 0f19cf
        self.cwdir = os.getcwd()
Packit 0f19cf
        self.tmpdir = self.tmpdir_user or tempfile.mkdtemp()
Packit 0f19cf
        if self.input:
Packit 0f19cf
            self.inputdir = os.path.dirname(self.input)
Packit 0f19cf
        else:
Packit 0f19cf
            self._stdin_write()
Packit 0f19cf
        os.chdir(self.tmpdir)
Packit 0f19cf
        try:
Packit 0f19cf
            donefiles = self._compile()
Packit 0f19cf
            if len(donefiles) == 1:
Packit 0f19cf
                shutil.move(donefiles[0], self.output)
Packit 0f19cf
                self.log.info("'%s' successfully built" % \
Packit 0f19cf
                              os.path.basename(self.output))
Packit 0f19cf
            else:
Packit 0f19cf
                for d in donefiles:
Packit 0f19cf
                    shutil.move(d, self.outputdir)
Packit 0f19cf
                donefiles.sort()
Packit 0f19cf
                self.log.info("Files successfully built in '%s':\n%s" % \
Packit 0f19cf
                              (self.outputdir, "\n".join(donefiles)))
Packit 0f19cf
        finally:
Packit 0f19cf
            os.chdir(self.cwdir)
Packit 0f19cf
            if not(self.debug):
Packit 0f19cf
                shutil.rmtree(self.tmpdir)
Packit 0f19cf
            else:
Packit 0f19cf
                self.log.info("%s not removed" % self.tmpdir)
Packit 0f19cf
Packit 0f19cf
    def _stdin_write(self):
Packit 0f19cf
        # Find out the stdin working directory
Packit 0f19cf
        self.inputdir = self.stdindir or self.cwdir
Packit 0f19cf
Packit 0f19cf
        # Need to dump the stdin input, because of the two passes
Packit 0f19cf
        self.input = os.path.join(self.tmpdir, "stdin.xml")
Packit Service f3de8e
        f = open(self.input, "wt", encoding="latin-1")
Packit 0f19cf
        for line in sys.stdin:
Packit 0f19cf
            f.write(line)
Packit 0f19cf
        f.close()
Packit 0f19cf
Packit 0f19cf
    def _compile(self):
Packit 0f19cf
        # The temporary output file
Packit 0f19cf
        tmpout = os.path.basename(self.input)
Packit 0f19cf
        for s in (" ", "\t"):
Packit 0f19cf
            tmpout = tmpout.replace(s, "_")
Packit 0f19cf
        self.basefile = suffix_replace(tmpout, "." + self.input_format)
Packit 0f19cf
Packit 0f19cf
        # Convert SGML to XML if needed
Packit 0f19cf
        if self.input_format == "sgml":
Packit 0f19cf
            self.make_xml()
Packit 0f19cf
Packit 0f19cf
        # Build the user XSL stylesheet if needed
Packit 0f19cf
        self.build_stylesheet()
Packit 0f19cf
Packit 0f19cf
        # List the documents to build
Packit 0f19cf
        self.build_doclist()
Packit 0f19cf
Packit 0f19cf
        # Refresh the TEXINPUTS
Packit 0f19cf
        self.update_texinputs()
Packit 0f19cf
Packit 0f19cf
        # For easy debug
Packit Service f3de8e
        if self.debug and "TEXINPUTS" in os.environ:
Packit 0f19cf
            if os.name != "nt":
Packit Service f3de8e
                f = open("env_tex", "wt")
Packit Service f3de8e
                f.write(u"TEXINPUTS=%s\nexport TEXINPUTS\n" % \
Packit 0f19cf
                        os.environ["TEXINPUTS"])
Packit 0f19cf
                f.close()
Packit 0f19cf
            else:
Packit Service f3de8e
                f = open("env_tex.bat", "wt")
Packit Service f3de8e
                f.write(u"set TEXINPUTS=%s\n" % os.environ["TEXINPUTS"])
Packit 0f19cf
                f.close()
Packit 0f19cf
Packit 0f19cf
        # Build the tex file(s), and compile it(them)
Packit 0f19cf
        self.make_listings()
Packit 0f19cf
        self.make_rawtex()
Packit 0f19cf
        if self.format == "rtex":
Packit 0f19cf
            return [ d.rawfile for d in self.documents ]
Packit 0f19cf
Packit 0f19cf
        self.make_tex()
Packit 0f19cf
        if self.format == "tex":
Packit 0f19cf
            return [ d.texfile for d in self.documents ]
Packit 0f19cf
Packit 0f19cf
        self.make_bin()
Packit 0f19cf
        return [ d.binfile for d in self.documents ]
Packit 0f19cf
Packit 0f19cf
Packit 0f19cf
#
Packit 0f19cf
# Command entry point
Packit 0f19cf
#
Packit 0f19cf
class DbTexCommand:
Packit 0f19cf
    def __init__(self, base):
Packit 0f19cf
        prog = os.path.splitext(os.path.basename(sys.argv[0]))[0]
Packit 0f19cf
        usage = "%s [options] file" % prog
Packit 0f19cf
        parser = OptionParser(usage=usage)
Packit 0f19cf
        parser.add_option("-b", "--backend",
Packit 0f19cf
                          help="Backend driver to use. The available drivers"
Packit 0f19cf
                               " are 'pdftex' (default), 'dvips' and 'xetex'.")
Packit 0f19cf
        parser.add_option("-B", "--no-batch", action="store_true",
Packit 0f19cf
                          help="All the tex output is printed")
Packit 0f19cf
        parser.add_option("-c", "-S", "--config", action="append",
Packit 0f19cf
                          help="Configuration file")
Packit 0f19cf
        parser.add_option("-C", "--changedir",
Packit 0f19cf
                          help="Standard input working directory")
Packit 0f19cf
        parser.add_option("-d", "--debug", action="store_true",
Packit 0f19cf
                          help="Debug mode. Keep the temporary directory in "
Packit 0f19cf
                               "which %s actually works" % prog)
Packit 0f19cf
        parser.add_option("-D", "--dump", action="store_true",
Packit 0f19cf
                          help="Dump error stack (debug purpose)")
Packit 0f19cf
        parser.add_option("-e", "--indexstyle",
Packit 0f19cf
                          help="Index Style file to pass to makeindex")
Packit 0f19cf
        parser.add_option("-f", "--fig-format",
Packit 0f19cf
                          help="Input figure format, used when not deduced "
Packit 0f19cf
                               "from figure extension")
Packit 0f19cf
        parser.add_option("-F", "--input-format",
Packit 0f19cf
                          help="Input file format: sgml, xml. (default=xml)")
Packit 0f19cf
        parser.add_option("-i", "--texinputs", action="append",
Packit 0f19cf
                          help="Path added to TEXINPUTS")
Packit 0f19cf
        parser.add_option("-I", "--fig-path", action="append",
Packit 0f19cf
                          dest="fig_paths", metavar="FIG_PATH",
Packit 0f19cf
                          help="Additional lookup path of the figures")
Packit 0f19cf
        parser.add_option("-l", "--bst-path", action="append",
Packit 0f19cf
                          dest="bst_paths", metavar="BST_PATH",
Packit 0f19cf
                          help="Bibliography style file path")
Packit 0f19cf
        parser.add_option("-L", "--bib-path", action="append",
Packit 0f19cf
                          dest="bib_paths", metavar="BIB_PATH",
Packit 0f19cf
                          help="BibTeX database path")
Packit 0f19cf
        parser.add_option("-m", "--xslt",
Packit 0f19cf
                          help="XSLT engine to use. (default=xsltproc)")
Packit 0f19cf
        parser.add_option("-o", "--output", dest="output",
Packit 0f19cf
                          help="Output filename. "
Packit 0f19cf
                               "When not used, the input filename "
Packit 0f19cf
                               "is used, with the suffix of the output format")
Packit 0f19cf
        parser.add_option("-O", "--output-dir",
Packit 0f19cf
                          help="Output directory for the built books."
Packit 0f19cf
                               " When not defined, the current working "
Packit 0f19cf
                               "directory is used. Option used only for "
Packit 0f19cf
                               "a document having a <set>")
Packit 0f19cf
        parser.add_option("-p", "--xsl-user", action="append",
Packit 0f19cf
                          help="XSL user configuration file to use")
Packit 0f19cf
        parser.add_option("-P", "--param", dest="xslparams",
Packit 0f19cf
                          action="append", metavar="PARAM=VALUE",
Packit 0f19cf
                          help="Set an XSL parameter value from command line")
Packit 0f19cf
        parser.add_option("-q", "--quiet", action="store_true",
Packit 0f19cf
                          help="Less verbose, showing only error messages")
Packit 0f19cf
        parser.add_option("-r", "--texpost", metavar="SCRIPT",
Packit 0f19cf
                          help="Script called at the very end of the tex "
Packit 0f19cf
                               "compilation. Its role is to modify the tex file "
Packit 0f19cf
                               "or one of the compilation file before the last "
Packit 0f19cf
                               "round.")
Packit 0f19cf
        parser.add_option("-s", "--texstyle", metavar="STYFILE",
Packit 0f19cf
                          help="Latex style to apply. It can be a package name, or "
Packit 0f19cf
                               "directly a package path that must ends with "
Packit 0f19cf
                               "'.sty'")
Packit 0f19cf
        parser.add_option("-t", "--type", dest="format",
Packit 0f19cf
                          help="Output format. Available formats:\n"
Packit 0f19cf
                               "tex, dvi, ps, pdf (default=pdf)")
Packit 0f19cf
        parser.add_option("--dvi", action="store_true", dest="format_dvi",
Packit 0f19cf
                          help="DVI output. Equivalent to -tdvi")
Packit 0f19cf
        parser.add_option("--pdf", action="store_true", dest="format_pdf",
Packit 0f19cf
                          help="PDF output. Equivalent to -tpdf")
Packit 0f19cf
        parser.add_option("--ps", action="store_true", dest="format_ps",
Packit 0f19cf
                          help="PostScript output. Equivalent to -tps")
Packit 0f19cf
        parser.add_option("-T", "--style",
Packit 0f19cf
                          help="Predefined output style")
Packit 0f19cf
        parser.add_option("--tmpdir",
Packit 0f19cf
                          help="Temporary working directory to use (for debug only)")
Packit 0f19cf
        parser.add_option("-v", "--version", action="store_true",
Packit 0f19cf
                          help="Print the %s version" % prog)
Packit 0f19cf
        parser.add_option("-V", "--verbose", action="store_true",
Packit 0f19cf
                          help="Verbose mode, showing the running commands")
Packit 0f19cf
        parser.add_option("-x", "--xslt-opts", dest="xslopts",
Packit 0f19cf
                          action="append", metavar="XSLT_OPTIONS",
Packit 0f19cf
                          help="Arguments directly passed to the XSLT engine")
Packit 0f19cf
        parser.add_option("-X", "--no-external", action="store_true",
Packit 0f19cf
                          help="Disable the external text file support used for "
Packit 0f19cf
                               "some callout processing")
Packit 0f19cf
Packit 0f19cf
        self.parser = parser
Packit 0f19cf
        self.base = base
Packit 0f19cf
        self.prog = prog
Packit 0f19cf
        # The actual engine to use is unknown
Packit 0f19cf
        self.run = None
Packit 0f19cf
Packit 0f19cf
    def load_plugin(self, pathname):
Packit 0f19cf
        moddir, modname = os.path.split(pathname)
Packit 0f19cf
        try:
Packit 0f19cf
            filemod, path, descr = imp.find_module(modname, [moddir])
Packit 0f19cf
        except ImportError:
Packit 0f19cf
            try:
Packit 0f19cf
                filemod, path, descr = imp.find_module(modname)
Packit 0f19cf
            except ImportError:
Packit 0f19cf
                failed_exit("Error: '%s' module not found" % modname)
Packit 0f19cf
        mod = imp.load_module(modname, filemod, path, descr)
Packit 0f19cf
        filemod.close()
Packit 0f19cf
        return mod
Packit 0f19cf
Packit 0f19cf
    def run_setup(self, options):
Packit 0f19cf
        run = self.run
Packit 0f19cf
Packit 0f19cf
        if not(options.format):
Packit 0f19cf
            if options.format_pdf:
Packit 0f19cf
                options.format = "pdf"
Packit 0f19cf
            elif options.format_ps:
Packit 0f19cf
                options.format = "ps"
Packit 0f19cf
            elif options.format_dvi:
Packit 0f19cf
                options.format = "dvi"
Packit 0f19cf
Packit 0f19cf
        if options.format:
Packit 0f19cf
            try:
Packit 0f19cf
                run.set_format(options.format)
Packit Service f3de8e
            except Exception as e:
Packit 0f19cf
                failed_exit("Error: %s" % e)
Packit 0f19cf
Packit 0f19cf
        # Always set the XSLT (default or not)
Packit 0f19cf
        try:
Packit 0f19cf
            run.set_xslt(options.xslt)
Packit Service f3de8e
        except Exception as e:
Packit 0f19cf
            failed_exit("Error: %s" % e)
Packit 0f19cf
Packit 0f19cf
        if options.xslopts:
Packit 0f19cf
            for o in options.xslopts:
Packit 0f19cf
                run.xslopts += shlex.split(o)
Packit 0f19cf
Packit 0f19cf
        if options.xslparams:
Packit 0f19cf
            run.xslparams += options.xslparams
Packit 0f19cf
Packit 0f19cf
        if options.debug:
Packit 0f19cf
            run.debug = options.debug
Packit 0f19cf
Packit 0f19cf
        if options.fig_paths:
Packit 0f19cf
            run.fig_paths += [os.path.realpath(p) for p in options.fig_paths]
Packit 0f19cf
Packit 0f19cf
        if options.bib_paths:
Packit 0f19cf
            run.bib_paths += [os.path.realpath(p) for p in options.bib_paths]
Packit 0f19cf
Packit 0f19cf
        if options.bst_paths:
Packit 0f19cf
            run.bst_paths += [os.path.realpath(p) for p in options.bst_paths]
Packit 0f19cf
Packit 0f19cf
        if options.texstyle:
Packit 0f19cf
            try:
Packit 0f19cf
                xslparam, texpath = texstyle_parse(options.texstyle)
Packit Service f3de8e
            except Exception as e:
Packit 0f19cf
                failed_exit("Error: %s" % e)
Packit 0f19cf
            run.xslparams.append(xslparam)
Packit 0f19cf
            if texpath: run.texinputs.append(texpath)
Packit 0f19cf
Packit 0f19cf
        if options.indexstyle:
Packit 0f19cf
            run.runtex.index_style = os.path.abspath(options.indexstyle)
Packit 0f19cf
Packit 0f19cf
        if options.texinputs:
Packit 0f19cf
            for texinputs in options.texinputs:
Packit 0f19cf
                run.texinputs += texinputs_parse(texinputs)
Packit 0f19cf
Packit 0f19cf
        if options.fig_format:
Packit 0f19cf
            run.fig_format = options.fig_format
Packit 0f19cf
Packit 0f19cf
        if options.input_format:
Packit 0f19cf
            run.input_format = options.input_format
Packit 0f19cf
Packit 0f19cf
        if options.no_batch:
Packit 0f19cf
            run.texbatch = 0
Packit 0f19cf
Packit 0f19cf
        if options.backend:
Packit 0f19cf
            run.backend = options.backend
Packit 0f19cf
Packit 0f19cf
        if options.xsl_user:
Packit 0f19cf
            for xfile in options.xsl_user:
Packit 0f19cf
                xsluser = os.path.realpath(xfile)
Packit 0f19cf
                if not(os.path.isfile(xsluser)):
Packit 0f19cf
                    failed_exit("Error: '%s' does not exist" % options.xsl_user)
Packit 0f19cf
                run.xslusers.append(xsluser)
Packit 0f19cf
Packit 0f19cf
        if options.texpost:
Packit 0f19cf
            is_plugin = options.texpost.startswith("plugin:")
Packit 0f19cf
            if is_plugin:
Packit 0f19cf
                path = self.load_plugin(options.texpost[len("plugin:"):])
Packit 0f19cf
            else:
Packit 0f19cf
                path = os.path.realpath(options.texpost)
Packit 0f19cf
                if not(os.path.isfile(path)):
Packit 0f19cf
                    failed_exit("Error: '%s' does not exist" % options.texpost)
Packit 0f19cf
            run.texpost = path
Packit 0f19cf
Packit 0f19cf
        if options.no_external:
Packit 0f19cf
            run.unset_flags(run.USE_MKLISTINGS)
Packit 0f19cf
Packit 0f19cf
        if options.verbose:
Packit 0f19cf
            run.verbose = options.verbose
Packit 0f19cf
Packit 0f19cf
        if options.quiet:
Packit 0f19cf
            run.verbose = logger.QUIET
Packit 0f19cf
            run.xslparams.append("output.quietly=1")
Packit 0f19cf
Packit 0f19cf
        if options.tmpdir:
Packit 0f19cf
            if not(os.path.exists(options.tmpdir)):
Packit 0f19cf
                try:
Packit 0f19cf
                    os.mkdir(options.tmpdir)
Packit Service f3de8e
                except Exception as e:
Packit 0f19cf
                    failed_exit("Error: %s" % e)
Packit 0f19cf
            run.tmpdir_user = os.path.abspath(options.tmpdir)
Packit 0f19cf
Packit 0f19cf
        if options.dump:
Packit 0f19cf
            dump_stack()
Packit 0f19cf
Packit 0f19cf
    def get_config_paths(self):
Packit 0f19cf
        # Allows user directories where to look for configuration files
Packit 0f19cf
        paths = [os.getcwd()]
Packit 0f19cf
        paths.append(os.path.expanduser(os.path.join("~", "."+self.prog)))
Packit 0f19cf
Packit 0f19cf
        # Unix specific system-wide config files
Packit 0f19cf
        if "posix" in sys.builtin_module_names:
Packit 0f19cf
            paths.append(os.path.join("/etc", self.prog))
Packit 0f19cf
Packit 0f19cf
        # Last but not least, the tool config dir
Packit 0f19cf
        paths.append(self.run.confdir)
Packit 0f19cf
Packit 0f19cf
        # Optionally the paths from an environment variable
Packit 0f19cf
        conf_paths = os.getenv("DBLATEX_CONFIG_FILES")
Packit 0f19cf
        if not(conf_paths):
Packit 0f19cf
            return paths
Packit 0f19cf
Packit 0f19cf
        paths += conf_paths.split(os.pathsep)
Packit 0f19cf
        return paths
Packit 0f19cf
Packit 0f19cf
    def main(self):
Packit 0f19cf
        (options, args) = self.parser.parse_args()
Packit 0f19cf
Packit 0f19cf
        run = self.run
Packit 0f19cf
        parser = self.parser
Packit 0f19cf
Packit 0f19cf
        if options.version:
Packit 0f19cf
            version = run.get_version()
Packit Service f3de8e
            print("%s version %s" % (self.prog, version))
Packit 0f19cf
            if not(args):
Packit 0f19cf
                sys.exit(0)
Packit 0f19cf
Packit 0f19cf
        # At least the input file is expected
Packit 0f19cf
        if not(args):
Packit 0f19cf
            parser.parse_args(args=["-h"])
Packit 0f19cf
Packit 0f19cf
        # Load the specified configurations
Packit 0f19cf
        conf = DbtexConfig()
Packit 0f19cf
        if options.dump:
Packit 0f19cf
            dump_stack()
Packit 0f19cf
Packit 0f19cf
        if options.style:
Packit 0f19cf
            try:
Packit 0f19cf
                conf.paths = self.get_config_paths()
Packit 0f19cf
                conf.fromstyle(options.style)
Packit Service f3de8e
            except Exception as e:
Packit 0f19cf
                failed_exit("Error: %s" % e)
Packit 0f19cf
            
Packit 0f19cf
        if options.config:
Packit 0f19cf
            try:
Packit 0f19cf
                for config in options.config:
Packit 0f19cf
                    conf.fromfile(config)
Packit Service f3de8e
            except Exception as e:
Packit 0f19cf
                failed_exit("Error: %s" % e)
Packit 0f19cf
Packit 0f19cf
        if conf.options:
Packit 0f19cf
            options2, args2 = parser.parse_args(conf.options)
Packit 0f19cf
            self.run_setup(options2)
Packit 0f19cf
         
Packit 0f19cf
        # Now apply the command line setup
Packit 0f19cf
        self.run_setup(options)
Packit 0f19cf
Packit 0f19cf
        # Verbose mode
Packit 0f19cf
        run.log = logger.logger(self.prog, run.verbose)
Packit 0f19cf
Packit 0f19cf
        # Data from standard input?
Packit 0f19cf
        if args[0] == "-":
Packit 0f19cf
            if not(options.output):
Packit 0f19cf
                failed_exit("Error: -o expected when input from stdin")
Packit 0f19cf
            input = ""
Packit 0f19cf
            if options.changedir:
Packit 0f19cf
                run.stdindir = os.path.realpath(options.changedir)
Packit 0f19cf
        else:
Packit 0f19cf
            input = os.path.realpath(args[0])
Packit 0f19cf
Packit 0f19cf
        # Output file in case of single document (main case)
Packit 0f19cf
        if not(options.output):
Packit 0f19cf
            output = None
Packit 0f19cf
        else:
Packit 0f19cf
            output = os.path.realpath(options.output)
Packit 0f19cf
Packit 0f19cf
        # Output directory in case of chunked books (from a set)
Packit 0f19cf
        if not(options.output_dir):
Packit 0f19cf
            outputdir = None
Packit 0f19cf
        else:
Packit 0f19cf
            # Check the output dir is OK
Packit 0f19cf
            outputdir = os.path.realpath(options.output_dir)
Packit 0f19cf
            if not(os.path.isdir(outputdir)):
Packit 0f19cf
                failed_exit("Error: '%s' is not a directory" %\
Packit 0f19cf
                            options.output_dir)
Packit 0f19cf
Packit 0f19cf
        run.input = input
Packit 0f19cf
        run.output = output
Packit 0f19cf
        run.outputdir = outputdir
Packit 0f19cf
Packit 0f19cf
        # Try to buid the file
Packit 0f19cf
        try:
Packit 0f19cf
            run.compile()
Packit Service f3de8e
        except Exception as e:
Packit 0f19cf
            signal_error(self, e)
Packit 0f19cf
            failed_exit("Error: %s" % e)
Packit 0f19cf