Пример #1
0
    def __init__(self, cwd=None):
        """
        Initialize the environment. The optional argument is the path to the
        reference directory for compilation, by default it is the current
        working directory.
        """
        self.kpse_msg = {
            "mktextfm": _("making font metrics for \\g<arg>"),
            "mktexmf": _("making font \\g<arg>"),
            "mktexpk": _("making bitmap for font \\g<arg>")
        }

        if cwd is None: cwd = os.getcwd()
        self.vars = Variables(items={'cwd': cwd, '_environment': self})
        self.path = [cwd]
        self.conv_prefs = {}

        # Represents a set of dependency nodes. Nodes can be accessed by absolute
        # path name using the dictionary interface.
        self.depends = dict()
        self.converter = Converter(self.depends)
        self.converter.read_ini(os.path.join(moddir, 'rules.ini'))

        self.is_in_unsafe_mode_ = False
        self.doc_requires_shell_ = False
        self.main = None
        self.final = None
Пример #2
0
	def run (self):
		msg.progress(_("running: %s") % ' '.join(self.command))
		process = Popen(self.command, stdin=devnull(), stdout=self.stdout)
		if process.wait() != 0:
			msg.error(_("execution of %s failed") % self.command[0])
			return False
		return True
Пример #3
0
 def do_read(self, args):
     if len(args) != 1:
         raise rubber.SyntaxError(
             _("invalid syntax for directive '%s'") % "read")
     name = args[0]
     saved_vars = self.vars
     try:
         self.vars = self.vars.copy()
         self.vars["file"] = name
         self.vars["line"] = None
         with open(name, encoding='utf_8', errors='replace') as file:
             lineno = 0
             for line in file:
                 lineno += 1
                 line = line.strip()
                 if line == "" or line[0] == "%":
                     continue
                 self.vars["line"] = lineno
                 lst = parse_line(line, self.vars)
                 self.command(lst[0], lst[1:])
     except IOError:
         msg.warning(
             rubber.util._format(self.vars,
                                 _("cannot read option file %s") % name))
     finally:
         self.vars = saved_vars
Пример #4
0
def process_source_pipe(env, pipe_tempfile, options):
    """
    Build the document, and dump the result on stdout.
    """
    try:
        build(options, RUBBER_PIPE, env)
        filename = env.final.primary_product()
        try:
            # dump the results on standard output
            with open(filename, "rb") as output:
                shutil.copyfileobj(output, sys.stdout.buffer)
        except IOError:
            raise rubber.GenericError(
                _("error copying the product '%s' to stdout") % filename)
    finally:
        # clean the intermediate files
        if not options.keep:
            for node in env.final.all_producers():
                node.clean()
            cache_path = env.main.basename('.rubbercache')
            if os.path.exists(cache_path):
                msg.debug(_("removing %s"), cache_path)
                os.remove(cache_path)
            if os.path.exists(pipe_tempfile):
                msg.info(_("removing %s"), pipe_tempfile)
                os.remove(pipe_tempfile)
Пример #5
0
    def __init__ (self, cwd=None):
        """
        Initialize the environment. The optional argument is the path to the
        reference directory for compilation, by default it is the current
        working directory.
        """
        self.kpse_msg = {
            "mktextfm" : _("making font metrics for \\g<arg>"),
            "mktexmf" : _("making font \\g<arg>"),
            "mktexpk" : _("making bitmap for font \\g<arg>")
            }

        if cwd is None: cwd = os.getcwd()
        self.vars = Variables(items = { 'cwd': cwd, '_environment': self })
        self.path = [cwd]
        self.conv_prefs = {}

        # Represents a set of dependency nodes. Nodes can be accessed by absolute
        # path name using the dictionary interface.
        self.depends = dict()
        self.converter = Converter(self.depends)
        self.converter.read_ini(os.path.join(moddir, 'rules.ini'))

        self.is_in_unsafe_mode_ = False
        self.doc_requires_shell_ = False
        self.main = None
        self.final = None
Пример #6
0
    def should_make(self):
        """
		Check the dependencies. Return true if this node has to be recompiled,
		i.e. if some dependency is modified. Nothing recursive is done here.
		"""
        if not self.date:
            return True
        for source_name in self.sources:
            source = self.set[source_name]
            # FIXME complain if source has been modified in an unplanned way
            # NB: we ignore the case source.date == None (missing dependency) here.
            # NB2: to be extra correct, equal (disk-precision) timestamps trigger a recompile.
            if source.date is not None and source.date >= self.date:
                if self.md5_for_source.has_key(source_name):
                    if self.md5_for_source[
                            source_name] == rubber.util.md5_file(source_name):
                        msg.debug(_(
                            "while making %s: contents of %s unchanged, ignoring mtime"
                        ) % (self.products[0], source_name),
                                  pkg="depend")
                        continue
                    msg.debug(_(
                        "while making %s: contents of dependency %s changed, rebuilding"
                    ) % (self.products[0], source_name),
                              pkg="depend")
                    return True
                msg.debug(_(
                    "while making %s: timestamp of dependency %s changed, rebuilding"
                ) % (self.products[0], source_name),
                          pkg="depend")
                return True
        return False
Пример #7
0
    def post_compile(self):
        """
        Run the package-specific operations that are to be performed after
        each compilation of the main source. Returns true on success or false
        on failure.
        """
        msg.debug(_("running post-compilation scripts..."))

        for l in self.onchange:
            (file, old_contents, cmd) = l
            new = rubber.contents.snapshot(file)
            if old_contents != new:
                # An exception should already have been raised if the
                # file has disappeared.
                assert new != rubber.contents.NO_SUCH_FILE
                l[1] = new
                msg.info(_("running %s") % cmd)
                # FIXME portability issue: explicit reference to shell
                if rubber.util.execute(("sh", "-c", cmd)) != 0:
                    msg.error(_("command '%s' returned a non-zero status"),
                              cmd)
                    return False

        for mod in self.modules.objects.values():
            if not mod.post_compile():
                self.failed_module = mod
                return False
        return True
