Beispiel #1
0
    def first_run_needed (self):
        """
        The condition is only on the database files' modification dates, but
        it would be more clever to check if the results have changed.
        BibTeXing is also needed when the last run of BibTeX failed, and in
        the very particular case when the style has changed since last
        compilation.
        """
        if not exists(self.auxfile):
            return 0
        if not exists(self.blgfile):
            return 1

        dtime = getmtime(self.blgfile)
        for db in self.db.values():
            if getmtime(db) > dtime:
                msg.log(_("bibliography database %s was modified") % db,
                        pkg="bibtex")
                return 1

        blg = open(self.blgfile)
        for line in blg.readlines():
            if re_error.search(line):
                blg.close()
                msg.log(_("last BibTeXing failed"), pkg="bibtex")
                return 1
        blg.close()

        if self.style_changed():
            return 1
        if self.bst_file and getmtime(self.bst_file) > dtime:
            msg.log(_("the bibliography style file was modified"), pkg="bibtex")
            return 1
        return 0
Beispiel #2
0
    def externaldocument (self, dict):
        # .aux document needed to cross-ref with xr
        auxfile = dict["arg"] + ".aux"
        texfile = dict["arg"] + ".tex"

        # Ignore the dependency if no tex source found
        if not(os.path.isfile(texfile)):
            msg.log(_("file %s is required by xr package but not found")\
                    % texfile, pkg="xr")
            return

        # Ask to compile the related .tex file to have the .aux 
        texdep = Latex(self.env)
        texdep.set_source(texfile)
        texdep.batch = self.doc.batch
        texdep.encoding = self.doc.encoding
        texdep.draft_only = True # Final output not required here
        for m in self.texmodules:
            texdep.modules.register(m)
        # Load other modules from source, except xr to avoid loops
        texdep.prepare(exclude_mods=["xr-hyper"])

        # Add the .aux as an expected input for compiling the doc
        self.doc.sources[auxfile] = texdep
        msg.log(_(
            "dependency %s added for external references") % auxfile, pkg="xr")
Beispiel #3
0
    def first_run_needed(self):
        """
        The condition is only on the database files' modification dates, but
        it would be more clever to check if the results have changed.
        BibTeXing is also needed when the last run of BibTeX failed, and in
        the very particular case when the style has changed since last
        compilation.
        """
        if not exists(self.auxfile):
            return 0
        if not exists(self.blgfile):
            return 1

        dtime = getmtime(self.blgfile)
        for db in self.db.values():
            if getmtime(db) > dtime:
                msg.log(_("bibliography database %s was modified") % db,
                        pkg="bibtex")
                return 1

        blg = open(self.blgfile)
        for line in blg.readlines():
            if re_error.search(line):
                blg.close()
                msg.log(_("last BibTeXing failed"), pkg="bibtex")
                return 1
        blg.close()

        if self.style_changed():
            return 1
        if self.bst_file and getmtime(self.bst_file) > dtime:
            msg.log(_("the bibliography style file was modified"),
                    pkg="bibtex")
            return 1
        return 0
Beispiel #4
0
 def run (self):
     # FIXME
     if len(self.prods) == 1:
         msg.error(_("%r does not exist") % self.prods[0], **self.loc)
     else:
         msg.error(_("one of %r does not exist") % self.prods, **self.loc)
     return 1
Beispiel #5
0
 def run (self):
     msg.progress(_("running %s") % self.cmd[0])
     rc = subprocess.call(self.cmd, stdout=msg.stdout)
     if rc != 0:
         msg.error(_("execution of %s failed") % self.cmd[0])
         return 1
     return 0
Beispiel #6
0
 def run(self):
     cmd = [self.cmdexec]
     msg.progress(_("running %s on %s") % (cmd[0], self.source))
     for opt in self.doc.paper.split():
         cmd.extend(["-t", opt])
     cmd.extend(self.options + ["-o", self.target, self.source])
     msg.debug(" ".join(cmd))
     rc = subprocess.call(cmd, stdout=msg.stdout)
     if rc != 0:
         msg.error(_("%s failed on %s") % (cmd[0], self.source))
         return 1
     return 0
Beispiel #7
0
 def run (self):
     cmd = [self.cmdexec]
     msg.progress(_("running %s on %s") % (cmd[0], self.source))
     for opt in self.doc.paper.split():
         cmd.extend(["-t", opt])
     cmd.extend(self.options + ["-o", self.target, self.source])
     msg.debug(" ".join(cmd))
     rc = subprocess.call(cmd, stdout=msg.stdout)
     if rc != 0:
         msg.error(_("%s failed on %s") % (cmd[0], self.source))
         return 1
     return 0
Beispiel #8
0
 def compile(self):
     self.must_compile = 0
     cmd = [self.program] + self.opts + [os.path.basename(self.srcfile)]
     msg.log(" ".join(cmd))
     rc = subprocess.call(cmd, stdout=msg.stdout)
     if rc != 0:
         msg.error(_("%s failed") % self.program)
     # Whatever the result is, read the log file
     if self.log.read(self.logfile):
         msg.error(_("Could not run %s.") % self.program)
         return 1
     if self.log.errors():
         return 1
     return rc
