# This file is part of Rubber and thus covered by the GPL
# (c) Emmanuel Beffara, 2002--2006
"""
This module defines the messages diplay class, and creates the application-wide
msg object.
"""
from __future__ import print_function
import os, os.path
import sys
import logging
from io import open
def _(txt): return txt
class Message (object):
"""
All messages in the program are output using the `msg' object in the
main package. This class defines the interface for this object.
"""
def __init__ (self, level=1, write=None):
"""
Initialize the object with the specified verbosity level and an
optional writing function. If no such function is specified, no
message will be output until the 'write' field is changed.
"""
self.level = level
self.write = self.write_stdout
if write:
self.write = write
self.short = 0
self.path = ""
self.cwd = "./"
self.pos = []
self._log = logging.getLogger("dblatex")
level = self._log.getEffectiveLevel()
if level >= logging.WARNING:
self.stdout = open(os.devnull, "wb")
else:
self.stdout = None
def write_stdout(self, text, level=0):
print(text)
def write_stderr(self, text, level=0):
print(text, file=sys.stderr)
def push_pos (self, pos):
self.pos.append(pos)
def pop_pos (self):
del self.pos[-1]
def __call__ (self, level, text):
"""
This is the low level printing function, it receives a line of text
with an associated verbosity level, so that output can be filtered
depending on command-line options.
"""
if self.write and level <= self.level:
self.write(text, level=level)
def display (self, 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:]
self._log.error(self.format_pos(info, text))
if "code" in info and info["code"] and not self.short:
self._log.error(self.format_pos(info,
_("leading text: ") + info["code"]))
elif kind == "abort":
if self.short:
msg = _("compilation aborted ") + info["why"]
else:
msg = _("compilation aborted: %s %s") % (text, info["why"])
self._log.error(self.format_pos(info, msg))
# elif kind == "warning":
# self._log.warning(self.format_pos(info, text))
def error (self, text, **info):
self.display(kind="error", text=text, **info)
def warn (self, what, **where):
self._log.warning(self.format_pos(where, what))
def progress (self, what, **where):
self._log.info(self.format_pos(where, what + "..."))
def info (self, what, **where):
self._log.info(self.format_pos(where, what))
def log (self, what, **where):
self._log.debug(self.format_pos(where, what))
def debug (self, what, **where):
self._log.debug(self.format_pos(where, what))
def format_pos (self, where, text):
"""
Format the given text into a proper error message, with file and line
information in the standard format. Position information is taken from
the dictionary given as first argument.
"""
if len(self.pos) > 0:
if where is None or "file" not in where:
where = self.pos[-1]
elif where is None or where == {}:
return text
if "file" in where and where["file"] is not None:
pos = self.simplify(where["file"])
if "line" in where and where["line"]:
pos = "%s:%d" % (pos, int(where["line"]))
if "last" in where:
if where["last"] != where["line"]:
pos = "%s-%d" % (pos, int(where["last"]))
pos = pos + ": "
else:
pos = ""
if "page" in where:
text = "%s (page %d)" % (text, int(where["page"]))
if "pkg" in where:
text = "[%s] %s" % (where["pkg"], text)
return pos + text
def simplify (self, name):
"""
Simplify an path name by removing the current directory if the
specified path is in a subdirectory.
"""
path = os.path.normpath(os.path.join(self.path, name))
if path[:len(self.cwd)] == self.cwd:
return path[len(self.cwd):]
return path
def display_all (self, generator, writer=None):
if writer:
write = self.write
self.write = writer
something = 0
for msg in generator:
self.display(**msg)
something = 1
if writer:
self.write = write
return something
msg = Message()