Пример #8
0
 def run(self):
     msg.progress(_("running: %s") % ' '.join(self.command))
     process = Popen(self.command, stdin=devnull(), stdout=self.stdout)
     if process.wait() != 0:
         msg.error(_("execution of %s failed") % self.command[0])
         return False
     return True
Пример #9
0
    def prepare_source(self, filename):
        """
		Dump the standard input in a file, and set up that file
		the same way we would normally process LaTeX sources.
		"""
        assert filename.endswith("-")  # filename is ignored

        try:
            # Make a temporary on-disk copy of the standard input,
            # in the current working directory.
            # The name will have the form "rubtmpXXX.tex.
            with tempfile.NamedTemporaryFile(suffix='.tex',
                                             prefix='rubtmp',
                                             dir='.',
                                             delete=False) as srcfile:
                # note the tempfile name so we can remove it later
                self.pipe_tempfile = srcfile.name
                # copy stdin into the tempfile
                msg.progress(_("saving the input in %s") % self.pipe_tempfile)
                shutil.copyfileobj(sys.stdin, srcfile)
        except IOError:
            msg.error(
                _("cannot create temporary file for the main LaTeX source"))
            rubber.util.abort_generic_error()

        return super(Pipe, self).prepare_source(self.pipe_tempfile)
Пример #10
0
def display(short, kind, text, **info):
    """
    Print an error or warning message. The argument 'kind' indicates the
    kind of message, among "error", "warning", "abort", the argument
    'text' is the main text of the message, the other arguments provide
    additional information, including the location of the error.
    """
    if kind == "error":
        if text[0:13] == "LaTeX Error: ":
            text = text[13:]
        msg.warning(rubber.util._format(info, text))
        if "code" in info and info["code"] and not short:
            if "macro" in info:
                del info["macro"]
            msg.warning(
                rubber.util._format(info,
                                    _("leading text: ") + info["code"]))
    elif kind == "abort":
        if short:
            m = _("compilation aborted ") + info["why"]
        else:
            m = _("compilation aborted: %s %s") % (text, info["why"])
        msg.warning(rubber.util._format(info, m))
    else:
        assert kind == "warning"
        msg.warning(rubber.util._format(info, text))
Пример #11
0
def prepare_source_pipe():
    """
    Dump the standard input in a file, and set up that file
    the same way we would normally process LaTeX sources.
    """

    # FIXME: with a better program structure, the context manager
    # should remove the input file.

    try:
        # Make a temporary on-disk copy of the standard input,
        # in the current working directory.
        # The name will have the form "rubtmpXXX.tex.
        with tempfile.NamedTemporaryFile(suffix='.tex',
                                         prefix='rubtmp',
                                         dir='.',
                                         delete=False) as srcfile:
            # note the tempfile name so we can remove it later
            pipe_tempfile = srcfile.name
            # copy stdin into the tempfile
            msg.info(_("saving the input in %s") % pipe_tempfile)
            shutil.copyfileobj(sys.stdin.buffer, srcfile)
    except IOError:
        raise rubber.GenericError(
            _("cannot create temporary file for the main LaTeX source"))

    return pipe_tempfile
Пример #12
0
    def convert(self,
                target,
                prefixes=[""],
                suffixes=[""],
                check=None,
                context=None):
        """
        Use conversion rules to make a given target file, and return:
        * the file path of an existing file matching the 'target' pattern
        * the final node of a new dependency tree if a conversion is necessary
        * None if the file does not exist and cannot be built.
        The optional arguments 'prefixes' and 'suffixes'
        are lists of strings that can be added at the beginning and the end of
        the name when searching for the file. Prefixes are tried in order, and
        for each prefix, suffixes are tried in order; the first file from this
        order that exists or can be made is kept. The optional arguments
        'check' and 'context' have the same meaning as in
        'Converter.best_rule'.
        """
        # Try all suffixes and prefixes until something is found.

        last = None
        for t in [p + target + s for s in suffixes for p in prefixes]:

            # Define a check function, according to preferences.

            if t in self.conv_prefs:
                prefs = self.conv_prefs[t]

                def do_check(vars, prefs=prefs):
                    if prefs is not None:
                        for key, val in prefs.items():
                            if not (key in vars and vars[key] == val):
                                return 0
                    return 1
            else:
                prefs = None
                do_check = check

            # Find the best applicable rule.

            ans = self.converter.best_rule(t, check=do_check, context=context)
            if ans is not None:
                if last is None or ans["cost"] < last["cost"]:
                    last = ans

            # Check if the target exists.

            if prefs is None and os.path.exists(t):
                if last is not None and last["cost"] <= 0:
                    break
                msg.debug(_("`%s' is `%s', no rule applied") % (target, t))
                return t

        if last is None:
            return None
        msg.debug(
            _("`%s' is `%s', made from `%s' by rule `%s'") %
            (target, last["target"], last["source"], last["name"]))
        return self.converter.apply(last)
Пример #13
0
def load_cache(cache_path):
    msg.debug(_('Reading external cache file %s') % cache_path)
    with open(cache_path) as f:
        line = f.readline()
        while line:
            product = line[:-1]
            sources = []
            snapshots = []
            while True:
                line = f.readline()
                if not line.startswith('  '):  # Including end of file.
                    break
                limit = 2 + rubber.contents.cs_str_len
                snapshots.append(rubber.contents.str2cs(line[2:limit]))
                sources.append(line[limit + 1:-1])
            try:
                node = _producer[product]
            except KeyError:
                msg.debug(_('%s: no such recipe anymore') % product)
            else:
                if node.sources != sources:
                    msg.debug(_('%s: depends on %s not anymore on %s'),
                              product, " ".join(node.sources),
                              " ".join(sources))
                elif node.snapshots is not None:
                    # FIXME: this should not happen. See cweb-latex test.
                    msg.debug(_('%s: rebuilt before cache read'), product)
                else:
                    msg.debug(_('%s: using cached checksums'), product)
                    node.snapshots = snapshots