Beispiel #9
0
 def compile(self):
     self.must_compile = 0
     cmd = [self.program] + self.opts + [os.path.basename(self.srcfile)]
     msg.log(" ".join(cmd))
     rc = subprocess.call(cmd, stdout=msg.stdout)
     if rc != 0:
         msg.error(_("%s failed") % self.program)
     # Whatever the result is, read the log file
     if self.log.read(self.logfile):
         msg.error(_("Could not run %s.") % self.program)
         return 1
     if self.log.errors():
         return 1
     return rc
Beispiel #10
0
 def do_order (self, *args):
     for opt in args:
         if opt == "standard": self.opts = []
         elif opt == "german": self.opts.append("-g")
         elif opt == "letter": self.opts.append("-l")
         else: msg.warn(
             _("unknown option '%s' for 'makeidx.order'") % opt)
Beispiel #11
0
 def clean (self):
     """
     Remove all generated files related to the index.
     """
     for file in self.source, self.target, self.transcript:
         if exists(file):
             msg.log(_("removing %s") % file, pkg="index")
             os.unlink(file)
Beispiel #12
0
    def recompile_needed (self):
        """
        Returns true if another compilation is needed. This method is used
        when a compilation has already been done.
        """
        changed = self.watcher.update()
        if self.must_compile:
            return 1
        if self.log.errors():
            msg.debug(_("last compilation failed"))
            return 1
#        if self.deps_modified(os.path.getmtime(self.outfile)):
#            msg.debug(_("dependencies were modified"))
#            return 1
        if changed and (len(changed) > 1 or changed[0] != self.auxfile):
            msg.debug(_("the %s file has changed") % changed[0])
            return 1
        if self.log.run_needed():
            msg.debug(_("LaTeX asks to run again"))
            if (not(changed)):
                msg.debug(_("but the aux files are unchanged"))
                return 0
            return 1
        if changed:
            msg.debug(_("the %s file has changed but no re-run required?") \
                      % changed[0])
            if self.program == "xelatex":
                msg.debug(_("force recompilation (XeTeX engine)"))
                return 1

        msg.debug(_("no new compilation is needed"))
        return 0
Beispiel #13
0
    def recompile_needed(self):
        """
        Returns true if another compilation is needed. This method is used
        when a compilation has already been done.
        """
        changed = self.watcher.update()
        if self.must_compile:
            return 1
        if self.log.errors():
            msg.debug(_("last compilation failed"))
            return 1
#        if self.deps_modified(os.path.getmtime(self.outfile)):
#            msg.debug(_("dependencies were modified"))
#            return 1
        if changed and (len(changed) > 1 or changed[0] != self.auxfile):
            msg.debug(_("the %s file has changed") % changed[0])
            return 1
        if self.log.run_needed():
            msg.debug(_("LaTeX asks to run again"))
            if (not (changed)):
                msg.debug(_("but the aux files are unchanged"))
                return 0
            return 1
        if changed:
            msg.debug(_("the %s file has changed but no re-run required?") \
                      % changed[0])
            if self.program == "xelatex":
                msg.debug(_("force recompilation (XeTeX engine)"))
                return 1

        msg.debug(_("no new compilation is needed"))
        return 0
Beispiel #14
0
 def post_compile (self):
     """
     This method runs BibTeX if needed to solve undefined citations. If it
     was run, then force a new LaTeX compilation.
     """
     if not self.bibtex_needed():
         msg.log(_("no BibTeXing needed"), pkg="bibtex")
         return 0
     return self.run()
Beispiel #15
0
 def post_compile(self):
     """
     This method runs BibTeX if needed to solve undefined citations. If it
     was run, then force a new LaTeX compilation.
     """
     if not self.bibtex_needed():
         msg.log(_("no BibTeXing needed"), pkg="bibtex")
         return 0
     return self.run()
Beispiel #16
0
 def remove_suffixes(self, list):
     """
     Remove all files derived from the main source with one of the
     specified suffixes.
     """
     for suffix in list:
         file = self.src_base + suffix
         if os.path.exists(file):
             msg.log(_("removing %s") % file)
             os.unlink(file)
Beispiel #17
0
 def remove_suffixes (self, list):
     """
     Remove all files derived from the main source with one of the
     specified suffixes.
     """
     for suffix in list:
         file = self.src_base + suffix
         if os.path.exists(file):
             msg.log(_("removing %s") % file)
             os.unlink(file)
Beispiel #18
0
 def run(self):
     """
     This method actually runs BibTeX with the appropriate environment
     variables set.
     """
     msg.progress(_("running BibTeX on %s") % self.base)
     doc = {}
     if len(self.bib_path) != 1:
         os.environ["BIBINPUTS"] = string.join(
             self.bib_path + [os.getenv("BIBINPUTS", "")], ":")
     if len(self.bst_path) != 1:
         os.environ["BSTINPUTS"] = string.join(
             self.bst_path + [os.getenv("BSTINPUTS", "")], ":")
     rc = subprocess.call(["bibtex", self.base], stdout=msg.stdout)
     if rc != 0:
         msg.error(_("There were errors making the bibliography."))
         return 1
     self.run_needed = 0
     self.doc.must_compile = 1
     return 0
