some better error handling

This commit is contained in:
Maximilian Keßler 2022-02-17 23:16:41 +01:00
parent 8ad8366158
commit 75e705c810
3 changed files with 67 additions and 19 deletions

View file

@ -1,6 +1,27 @@
from typing import Optional
class PyTeXError(Exception):
pass
def __init__(self, msg, explanation: Optional[str] = None):
self._msg = msg
self._traceback_explanation = []
if explanation is not None:
self._traceback_explanation.append(explanation)
super().__init__(self._dispstr())
def _dispstr(self):
depth = 0
ret = [self._msg]
for explanation in self._traceback_explanation:
ret.append(' ' * 2 * depth + explanation)
depth += 1
return '\n'.join(ret)
def add_explanation(self, explanation: str):
self._traceback_explanation.append(explanation)
def __str__(self):
return self._dispstr()
class PyTeXFormattingError(PyTeXError):

View file

@ -158,7 +158,9 @@ class MacroCodeBeginMacro(SingleLineMacro):
def _apply(self, line: str, formatter) -> Union[str, List[str]]:
if not formatter.mode == FormatterMode.meta:
raise PyTeXInvalidBeginMacroCodeUsageError
raise PyTeXInvalidBeginMacroCodeUsageError(
r"\begin{macrocode} used outside meta context"
)
formatter.mode = FormatterMode.macrocode
return r'% \begin{macrocode}'
@ -169,7 +171,9 @@ class MacroCodeEndMacro(SingleLineMacro):
def _apply(self, line: str, formatter) -> Union[str, List[str]]:
if not formatter.mode == FormatterMode.macrocode:
raise PyTeXInvalidEndMacroCodeUsageError
raise PyTeXInvalidEndMacroCodeUsageError(
r"\end{macrocode} used outside macrocode context"
)
formatter.mode = FormatterMode.meta
return r'% \end{macrocode}'

View file

@ -7,6 +7,7 @@ from .macros import Macro
from .pytex_formatter import PyTeXFormatter
from .enums import *
from ..logger import logger
from .errors import *
class LineStream:
@ -15,6 +16,7 @@ class LineStream:
self._handle = open(filename, 'r')
self._cached_lines: List[str] = []
self._file_exhausted: bool = False
self._line_number: int = 0
def current_line(self):
return self.future_line(0)
@ -47,6 +49,7 @@ class LineStream:
self._cached_lines.append(
self._handle.readline()
)
self._line_number += 1
if self._cached_lines[-1] == '':
self._handle.close()
self._file_exhausted = True
@ -57,6 +60,10 @@ class LineStream:
b = len(self._cached_lines) == 0
return a & b
@property
def line_number(self) -> int:
return self._line_number
class TexFormatter(PyTeXFormatter, ABC):
def __init__(self, *args, **kwargs):
@ -102,13 +109,21 @@ class TexFormatter(PyTeXFormatter, ABC):
self._macros = macros
def _handle_macro(self, macro: Macro):
try:
replacement, shipout = macro.apply(
self.line_stream.current_line(),
self
)
except PyTeXMacroError as e:
e.add_explanation('While applying macro')
raise e
if shipout:
self.line_stream.pop_line()
if isinstance(replacement, str):
self._shipout_line(replacement)
else:
for line in replacement:
self._shipout_line(line)
else:
if isinstance(replacement, str):
self.line_stream.set_line(replacement)
@ -150,13 +165,13 @@ class TexFormatter(PyTeXFormatter, ABC):
def mode(self, mode: FormatterMode) -> None:
self._mode = mode
def _get_provides_text(self) -> str:
def _get_provides_text(self, provided_type: str) -> str:
if self.config.has_description:
if self.config.tex_flavour == TeXFlavour.LaTeX2e:
return \
r'\Provides%s{%s}[%s - %s]' \
% (
self.config.tex_type.value.capitalize(),
provided_type,
self.name,
self.attribute_dict[FormatterProperty.date.value],
self.attribute_dict[FormatterProperty.description.value]
@ -166,7 +181,7 @@ class TexFormatter(PyTeXFormatter, ABC):
return \
'\\ProvidesExpl%s { %s } { %s } { %s }\n { %s }' \
% (
self.config.tex_type.value.capitalize(),
provided_type,
self.name,
self.attribute_dict[FormatterProperty.date.value],
self.config.version,
@ -183,14 +198,22 @@ class TexFormatter(PyTeXFormatter, ABC):
def format_document(self) -> None:
while not self.line_stream.exhausted:
try:
recent_replacement = True
while recent_replacement:
recent_replacement = False
for macro in self.macros:
if macro.matches(self.line_stream.current_line()):
try:
self._handle_macro(macro)
except PyTeXMacroError as e:
e.add_explanation('while handling macro')
raise e
recent_replacement = True
break
except PyTeXMacroError as e:
e.add_explanation(f'in line {self.line_stream.line_number} ({self.line_stream.current_line().rstrip()})')
pass
self._shipout_line(self._post_process_line(
self.line_stream.pop_line()
))