Пример #14
0
    def process(self, path):
        """
        This method is called when an included file is processed. The argument
        must be a valid file name.
        """
        if path in self.processed_sources:
            msg.debug(_("%s already parsed") % path)
            return
        self.processed_sources[path] = None
        self.add_source(path)

        try:
            saved_vars = self.vars.copy()
            try:
                msg.debug(_("parsing %s") % path)
                self.vars["file"] = path
                self.vars["line"] = None
                with open(path, encoding='utf_8', errors='replace') as file:
                    self.parse_file(file)

            finally:
                self.vars = saved_vars
                msg.debug(_("end of %s") % path)

        except EndInput:
            pass
Пример #15
0
    def run(self):
        """
        This method reads the source file (which is supposed to be a
        gzip-compressed PostScript file) until it finds a line that contains a
        bounding box indication. Then it creates the target file with this
        single line.
        """
        msg.info(_("extracting bounding box from %s") % self.source)
        # Binary mode causes no decoding errors, but makes
        # difficult in Python to split UTF-8 input in lines.

        # Usual TeX encodings and UTF-8 share the property
        # that we can search for an ASCII pattern, and avoid
        # data corruption if other bytes are copied unchanged,
        # whichever character they represent.

        # Any 8-bit character has the advantage over UTF-8
        # that it never causes UnicodeDecodeError.
        with gzip.open(self.source, mode='rt', encoding='latin_1') as source:
            for line in source:
                if re_bbox.match(line):
                    with open(self.target, 'w', encoding='latin_1') as target:
                        target.write(line)
                    return True
        msg.error(_("no bounding box was found in %s!") % self.source)
        return False
Пример #16
0
 def readlog(self, name, limit):
     """
     Read the specified log file, checking that it was produced by the
     right compiler. Returns False if the log file is invalid or does not
     exist.
     """
     self.lines = None
     try:
         with open(name, encoding='utf_8', errors='replace') as fp:
             line = fp.readline()
             if not line or not re_loghead.match(line):
                 msg.debug(_('empty log'))
                 return False
             # do not read the whole log unconditionally
             whole_file = fp.read(limit)
             self.lines = whole_file.split('\n')
             if fp.read(1) != '':
                 # more data to be read
                 msg.warning(
                     _('log file is very long, and will not be read completely.'
                       ))
         return True
     except IOError:
         msg.debug(_('IO Error with log'))
         return False
Пример #17
0
 def do_tool(self, args):
     if len(args) != 1:
         raise rubber.SyntaxError(
             _("invalid syntax for directive '%s'") % "tool")
     tool = args[0]
     if tol not in ("makeindex", "xindy"):
         msg.error(_("unknown indexing tool '%s'") % tool)
     self.cmd[0] = tool
Пример #18
0
 def run(self):
     bak = self.aux + '.away_from_asymptote'
     msg.debug(_("saving %s to %s"), self.aux, bak)
     os.rename(self.aux, bak)
     try:
         return super().run()
     finally:
         msg.debug(_("restoring %s to %s"), bak, self.aux)
         os.rename(bak, self.aux)
Пример #19
0
 def run(self):
     msg.info(_("running: %s") % ' '.join(self.command))
     process = subprocess.Popen(self.command,
                                stdin=subprocess.DEVNULL,
                                stdout=self.stdout)
     if process.wait() != 0:
         msg.error(_("execution of %s failed") % self.command[0])
         return False
     return True
Пример #20
0
 def hook_externaldocument(self, loc, opt, name):
     aux = self.doc.env.find_file(name + '.aux')
     if aux:
         self.doc.add_source(aux)
         msg.debug(_("dependency %s added for external references") % aux)
     else:
         msg.debug(
             _("file %s.aux is required by xr package but not found") %
             name)
Пример #21
0
 def run (self):
     msg.info (_("compressing %s into %s") % (self.source, self.target))
     try:
         with open (self.source, 'rb') as f_in:
             with self.constructor (self.target, 'wb') as f_out:
                 f_out.writelines (f_in)
     except:
         msg.error (_ ("compression failed"))
         return False
     return True
Пример #22
0
 def do_onchange(self, args):
     if len(args) != 2:
         raise rubber.SyntaxError(
             _("invalid syntax for directive '%s'") % "onchange")
     file, cmd = args
     if self.env.is_in_unsafe_mode_:
         # A list, because we will update the snapshot later.
         self.onchange.append([file, rubber.contents.snapshot(file), cmd])
     else:
         msg.warning(
             _("Rubber directive 'onchange' is valid only in unsafe mode"))
Пример #23
0
 def do_alias(self, args):
     if len(args) != 2:
         raise rubber.SyntaxError(
             _("invalid syntax for directive '%s'") % "alias")
     name, val = args
     try:
         h = self.hooks[val]
     except KeyError:
         raise rubber.SyntaxError(_("cannot alias unknown name %s") % val)
     self.hooks[name] = h
     self.hooks_version += 1