Beispiel #19
0
 def newindex (self, dict):
     """
     Register a new index.
     """
     m = re_newindex.match(dict["line"])
     if not m:
         return
     index = dict["arg"]
     d = m.groupdict()
     self.register(index, d["idx"], d["ind"], "ilg")
     msg.log(_("index %s registered") % index, pkg="index")
Beispiel #20
0
 def __init__(self, doc, dict):
     self.doc = doc
     lastdep = doc.env.dep_last()
     dvi = lastdep.prods[0]
     root, ext = os.path.splitext(dvi)
     if ext != ".dvi":
         msg.error(_("I can't use dvips when not producing a DVI"))
         sys.exit(2)
     ps = root + ".ps"
     self.dep = Dep(doc, ps, dvi, lastdep)
     doc.env.dep_append(self.dep)
Beispiel #21
0
 def run (self):
     """
     This method actually runs BibTeX with the appropriate environment
     variables set.
     """
     msg.progress(_("running BibTeX on %s") % self.base)
     doc = {}
     if len(self.bib_path) != 1:
         os.environ["BIBINPUTS"] = string.join(self.bib_path +
             [os.getenv("BIBINPUTS", "")], ":")
     if len(self.bst_path) != 1:
         os.environ["BSTINPUTS"] = string.join(self.bst_path +
             [os.getenv("BSTINPUTS", "")], ":")
     rc = subprocess.call(["bibtex", self.base], stdout=msg.stdout)
     if rc != 0:
         msg.error(_("There were errors making the bibliography."))
         return 1
     self.run_needed = 0
     self.doc.must_compile = 1
     return 0
Beispiel #22
0
 def __init__ (self, doc, dict):
     self.doc = doc
     lastdep = doc.env.dep_last()
     dvi = lastdep.prods[0]
     root, ext = os.path.splitext(dvi)
     if ext != ".dvi":
         msg.error(_("I can't use dvips when not producing a DVI"))
         sys.exit(2)
     ps = root + ".ps"
     self.dep = Dep(doc, ps, dvi, lastdep)
     doc.env.dep_append(self.dep)
Beispiel #23
0
    def last_compile(self):
        """
        Run the module-specific operations that are to be performed after
        the last compilation of the main source. Returns true on failure.
        """
        msg.log(_("running last-compilation scripts..."))

        for mod in self.modules.objects.values():
            if mod.last_compile():
                self.failed_module = mod
                return 1
        return 0
Beispiel #24
0
    def last_compile(self):
        """
        Run the module-specific operations that are to be performed after
        the last compilation of the main source. Returns true on failure.
        """
        msg.log(_("running last-compilation scripts..."))

        for mod in self.modules.objects.values():
            if mod.last_compile():
                self.failed_module = mod
                return 1
        return 0
Beispiel #25
0
 def clean (self):
     """
     Remove the files produced by this rule and recursively clean all
     dependencies.
     """
     for file in self.prods:
         if os.path.exists(file):
             msg.log(_("removing %s") % file)
             os.unlink(file)
     for src in self.sources.values():
         src.clean()
     self.date = None
Beispiel #26
0
    def clean(self):
        """
        Remove all files that are produced by compilation.
        """
        self.remove_suffixes([".log", ".aux", ".toc", ".lof", ".lot",
                              ".out", ".glo", ".cb"])

        msg.log(_("cleaning additional files..."))
        # for dep in self.sources.values():
        #     dep.clean()

        for mod in self.modules.objects.values():
            mod.clean()
Beispiel #27
0
 def run_needed (self):
     """
     Check if makeindex has to be run. This is the case either if the
     target file does not exist or if the source file has changed.
     """
     if os.path.getsize(self.source) == 0:
         msg.log(_("the index file %s is empty") % self.source, pkg="index")
         return 0
     new = md5_file(self.source)
     if not os.path.exists(self.target):
         self.md5 = new
         return 1
     if not self.md5:
         self.md5 = new
         msg.log(_("the index file %s is new") % self.source, pkg="index")
         return 1
     if self.md5 == new:
         msg.log(_("the index %s did not change") % self.source, pkg="index")
         return 0
     self.md5 = new
     msg.log(_("the index %s has changed") % self.source, pkg="index")
     return 1
Beispiel #28
0
    def clean(self):
        """
        Remove all files that are produced by compilation.
        """
        self.remove_suffixes(
            [".log", ".aux", ".toc", ".lof", ".lot", ".out", ".glo", ".cb"])

        msg.log(_("cleaning additional files..."))
        # for dep in self.sources.values():
        #     dep.clean()

        for mod in self.modules.objects.values():
            mod.clean()
Beispiel #29
0
 def compile_needed(self):
     """
     Returns true if a first compilation is needed. This method supposes
     that no compilation was done (by the script) yet.
     """
     if self.must_compile:
         return 1
     msg.log(_("checking if compiling is necessary..."))
     if not self.draft_support and not os.path.exists(self.outfile):
         msg.debug(_("the output file doesn't exist"))
         return 1
     if not os.path.exists(self.logfile):
         msg.debug(_("the log file does not exist"))
         return 1
     if (not self.draft_support and
         (os.path.getmtime(self.outfile) < os.path.getmtime(self.srcfile))):
         msg.debug(_("the source is younger than the output file"))
         return 1
     if self.log.read(self.logfile):
         msg.debug(_("the log file is not produced by TeX"))
         return 1
     return self.recompile_needed()
Beispiel #30
0
 def compile_needed (self):
     """
     Returns true if a first compilation is needed. This method supposes
     that no compilation was done (by the script) yet.
     """
     if self.must_compile:
         return 1
     msg.log(_("checking if compiling is necessary..."))
     if not self.draft_support and not os.path.exists(self.outfile):
         msg.debug(_("the output file doesn't exist"))
         return 1
     if not os.path.exists(self.logfile):
         msg.debug(_("the log file does not exist"))
         return 1
     if (not self.draft_support and 
         (os.path.getmtime(self.outfile) < os.path.getmtime(self.srcfile))):
         msg.debug(_("the source is younger than the output file"))
         return 1
     if self.log.read(self.logfile):
         msg.debug(_("the log file is not produced by TeX"))
         return 1
     return self.recompile_needed()
Beispiel #31
0
 def __init__ (self, doc, dict):
     env = doc.env
     ps = env.dep_last().prods[0]
     root, ext = os.path.splitext(ps)
     if ext != ".ps":
         msg.error(_("I can't use ps2pdf when not producing a PS"))
         sys.exit(2)
     pdf = root + ".pdf"
     cmd = ["ps2pdf"]
     for opt in doc.paper.split():
         cmd.append("-sPAPERSIZE=" + opt)
     cmd.extend([ps, pdf])
     dep = DependShell(env, cmd, prods=[pdf], sources={ ps: env.dep_last() })
     env.dep_append(dep)
Beispiel #32
0
 def update(self):
     """
     Update the MD5 sums of all files watched, and return the name of one
     of the files that changed, or None of they didn't change.
     """
     changed = []
     for file in self.files.keys():
         if os.path.exists(file):
             new = md5_file(file)
             if self.files[file] != new:
                 msg.debug(_("%s MD5 checksum changed") % \
                           os.path.basename(file))
                 changed.append(file)
             self.files[file] = new
     return changed
Beispiel #33
0
    def pre_compile(self, force):
        """
        Prepare the source for compilation using package-specific functions.
        This function must return true on failure. This function sets
        `must_compile' to 1 if we already know that a compilation is needed,
        because it may avoid some unnecessary preprocessing (e.g. BibTeXing).
        """
        # Watch for the changes of these working files
        for ext in ("aux", "toc", "lot", "lof"):
            self.watcher.watch(self.srcbase + "." + ext)

        msg.log(_("building additional files..."))
        for mod in self.modules.objects.values():
            if mod.pre_compile():
                self.failed_module = mod
                return 1
        return 0
Beispiel #34
0
    def pre_compile(self, force):
        """
        Prepare the source for compilation using package-specific functions.
        This function must return true on failure. This function sets
        `must_compile' to 1 if we already know that a compilation is needed,
        because it may avoid some unnecessary preprocessing (e.g. BibTeXing).
        """
        # Watch for the changes of these working files
        for ext in ("aux", "toc", "lot", "lof"):
            self.watcher.watch(self.srcbase + "." + ext)

        msg.log(_("building additional files..."))
        for mod in self.modules.objects.values():
            if mod.pre_compile():
                self.failed_module = mod
                return 1
        return 0
Beispiel #35
0
 def style_changed (self):
     """
     Read the log file if it exists and check if the style used is the one
     specified in the source. This supposes that the style is mentioned on
     a line with the form 'The style file: foo.bst'.
     """
     if not exists(self.blgfile):
         return 0
     log = open(self.blgfile)
     line = log.readline()
     while line != "":
         if line.startswith("The style file: "):
             if line.rstrip()[16:-4] != self.style:
                 msg.log(_("the bibliography style was changed"), pkg="bibtex")
                 log.close()
                 return 1
         line = log.readline()
     log.close()
     return 0
Beispiel #36
0
 def style_changed(self):
     """
     Read the log file if it exists and check if the style used is the one
     specified in the source. This supposes that the style is mentioned on
     a line with the form 'The style file: foo.bst'.
     """
     if not exists(self.blgfile):
         return 0
     log = open(self.blgfile)
     line = log.readline()
     while line != "":
         if line.startswith("The style file: "):
             if line.rstrip()[16:-4] != self.style:
                 msg.log(_("the bibliography style was changed"),
                         pkg="bibtex")
                 log.close()
                 return 1
         line = log.readline()
     log.close()
     return 0