Пример #24
0
    def real_make(self, force):
        rv = UNCHANGED
        patience = 5
        primary_product = self.products[0]
        msg.debug(_("make %s -> %s") % (primary_product, str(self.sources)),
                  pkg="depend")
        while patience > 0:
            # make our sources
            for source_name in self.sources:
                source = self.set[source_name]
                if source.making:
                    # cyclic dependency -- drop for now, we will re-visit
                    # this would happen while trying to remake the .aux in order to make the .bbl, for example
                    msg.debug(
                        _("while making %s: cyclic dependency on %s (pruned)")
                        % (primary_product, source_name),
                        pkg="depend")
                    continue
                source_rv = source.make(force)
                if source_rv == ERROR:
                    self.failed_dep = source.failed_dep
                    msg.debug(
                        _("while making %s: dependency %s could not be made") %
                        (primary_product, source_name),
                        pkg="depend")
                    return ERROR
                elif source_rv == CHANGED:
                    rv = CHANGED

            must_make = force or self.should_make()
            if not must_make:
                return rv

            # record MD5 hash of source files as we now actually start the build
            for source_name in self.md5_for_source.keys():
                self.md5_for_source[source_name] = rubber.util.md5_file(
                    source_name)

            # actually make
            if not self.run():
                self.failed_dep = self
                return ERROR

            self.date = time.time()
            rv = CHANGED
            force = False

            patience -= 1

        self.failed_dep = self
        msg.error(_("while making %s: file contents does not seem to settle") %
                  self.products[0],
                  pkg="depend")
        return ERROR
Пример #25
0
def process_source_info(env, act, short):
    if act == "deps":
        print(" ".join(env.final.all_leaves()))

    elif act == "rules":
        for node in env.final.all_producers():
            print("\n%s:" % " ".join(node.products()))
            print(" ".join(node.sources))

    else:
        # Check for a log file and extract information from it if it exists,
        # accroding to the argument's value.
        log = env.main.log
        if not env.main.parse_log():
            raise rubber.GenericError(_("Parsing the log file failed"))

        if act == "boxes":
            for err in log.get_boxes():
                display(short, **err)
            else:
                msg.info(_("There is no bad box."))
        elif act == "check":
            finished = False
            for err in log.get_errors():
                display(short, **err)
                finished = True
            if finished:
                return 0
            msg.info(_("There was no error."))
            for err in log.get_references():
                display(short, **err)
                finished = True
            if finished:
                return 0
            msg.info(_("There is no undefined reference."))
            for err in log.get_warnings():
                display(short, **err)
            else:
                msg.info(_("There is no warning."))
            for err in log.get_boxes():
                display(short, **err)
            else:
                msg.info(_("There is no bad box."))
        elif act == "errors":
            for err in log.get_errors():
                display(short, **err)
            else:
                msg.info(_("There was no error."))
        elif act == "refs":
            for err in log.get_references():
                display(short, **err)
            else:
                msg.info(_("There is no undefined reference."))
        else:
            assert act == "warnings"
            for err in log.get_warnings():
                display(short, **err)
            else:
                msg.info(_("There is no warning."))