Beispiel #37
0
    def register(self, name, dict={}):
        """
        Attempt to register a package with the specified name. If a module is
        found, create an object from the module's class called `Module',
        passing it the environment and `dict' as arguments, and execute all
        delayed commands for this module. The dictionary describes the
        command that caused the registration.
        """
        if self.has_key(name):
            msg.debug(_("module %s already registered") % name)
            return 2

        # First look for a script

        moddir = ""
        mod = None
        for path in "", join(moddir, "modules"):
            file = join(path, name + ".rub")
            if exists(file):
                mod = ScriptModule(self.env, file)
                msg.log(_("script module %s registered") % name)
                break

        # Then look for a Python module

        if not mod:
            if Plugins.register(self, name) == 0:
                msg.debug(_("no support found for %s") % name)
                return 0
            mod = self.modules[name].Module(self.env, dict)
            msg.log(_("built-in module %s registered") % name)

        # Run any delayed commands.

        if self.commands.has_key(name):
            for (cmd, args, vars) in self.commands[name]:
                msg.push_pos(vars)
                try:
                    mod.command(cmd, args)
                except AttributeError:
                    msg.warn(_("unknown directive '%s.%s'") % (name, cmd))
                except TypeError:
                    msg.warn(_("wrong syntax for '%s.%s'") % (name, cmd))
                msg.pop_pos()
            del self.commands[name]

        self.objects[name] = mod
        return 1
Beispiel #38
0
    def register (self, name, dict={}):
        """
        Attempt to register a package with the specified name. If a module is
        found, create an object from the module's class called `Module',
        passing it the environment and `dict' as arguments, and execute all
        delayed commands for this module. The dictionary describes the
        command that caused the registration.
        """
        if self.has_key(name):
            msg.debug(_("module %s already registered") % name)
            return 2

        # First look for a script

        moddir = ""
        mod = None
        for path in "", join(moddir, "modules"):
            file = join(path, name + ".rub")
            if exists(file):
                mod = ScriptModule(self.env, file)
                msg.log(_("script module %s registered") % name)
                break

        # Then look for a Python module

        if not mod:
            if Plugins.register(self, name) == 0:
                msg.debug(_("no support found for %s") % name)
                return 0
            mod = self.modules[name].Module(self.env, dict)
            msg.log(_("built-in module %s registered") % name)

        # Run any delayed commands.

        if self.commands.has_key(name):
            for (cmd, args, vars) in self.commands[name]:
                msg.push_pos(vars)
                try:
                    mod.command(cmd, args)
                except AttributeError:
                    msg.warn(_("unknown directive '%s.%s'") % (name, cmd))
                except TypeError:
                    msg.warn(_("wrong syntax for '%s.%s'") % (name, cmd))
                msg.pop_pos()
            del self.commands[name]

        self.objects[name] = mod
        return 1
Beispiel #39
0
 def do_tool (self, tool):
     if tool not in ("makeindex", "xindy"):
         msg.error(_("unknown indexing tool '%s'") % tool)
     self.tool = tool
Beispiel #40
0
    def bibtex_needed (self):
        """
        Return true if BibTeX must be run.
        """
        if self.run_needed:
            return 1
        msg.log(_("checking if BibTeX must be run..."), pkg="bibtex")

        newcites, dbs = self.parse_aux()

        # If there was a list of used citations, we check if it has
        # changed. If it has, we have to rerun.

        if self.prev_dbs is not None and self.prev_dbs != dbs:
            msg.log(_("the set of databases changed"), pkg="bibtex")
            self.prev_dbs = dbs
            self.used_cites = newcites
            self.undef_cites = self.list_undefs()
            return 1
        self.prev_dbs = dbs

        # If there was a list of used citations, we check if it has
        # changed. If it has, we have to rerun.

        if self.used_cites and newcites != self.used_cites:
            msg.log(_("the list of citations changed"), pkg="bibtex")
            self.used_cites = newcites
            self.undef_cites = self.list_undefs()
            return 1
        self.used_cites = newcites

        # If there was a list of undefined citations, we check if it has
        # changed. If it has and it is not empty, we have to rerun.

        if self.undef_cites:
            new = self.list_undefs()
            if new == []:
                msg.log(_("no more undefined citations"), pkg="bibtex")
                self.undef_cites = new
            else:
                for cite in new:
                    if cite in self.undef_cites:
                        continue
                    msg.log(_("there are new undefined citations"), pkg="bibtex")
                    self.undef_cites = new
                    return 1
                msg.log(_("there is no new undefined citation"), pkg="bibtex")
                self.undef_cites = new
                return 0
        else:
            self.undef_cites = self.list_undefs()

        # At this point we don't know if undefined citations changed. If
        # BibTeX has not been run before (i.e. there is no log file) we know
        # that it has to be run now.

        if not exists(self.blgfile):
            msg.log(_("no BibTeX log file"), pkg="bibtex")
            return 1

        # Here, BibTeX has been run before but we don't know if undefined
        # citations changed.

        if self.undef_cites == []:
            msg.log(_("no undefined citations"), pkg="bibtex")
            return 0

        if getmtime(self.blgfile) < getmtime(self.doc.logfile):
            msg.log(_("BibTeX's log is older than the main log"), pkg="bibtex")
            return 1

        return 0
Beispiel #41
0
    def parse (self, errors=0, boxes=0, refs=0, warnings=0):
        """
        Parse the log file for relevant information. The named arguments are
        booleans that indicate which information should be extracted:
        - errors: all errors
        - boxes: bad boxes
        - refs: warnings about references
        - warnings: all other warnings
        The function returns a generator. Each generated item is a dictionary
        that contains (some of) the following entries:
        - kind: the kind of information ("error", "box", "ref", "warning")
        - text: the text of the error or warning
        - code: the piece of code that caused an error
        - file, line, last, pkg: as used by Message.format_pos.
        """
        if not self.lines:
            return
        last_file = None
        pos = [last_file]
        page = 1
        parsing = 0    # 1 if we are parsing an error's text
        skipping = 0   # 1 if we are skipping text until an empty line
        something = 0  # 1 if some error was found
        prefix = None  # the prefix for warning messages from packages
        accu = ""      # accumulated text from the previous line
        for line in self.lines:
            line = line[:-1]  # remove the line feed

            # TeX breaks messages at 79 characters, just to make parsing
            # trickier...

            if self.continued(line):
                accu += line
                continue
            line = accu + line
            accu = ""

            # Text that should be skipped (from bad box messages)

            if prefix is None and line == "":
                skipping = 0
                continue

            if skipping:
                continue

            # Errors (including aborted compilation)

            if parsing:
                if error == "Undefined control sequence.":
                    # This is a special case in order to report which control
                    # sequence is undefined.
                    m = self.re_cseq.match(line)
                    if m:
                        error = "Undefined control sequence %s." % m.group("seq")
                m = self.re_line.match(line)
                if m:
                    parsing = 0
                    skipping = 1
                    pdfTeX = error.find("pdfTeX warning") != -1
                    if (pdfTeX and warnings) or (errors and not pdfTeX):
                        if pdfTeX:
                            d = {
                                "kind": "warning",
                                "pkg": "pdfTeX",
                                "text": error[error.find(":")+2:]
                            }
                        else:
                            d = {
                                "kind": "error",
                                "text": error
                            }
                        d.update( m.groupdict() )
                        m = self.re_ignored.search(error)
                        if m:
                            d["file"] = last_file
                            if d.has_key("code"):
                                del d["code"]
                            d.update( m.groupdict() )
                        elif pos[-1] is None:
                            d["file"] = last_file
                        else:
                            d["file"] = pos[-1]
                        yield d
                elif line[0] == "!":
                    error = line[2:]
                elif line[0:3] == "***":
                    parsing = 0
                    skipping = 1
                    if errors:
                        yield    {
                            "kind": "abort",
                            "text": error,
                            "why" : line[4:],
                            "file": last_file
                            }
                elif line[0:15] == "Type X to quit ":
                    parsing = 0
                    skipping = 0
                    if errors:
                        yield    {
                            "kind": "error",
                            "text": error,
                            "file": pos[-1]
                            }
                continue

            if len(line) > 0 and line[0] == "!":
                error = line[2:]
                parsing = 1
                continue

            if line == "Runaway argument?":
                error = line
                parsing = 1
                continue

            # Long warnings

            if prefix is not None:
                if line[:len(prefix)] == prefix:
                    text.append(line[len(prefix):].strip())
                else:
                    text = " ".join(text)
                    m = self.re_online.search(text)
                    if m:
                        info["line"] = m.group("line")
                        text = text[:m.start()] + text[m.end():]
                    if warnings:
                        info["text"] = text
                        d = { "kind": "warning" }
                        d.update( info )
                        yield d
                    prefix = None
                continue

            # Undefined references

            m = self.re_reference.match(line)
            if m:
                if refs:
                    d = {
                        "kind": "warning",
                        "text": _("Reference `%s' undefined.") % m.group("ref"),
                        "file": pos[-1]
                        }
                    d.update( m.groupdict() )
                    yield d
                continue

            m = self.re_label.match(line)
            if m:
                if refs:
                    d = {
                        "kind": "warning",
                        "file": pos[-1]
                        }
                    d.update( m.groupdict() )
                    yield d
                continue

            # Other warnings

            if line.find("Warning") != -1:
                m = self.re_warning.match(line)
                if m:
                    info = m.groupdict()
                    info["file"] = pos[-1]
                    info["page"] = page
                    if info["pkg"] is None:
                        del info["pkg"]
                        prefix = ""
                    else:
                        prefix = ("(%s)" % info["pkg"])
                    prefix = prefix.ljust(m.start("text"))
                    text = [info["text"]]
                continue

            # Bad box messages

            m = self.re_badbox.match(line)
            if m:
                if boxes:
                    mpos = { "file": pos[-1], "page": page }
                    m = self.re_atline.search(line)
                    if m:
                        md = m.groupdict()
                        for key in "line", "last":
                            if md[key]: mpos[key] = md[key]
                        line = line[:m.start()]
                    d = {
                        "kind": "warning",
                        "text": line
                        }
                    d.update( mpos )
                    yield d
                skipping = 1
                continue

            # If there is no message, track source names and page numbers.

            last_file = self.update_file(line, pos, last_file)
            page = self.update_page(line, page)