Пример #26
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 True
        if not self.run_needed():
            return True

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

        if self.tool == "makeindex":
            cmd = ["makeindex", "-q", "-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: ':'.join(self.path + [os.getenv(path_var, '')])}
        else:
            env = {}
        if self.doc.env.execute(cmd, env):
            msg.error(_("could not make index %s") % self.target)
            return False

        self.doc.must_compile = 1
        return True
Пример #27
0
 def do_setlist(self, args):
     if len(args) == 0:
         raise rubber.SyntaxError(
             _("invalid syntax for directive '%s'") % cmd)
     name, val = args[0], args[1:]
     if name in ('arguments', ):
         self.arguments.extend(val)
     else:
         msg.warning(
             rubber.util._format(self.vars,
                                 _("unknown list variable: %s") % name))
Пример #28
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 True
		if not self.run_needed():
			return True

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

		if self.tool == "makeindex":
			cmd = ["makeindex", "-q", "-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: ':'.join(self.path + [os.getenv(path_var, '')]) }
		else:
			env = {}
		if self.doc.env.execute(cmd, env):
			msg.error(_("could not make index %s") % self.target)
			return False

		self.doc.must_compile = 1
		return True
Пример #29
0
	def convert (self, target, prefixes=[""], suffixes=[""], check=None, context=None):
		"""
		Use conversion rules to make a dependency tree for a given target
		file, and return the final node, or None if the file does not exist
		and cannot be built. The optional arguments 'prefixes' and 'suffixes'
		are lists of strings that can be added at the beginning and the end of
		the name when searching for the file. Prefixes are tried in order, and
		for each prefix, suffixes are tried in order; the first file from this
		order that exists or can be made is kept. The optional arguments
		'check' and 'context' have the same meaning as in
		'Converter.best_rule'.
		"""
		# Try all suffixes and prefixes until something is found.

		last = None
		for t in [p + target + s for s in suffixes for p in prefixes]:

			# Define a check function, according to preferences.

			if self.conv_prefs.has_key(t):
				prefs = self.conv_prefs[t]
				def do_check (vars, prefs=prefs):
					if prefs is not None:
						for key, val in prefs.items():
							if not (vars.has_key(key) and vars[key] == val):
								return 0
					return 1
			else:
				prefs = None
				do_check = check

			# Find the best applicable rule.

			ans = self.converter.best_rule(t, check=do_check, context=context)
			if ans is not None:
				if last is None or ans["cost"] < last["cost"]:
					last = ans

			# Check if the target exists.

			if prefs is None and os.path.exists(t):
				if last is not None and last["cost"] <= 0:
					break
				msg.log(_("`%s' is `%s', no rule applied") % (target, t))
				return rubber.depend.Leaf(self.depends, t)

		if last is None:
			return None
		msg.log(_("`%s' is `%s', made from `%s' by rule `%s'") %
				(target, last["target"], last["source"], last["name"]))
		return self.converter.apply(last)
Пример #30
0
 def do_rules(self, args):
     if len(args) != 1:
         raise rubber.SyntaxError(
             rubber.util._format(
                 self.vars,
                 _("invalid syntax for directive '%s'") % cmd))
     file = args[0]
     name = self.env.find_file(file)
     if name is None:
         msg.warning(
             rubber.util._format(self.vars,
                                 _("cannot read rule file %s") % file))
     else:
         self.env.converter.read_ini(name)
Пример #31
0
    def real_make(self, force):
        rv = UNCHANGED
        patience = 5
        primary_product = self.products[0]
        msg.debug(_("make %s -> %s") % (primary_product, str(self.sources)), pkg="depend")
        while patience > 0:
            # make our sources
            for source_name in self.sources:
                source = self.set[source_name]
                if source.making:
                    # cyclic dependency -- drop for now, we will re-visit
                    # this would happen while trying to remake the .aux in order to make the .bbl, for example
                    msg.debug(
                        _("while making %s: cyclic dependency on %s (pruned)") % (primary_product, source_name),
                        pkg="depend",
                    )
                    continue
                source_rv = source.make(force)
                if source_rv == ERROR:
                    self.failed_dep = source.failed_dep
                    msg.debug(
                        _("while making %s: dependency %s could not be made") % (primary_product, source_name),
                        pkg="depend",
                    )
                    return ERROR
                elif source_rv == CHANGED:
                    rv = CHANGED

            must_make = force or self.should_make()
            if not must_make:
                return rv

                # record MD5 hash of source files as we now actually start the build
            for source_name in self.md5_for_source.keys():
                self.md5_for_source[source_name] = rubber.util.md5_file(source_name)

                # actually make
            if not self.run():
                self.failed_dep = self
                return ERROR

            self.date = time.time()
            rv = CHANGED
            force = False

            patience -= 1

        self.failed_dep = self
        msg.error(_("while making %s: file contents does not seem to settle") % self.products[0], pkg="depend")
        return ERROR
Пример #32
0
	def main (self, cmdline):
		self.env = Environment()
		self.prologue = []
		self.epilogue = []

		self.act = None
		args = self.parse_opts(cmdline)
		if not self.act: self.act = "check"

		msg.log(_(
			"This is Rubber's information extractor version %s.") % version)

		if len(args) != 1:
			sys.stderr.write(_("You must specify one source file.\n"))
			sys.exit(1)

		src = args[0]
		if self.env.set_source(src):
			sys.stderr.write(_("I cannot find %s.\n") % src)
			sys.exit(1)

		if self.act == "deps":
			self.prepare(src)
			deps = {}
			for dep in self.env.main.source_nodes():
				for file in dep.leaves():
					deps[file] = None
			print(' '.join(deps.keys()))

		elif self.act == "rules":
			self.prepare(src)
			seen = {}
			next_ = [self.env.final]
			while len(next_) > 0:
				node = next_[0]
				next_ = next_[1:]
				if seen.has_key(node):
					continue
				seen[node] = None
				if len(node.sources) == 0:
					continue
				print("\n%s:" %  ' '.join(node.products), end=',')
				print(' '.join(node.sources))
				next_.extend(node.source_nodes())
		else:
			self.prepare(src, parse=0)
			return self.info_log(self.act)

		return 0
Пример #33
0
    def main(self, cmdline):
        self.env = Environment()
        self.prologue = []
        self.epilogue = []

        self.act = None
        args = self.parse_opts(cmdline)
        if not self.act: self.act = "check"

        msg.log(
            _("This is Rubber's information extractor version %s.") % version)

        if len(args) != 1:
            sys.stderr.write(_("You must specify one source file.\n"))
            sys.exit(1)

        src = args[0]
        if self.env.set_source(src):
            sys.stderr.write(_("I cannot find %s.\n") % src)
            sys.exit(1)

        if self.act == "deps":
            self.prepare(src)
            deps = {}
            for dep in self.env.main.source_nodes():
                for file in dep.leaves():
                    deps[file] = None
            print(' '.join(deps.keys()))

        elif self.act == "rules":
            self.prepare(src)
            seen = {}
            next_ = [self.env.final]
            while len(next_) > 0:
                node = next_[0]
                next_ = next_[1:]
                if seen.has_key(node):
                    continue
                seen[node] = None
                if len(node.sources) == 0:
                    continue
                print("\n%s:" % ' '.join(node.products), end=',')
                print(' '.join(node.sources))
                next_.extend(node.source_nodes())
        else:
            self.prepare(src, parse=0)
            return self.info_log(self.act)

        return 0
Пример #34
0
 def do_make(self, args):
     if len(args) % 2 != 1:
         raise rubber.SyntaxError(
             _("invalid syntax for directive '%s'") % "make")
     file = args[0]
     vars = {"target": file}
     for i in range(1, len(args), 2):
         if args[i] == "from":
             vars["source"] = args[i + 1]
         elif args[i] == "with":
             vars["name"] = args[1 + 1]
         else:
             raise rubber.SyntaxError(
                 _("invalid syntax for directive '%s'") % "make")
     self.env.conv_set(file, vars)
Пример #35
0
    def run(self):
        # command might have been updated in the mean time, so get it now
        self.environ["BIBINPUTS"] = ":".join(self.bib_paths)
        self.environ["BSTINPUTS"] = ":".join(self.bst_paths)
        command = self.build_command()

        msg.info(_("running: %s") % " ".join(command))
        process = subprocess.Popen(command,
                                   stdin=subprocess.DEVNULL,
                                   stdout=subprocess.DEVNULL,
                                   env=self.environ)
        if process.wait() != 0:
            msg.error(_("There were errors running %s.") % self.tool)
            return False
        return True
Пример #36
0
    def get_errors(self):
        """
		Read the log file, identify error messages and report them.
		"""
        if self.tool != "biber":
            # we re-use the BibTeX support in superclass
            for error in super(BibLaTeXDep, self).get_errors():
                yield error
            return

        current_bib = None

        try:
            log = open(self.blg, "r")
        except:
            msg.warn(_("cannot open Biber logfile: %s") % self.blg, pkg="biblatex")
            return

        with log:
            for line in log:
                m = re_updatefile.match(line)
                if m:
                    current_bib = m.group("filename")
                m = re_error.match(line)
                if m:
                    d = {"pkg": "biber"}
                    d["kind"] = biber_to_rubber[m.group("kind")]
                    if current_bib:
                        d["file"] = current_bib
                    d["line"] = int(m.group("line"))
                    d["text"] = m.group("text")
                    yield d
Пример #37
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)
Пример #38
0
    def set_source (self, name, jobname=None):
        """
        Create a main dependency node from the given file name. If this name
        has an extension that is known of a preprocessor, this preprocessor is
        used, otherwise the name is that of a LaTeX source.
        """
        path = self.find_file(name, ".tex")
        if not path:
            msg.error(_("cannot find %s") % name)
            return 1

        base,ext = os.path.splitext(path)

        if ext in literate_preprocessors.keys():
            src = base + ".tex"
            self.src_node = literate_preprocessors[ext](self.depends, src, path)
        else:
            src = path
            self.src_node = None

        from rubber.converters.latex import LaTeXDep
        self.main = LaTeXDep(self)
        if os.path.exists(src):
            if self.main.set_source(src, jobname):
                return 1
        self.final = self.main
        return 0
Пример #39
0
 def run (self):
     source = self.sources [0]
     if not os.path.exists (source):
         msg.info(_("{} not yet generated").format (msg.simplify (source)),
                  pkg="asymptote")
         return True
     os.rename (self.aux, self.bak)
     msg.log (_ ("saving {} to {}").format (msg.simplify (self.aux),
                                            msg.simplify (self.bak)),
              pkg="asymptote")
     ret = super (Shell_Restoring_Aux, self).run ()
     msg.log (_ ("restoring {} to {}").format (msg.simplify (self.aux),
                                               msg.simplify (self.bak)),
             pkg="asymptote")
     os.rename (self.bak, self.aux)
     return ret
Пример #40
0
	def help (self):
		sys.stderr.write (_("""\
This is Rubber version %s.
usage: rubber-pipe [options]
available options:
  -b, --bzip2              compress the final document with bzip2
  -c, --command=CMD        run the directive CMD before parsing (see man page)
  -e, --epilogue=CMD       run the directive CMD after parsing
  -z, --gzip               compress the final document
  -h, --help               display this help
      --into=DIR           go to directory DIR before compiling
  -k, --keep               keep the temporary files after compiling
  -n, --maxerr=NUM         display at most NUM errors (default: 10)
  -m, --module=MOD[:OPTS]  use module MOD (with options OPTS)
      --only=SOURCES       only include the specified SOURCES
  -o, --post=MOD[:OPTS]    postprocess with module MOD (with options OPTS)
  -d, --pdf                produce a pdf (synonym for -m pdftex or -o ps2pdf)
  -p, --ps                 process through dvips (synonym for -m dvips)
  -q, --quiet              suppress messages
  -r, --read=FILE          read additional directives from FILE
  -S, --src-specials       enable insertion of source specials
  -s, --short              display errors in a compact form
  -I, --texpath=DIR        add DIR to the search path for LaTeX
  -v, --verbose            increase verbosity
      --version            print version information and exit
""") % rubber_version)
Пример #41
0
 def do_shell_escape(self, args):
     if len(args) != 0:
         raise rubber.SyntaxError(
             rubber.util._format(
                 self.vars,
                 _("invalid syntax for directive '%s'") % cmd))
     self.env.doc_requires_shell_ = True
Пример #42
0
	def help (self):
		"""
		Display the description of all the options and exit.
		"""
		sys.stderr.write (_("""\
This is Rubber version %s.
usage: rubber [options] sources...
available options:
  -b, --bzip2              compress the final document with bzip2
      --clean              remove produced files instead of compiling
  -c, --command=CMD        run the directive CMD before parsing (see man page)
  -e, --epilogue=CMD       run the directive CMD after parsing
  -f, --force              force at least one compilation
  -z, --gzip               compress the final document
  -h, --help               display this help
      --inplace            compile the documents from their source directory
      --into=DIR           go to directory DIR before compiling
      --jobname=NAME       set the job name for the first target
  -n, --maxerr=NUM         display at most NUM errors (default: 10)
  -m, --module=MOD[:OPTS]  use module MOD (with options OPTS)
      --only=SOURCES       only include the specified SOURCES
  -o, --post=MOD[:OPTS]    postprocess with module MOD (with options OPTS)
  -d, --pdf                produce a pdf (synonym for -m pdftex or -o ps2pdf)
  -p, --ps                 process through dvips (synonym for -o dvips)
  -q, --quiet              suppress messages
  -r, --read=FILE          read additional directives from FILE
  -S, --src-specials       enable insertion of source specials
      --synctex            enable SyncTeX support
      --unsafe             permits the document to run external commands
  -s, --short              display errors in a compact form
  -I, --texpath=DIR        add DIR to the search path for LaTeX
  -v, --verbose            increase verbosity
      --version            print version information and exit
  -W, --warn=TYPE          report warnings of the given TYPE (see man page)
""") % rubber.version.version)
Пример #43
0
	def clean (self):
		"""
		Remove all generated files related to the index.
		"""
		for file in self.source, self.target, self.transcript:
			if os.path.exists(file):
				msg.log(_("removing %s") % file, pkg="index")
				os.unlink(file)
Пример #44
0
    def add_bib_resource(self, doc, opt, name):
        msg.log(_("bibliography resource discovered: %s" % name), pkg="biblio")
        options = rubber.util.parse_keyval(opt)

        # If the file name looks like it contains a control sequence
        # or a macro argument, forget about this resource.
        if name.find("\\") > 0 or name.find("#") > 0:
            return

            # skip Biber remote resources
        if "location" in options and options["location"] == "remote":
            return

        filename = self.find_bib(name)
        if filename is None:
            msg.error(_("cannot find bibliography resource %s") % name, pkg="biblatex")
        else:
            self.add_source(filename)
Пример #45
0
	def short_help (self):
		"""
		Display a short description of the command line.
		"""
		sys.stderr.write (_("""\
usage: rubber [options] sources...
For more information, try `rubber --help'.
"""))
		rubber.util.abort_rubber_syntax_error ()
Пример #46
0
	def __call__ (self, cmdline):
		if cmdline == []:
			self.short_help()
			return 1
		try:
			self.main(cmdline)
		except KeyboardInterrupt:
			msg(0, _("*** interrupted"))
			return 2
Пример #47
0
	def run (self):
		"""
		Run Metapost from the source file's directory, so that figures are put
		next to their source file.
		"""
		msg.progress(_("running Metapost on %s") %
				msg.simplify(self.base + ".mp"))
		if self.env.execute (self.cmd, self.penv, pwd=self.cmd_pwd) == 0:
			return True

		# This creates a log file that has the same aspect as TeX logs.

		self.log = MPLogCheck(self.cmd_pwd)
		if not self.log.readlog (self.base + ".log", metapost_logfile_limit):
			msg.error(_(
				"I can't read MetaPost's log file, this is wrong."))
			return False
		return not self.log.errors()
Пример #48
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 not os.path.exists(self.target):
			self.md5 = md5_file(self.source)
			return 1
		if not self.md5:
			self.md5 = md5_file(self.source)
			msg.log(_("the index file %s is new") % self.source, pkg="index")
			return 1
		new = md5_file(self.source)
		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
Пример #49
0
	def __call__ (self, cmdline):
		"""
		This method is a wrapper around the main method,
		catching the keyboard interruption signal.
		"""
		try:
			self.main (cmdline)
			assert False
		except KeyboardInterrupt:
			msg(0, _("*** interrupted"))
			rubber.util.abort_generic_error ()
Пример #50
0
			def parse_kpse ():
				for line in process.stderr.readlines():
					line = line.rstrip()
					match = re_kpse.match(line)
					if not match:
						continue
					cmd = match.group("cmd")
					if self.kpse_msg.has_key(cmd):
						msg.progress(match.expand(self.kpse_msg[cmd]))
					else:
						msg.progress(_("kpathsea running %s") % cmd)
Пример #51
0
	def clean (self):
		"""
		Remove the files produced by this rule and recursively clean all
		dependencies.
		"""
		for file in self.products:
			if os.path.exists(file):
				msg.log(_("removing %s") % file)
				os.unlink(file)
		for source in self.source_nodes():
			source.clean()
		self.date = None
Пример #52
0
	def execute (self, prog, env={}, pwd=None, out=None):
		"""
		Silently execute an external program. The `prog' argument is the list
		of arguments for the program, `prog[0]' is the program name. The `env'
		argument is a dictionary with definitions that should be added to the
		environment when running the program. The standard output is passed
		line by line to the `out' function (or discarded by default).
		"""
		msg.info(_("executing: %s") % string.join(prog))
		if pwd:
			msg.log(_("  in directory %s") % pwd)
		if env != {}:
			msg.log(_("  with environment: %r") % env)

		progname = prog_available(prog[0])
		if not progname:
			msg.error(_("%s not found") % prog[0])
			return 1

		penv = os.environ.copy()
		for (key,val) in env.items():
			penv[key] = val

		process = Popen(prog,
			executable = progname,
			env = penv,
			cwd = pwd,
			stdin = devnull(),
			stdout = subprocess.PIPE,
			stderr = None)

		if out is not None:
			for line in process.stdout:
				out(line)
		else:
			process.stdout.readlines()

		ret = process.wait()
		msg.log(_("process %d (%s) returned %d") % (process.pid, prog[0],ret))
		return ret
Пример #53
0
	def build (self, env):
		"""
		Build the final product.
		"""
		srcname = env.main.sources[0]
		# FIXME unindent, untangle
		if True:
			if self.force:
				ret = env.main.make(True)
				if ret != ERROR and env.final is not env.main:
					ret = env.final.make()
				else:
					# This is a hack for the call to get_errors() below
					# to work when compiling failed when using -f.
					env.final.failed_dep = env.main.failed_dep
			else:
				ret = env.final.make(self.force)

			if ret == ERROR:
				msg.info(_("There were errors compiling %s.") % srcname)
				number = self.max_errors
				for err in env.final.failed().get_errors():
					if number == 0:
						msg.info(_("More errors."))
						break
					msg.display(**err)
					number -= 1
				rubber.util.abort_generic_error ()

			if ret == UNCHANGED:
				msg(1, _("nothing to be done for %s") % srcname)

			if self.warn:
				# FIXME
				log = env.main.log
				if not env.main.parse_log ():
					msg.error(_("cannot read the log file"))
					return 1
				msg.display_all(log.parse(boxes=self.warn_boxes,
					refs=self.warn_refs, warnings=self.warn_misc))
Пример #54
0
 def __init__ (self, document, context):
     env = document.env
     if env.final.products[0][-3:] != '.ps':
          msg.error(_("I can't use ps2pdf when not producing a PS"))
          rubber.util.abort_generic_error ()
     ps = env.final.products[0]
     pdf = ps[:-2] + 'pdf'
     cmd = ['ps2pdf']
     cmd.extend([ps, pdf])
     dep = Shell (env.depends, cmd)
     dep.add_product (pdf)
     dep.add_source (ps)
     env.final = dep
Пример #55
0
	def prepare_source (self, filename):
		"""
		Dump the standard input in a file, and set up that file
		the same way we would normally process LaTeX sources.
		"""
		assert filename.endswith ("-")  # filename is ignored

		try:
			# Make a temporary on-disk copy of the standard input,
			# in the current working directory.
			# The name will have the form "rubtmpXXX.tex.
			with tempfile.NamedTemporaryFile (suffix='.tex', prefix='rubtmp', dir='.', delete=False) as srcfile:
				# note the tempfile name so we can remove it later
				self.pipe_tempfile = srcfile.name
				# copy stdin into the tempfile
				msg.progress (_("saving the input in %s") % self.pipe_tempfile)
				shutil.copyfileobj (sys.stdin, srcfile)
		except IOError:
			msg.error (_("cannot create temporary file for the main LaTeX source"))
			rubber.util.abort_generic_error ()

		return super (Pipe, self).prepare_source (self.pipe_tempfile)
Пример #56
0
	def __init__ (self, cwd=None):
		"""
		Initialize the environment. The optional argument is the path to the
		reference directory for compilation, by default it is the current
		working directory.
		"""
		self.kpse_msg = {
			"mktextfm" : _("making font metrics for \\g<arg>"),
			"mktexmf" : _("making font \\g<arg>"),
			"mktexpk" : _("making bitmap for font \\g<arg>")
			}

		if cwd is None: cwd = os.getcwd()
		self.vars = Variables(items = { 'cwd': cwd, '_environment': self })
		self.path = [cwd]
		self.conv_prefs = {}
		self.depends = rubber.depend.Set()
		self.converter = Converter(self.depends)
		self.converter.read_ini(os.path.join(moddir, 'rules.ini'))
		
		self.main = None
		self.final = None
Пример #57
0
	def prepare_source (self, filename):
		"""
		Prepare the dependency node for the main LaTeX run.
		Returns the filename of the main LaTeX source file, which might
		change for various reasons (adding a .tex suffix; preprocessors;
		pipe dumping).
		When this is done, the file must exist on disk, otherwise this
		function must exit(1) or exit(2).
		"""
		path = rubber.util.find_resource (filename, suffix=".tex")

		if not path:
			msg.error (_("Main document not found: '%s'") % filename)
			rubber.util.abort_generic_error ()

		base, ext = os.path.splitext (path)

		from rubber.converters.literate import literate_preprocessors as lpp
		if ext in lpp.keys ():
			src = base + ".tex"
			# FIXME kill src_node
			src_node = lpp[ext] (self.env.depends, src, path)
			if self.rubber_mode == "build":
				if not self.unsafe:
					msg.error (_("Running external commands requires --unsafe."))
					rubber.util.abort_rubber_syntax_error ()
				# Produce the source from its dependency rules, if needed.
				if src_node.make () == ERROR:
					msg.error (_("Producing the main LaTeX file failed: '%s'") \
						% src)
					rubber.util.abort_generic_error ()
		else:
			src = path

		from rubber.converters.latex import LaTeXDep
		self.env.final = self.env.main = LaTeXDep (self.env, src, self.jobname)

		return src
Пример #58
0
	def run (self):
		if not os.path.exists (self.cmd [1]):
			msg.info (_ ("%s not yet generated" % self.cmd [1]))
			return True

		# No more settings are expected, we compute the
		# command once and for all.
		if self.command_env == None:
			if self.cmd [0] == "makeindex":
				self.cmd.extend (self.opts)
				if self.style:
					self.cmd.extend (["-s", self.style])
				path_var = "INDEXSTYLE"
			else:   # self.cmd [0] == "texindy"
				for opt in self.opts:
					if opt == "-g":
						if self.lang != "":
							msg.warn(_("'language' overrides 'order german'"),
								 pkg="index")
						else:
							self.lang = "german-din"
					else: # opt == "-l"
						self.modules.append("letter-ordering")
						msg.warn(_("use 'module letter-ordering' instead of 'order letter'"),
							 pkg="index")
				for mod in self.modules:
					self.cmd.extend(["--module", mod])
				if self.lang:
					self.cmd.extend(["--language", self.lang])
				path_var = "XINDY_SEARCHPATH"

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

		# The actual run.
		return self.doc.env.execute(self.cmd, self.command_env) == 0
Пример #59
0
	def set_source (self, name, jobname=None):
		"""
		Create a main dependency node from the given file name. If this name
		has an extension that is known of a preprocessor, this preprocessor is
		used, otherwise the name is that of a LaTeX source.
		"""
		src = None
		i = name.rfind(".")
		if i >= 0:
			ext = name[i+1:]
			if ext in ["w", "lhs"]:
				path = self.find_file(name)
				if not path:
					msg.error(_("cannot find %s") % name)
					return 1
				src = path[:-len(ext)] + "tex"
				if ext == "w":
					from rubber.converters.cweb import CWebDep
					self.src_node = CWebDep(self, src, path)
				elif ext == "lhs":
					from rubber.converters.lhs2TeX import LHSDep
					self.src_node = LHSDep(self, src, path)

		if src is None:
			path = self.find_file(name, ".tex")
			if not path:
				msg.error(_("cannot find %s") % name)
				return 1
			src = path
			self.src_node = None

		from rubber.converters.latex import LaTeXDep
		self.main = LaTeXDep(self)
		if os.path.exists(src):
			if self.main.set_source(src, jobname):
				return 1
		self.final = self.main
		return 0
Пример #60
0
    def __init__(self, document, context):
        doc = document

        options = rubber.util.parse_keyval(context["opt"])
        backend = options.setdefault("backend", "biber")

        if backend not in ("biber", "bibtex", "bibtex8", "bibtexu"):
            msg.error(_("Garbled biblatex backend: backend=%s (aborting)") % backend)
            rubber.util.abort_generic_error()  # abort rather than guess

        self.dep = BibLaTeXDep(doc, backend)
        doc.hook_macro("bibliography", "a", self.dep.add_bibliography)

        # overwrite the hook which would load the bibtex module
        doc.hook_macro("bibliographystyle", "a", self.dep.bibliographystyle)