Beispiel #42
0
    def parse(self, errors=0, boxes=0, refs=0, warnings=0, misschars=0):
        """
        Parse the log file for relevant information. The named arguments are
        booleans that indicate which information should be extracted:
        - errors: all errors
        - boxes: bad boxes
        - refs: warnings about references
        - warnings: all other warnings
        The function returns a generator. Each generated item is a dictionary
        that contains (some of) the following entries:
        - kind: the kind of information ("error", "box", "ref", "warning")
        - text: the text of the error or warning
        - code: the piece of code that caused an error
        - file, line, last, pkg: as used by Message.format_pos.
        """
        if not self.lines:
            return
        last_file = None
        pos = [last_file]
        page = 1
        parsing = 0  # 1 if we are parsing an error's text
        skipping = 0  # 1 if we are skipping text until an empty line
        something = 0  # 1 if some error was found
        prefix = None  # the prefix for warning messages from packages
        accu = ""  # accumulated text from the previous line
        for line in self.lines:
            line = line[:-1]  # remove the line feed

            # TeX breaks messages at 79 characters, just to make parsing
            # trickier...

            if self.continued(line):
                accu += line
                continue
            line = accu + line
            accu = ""

            # Text that should be skipped (from bad box messages)

            if prefix is None and line == "":
                skipping = 0
                continue

            if skipping:
                continue

            # Errors (including aborted compilation)

            if parsing:
                if error == "Undefined control sequence.":
                    # This is a special case in order to report which control
                    # sequence is undefined.
                    m = self.re_cseq.match(line)
                    if m:
                        error = "Undefined control sequence %s." % m.group(
                            "seq")
                m = self.re_line.match(line)
                if m:
                    parsing = 0
                    skipping = 1
                    pdfTeX = error.find("pdfTeX warning") != -1
                    if (pdfTeX and warnings) or (errors and not pdfTeX):
                        if pdfTeX:
                            d = {
                                "kind": "warning",
                                "pkg": "pdfTeX",
                                "text": error[error.find(":") + 2:]
                            }
                        else:
                            d = {"kind": "error", "text": error}
                        d.update(m.groupdict())
                        m = self.re_ignored.search(error)
                        if m:
                            d["file"] = last_file
                            if d.has_key("code"):
                                del d["code"]
                            d.update(m.groupdict())
                        elif pos[-1] is None:
                            d["file"] = last_file
                        else:
                            d["file"] = pos[-1]
                        yield d
                elif line[0] == "!":
                    error = line[2:]
                elif line[0:3] == "***":
                    parsing = 0
                    skipping = 1
                    if errors:
                        yield {
                            "kind": "abort",
                            "text": error,
                            "why": line[4:],
                            "file": last_file
                        }
                elif line[0:15] == "Type X to quit ":
                    parsing = 0
                    skipping = 0
                    if errors:
                        yield {"kind": "error", "text": error, "file": pos[-1]}
                continue

            if len(line) > 0 and line[0] == "!":
                error = line[2:]
                parsing = 1
                continue

            if line == "Runaway argument?":
                error = line
                parsing = 1
                continue

            # Long warnings

            if prefix is not None:
                if line[:len(prefix)] == prefix:
                    text.append(line[len(prefix):].strip())
                else:
                    text = " ".join(text)
                    m = self.re_online.search(text)
                    if m:
                        info["line"] = m.group("line")
                        text = text[:m.start()] + text[m.end():]
                    if warnings:
                        info["text"] = text
                        d = {"kind": "warning"}
                        d.update(info)
                        yield d
                    prefix = None
                continue

            # Undefined references

            m = self.re_reference.match(line)
            if m:
                if refs:
                    d = {
                        "kind": "warning",
                        "text":
                        _("Reference `%s' undefined.") % m.group("ref"),
                        "file": pos[-1]
                    }
                    d.update(m.groupdict())
                    yield d
                continue

            m = self.re_label.match(line)
            if m:
                if refs:
                    d = {"kind": "warning", "file": pos[-1]}
                    d.update(m.groupdict())
                    yield d
                continue

            # Other warnings

            if line.find("Warning") != -1:
                m = self.re_warning.match(line)
                if m:
                    info = m.groupdict()
                    info["file"] = pos[-1]
                    info["page"] = page
                    if info["pkg"] is None:
                        del info["pkg"]
                        prefix = ""
                    else:
                        prefix = ("(%s)" % info["pkg"])
                    prefix = prefix.ljust(m.start("text"))
                    text = [info["text"]]
                continue

            # Bad box messages

            m = self.re_badbox.match(line)
            if m:
                if boxes:
                    mpos = {"file": pos[-1], "page": page}
                    m = self.re_atline.search(line)
                    if m:
                        md = m.groupdict()
                        for key in "line", "last":
                            if md[key]: mpos[key] = md[key]
                        line = line[:m.start()]
                    d = {"kind": "warning", "text": line}
                    d.update(mpos)
                    yield d
                skipping = 1
                continue

            # Missing characters in a font
            if misschars:
                m = self.re_misschar.match(line)
                if m:
                    d = {
                        "kind": "warning",
                        "uchar": m.group("uchar"),
                        "font": m.group("font"),
                    }
                    yield d
                    continue

            # If there is no message, track source names and page numbers.

            last_file = self.update_file(line, pos, last_file)
            page = self.update_page(line, page)
Beispiel #43
0
    def post_compile (self):
        """
        Run makeindex if needed, with appropriate options and environment.
        """
        if not os.path.exists(self.source):
            msg.log(_("strange, there is no %s") % self.source, pkg="index")
            return 0
        if not self.run_needed():
            return 0

        msg.progress(_("processing index %s") % self.source)

        if self.tool == "makeindex":
            cmd = ["makeindex", "-o", self.target] + self.opts
            cmd.extend(["-t", self.transcript])
            if self.style:
                cmd.extend(["-s", self.style])
            cmd.append(self.source)
            path_var = "INDEXSTYLE"

        elif self.tool == "xindy":
            cmd = ["texindy", "--quiet"]
            for opt in self.opts:
                if opt == "-g":
                    if self.lang != "":
                        msg.warn(_("'language' overrides 'order german'"),
                            pkg="index")
                    else:
                        self.lang = "german-din"
                elif opt == "-l":
                    self.modules.append("letter-ordering")
                    msg.warn(_("use 'module letter-ordering' instead of 'order letter'"),
                        pkg="index")
                else:
                    msg.error("unknown option to xindy: %s" % opt, pkg="index")
            for mod in self.modules:
                cmd.extend(["--module", mod])
            if self.lang:
                cmd.extend(["--language", self.lang])
            cmd.append(self.source)
            path_var = "XINDY_SEARCHPATH"

        if self.path != []:
            env = { path_var:
                string.join(self.path + [os.getenv(path_var, "")], ":") }
        else:
            env = {}

        msg.debug(" ".join(cmd))
        # Makeindex outputs everything to stderr, even progress messages
        rc = subprocess.call(cmd, stderr=msg.stdout)
        if (rc != 0):
            msg.error(_("could not make index %s") % self.target)
            return 1

        # Beware with UTF-8 encoding, makeindex with headings can be messy
        if self.doc.encoding == "utf8" and self.style:
            f = file(self.target, "r")
            error = 0
            for line in f:
                try:
                    line.decode("utf8")
                except:
                    error = 1
                    break
            f.close()
            if error:
                print "here"
                # Retry without style
                msg.log(_("%s on UTF8 failed. Retry...") % self.tool)
                self.style = ""
                self.md5 = None
                return self.post_compile()

        self.doc.must_compile = 1
        return 0
Beispiel #44
0
    def bibtex_needed(self):
        """
        Return true if BibTeX must be run.
        """
        if self.run_needed:
            return 1
        msg.log(_("checking if BibTeX must be run..."), pkg="bibtex")

        newcites, dbs = self.parse_aux()

        # If there was a list of used citations, we check if it has
        # changed. If it has, we have to rerun.

        if self.prev_dbs is not None and self.prev_dbs != dbs:
            msg.log(_("the set of databases changed"), pkg="bibtex")
            self.prev_dbs = dbs
            self.used_cites = newcites
            self.undef_cites = self.list_undefs()
            return 1
        self.prev_dbs = dbs

        # If there was a list of used citations, we check if it has
        # changed. If it has, we have to rerun.

        if self.used_cites and newcites != self.used_cites:
            msg.log(_("the list of citations changed"), pkg="bibtex")
            self.used_cites = newcites
            self.undef_cites = self.list_undefs()
            return 1
        self.used_cites = newcites

        # If there was a list of undefined citations, we check if it has
        # changed. If it has and it is not empty, we have to rerun.

        if self.undef_cites:
            new = self.list_undefs()
            if new == []:
                msg.log(_("no more undefined citations"), pkg="bibtex")
                self.undef_cites = new
            else:
                for cite in new:
                    if cite in self.undef_cites:
                        continue
                    msg.log(_("there are new undefined citations"),
                            pkg="bibtex")
                    self.undef_cites = new
                    return 1
                msg.log(_("there is no new undefined citation"), pkg="bibtex")
                self.undef_cites = new
                return 0
        else:
            self.undef_cites = self.list_undefs()

        # At this point we don't know if undefined citations changed. If
        # BibTeX has not been run before (i.e. there is no log file) we know
        # that it has to be run now.

        if not exists(self.blgfile):
            msg.log(_("no BibTeX log file"), pkg="bibtex")
            return 1

        # Here, BibTeX has been run before but we don't know if undefined
        # citations changed.

        if self.undef_cites == []:
            msg.log(_("no undefined citations"), pkg="bibtex")
            return 0

        if getmtime(self.blgfile) < getmtime(self.doc.logfile):
            msg.log(_("BibTeX's log is older than the main log"), pkg="bibtex")
            return 1

        return 0