From 829989364aeaece2fa6a36716571c01d11f7a322 Mon Sep 17 00:00:00 2001 From: Louis Date: Tue, 9 Feb 2016 17:42:13 +0100 Subject: [PATCH] [songbook] Add option --error Closes #123 --- patacrep/build.py | 5 +++++ patacrep/content/song.py | 18 +++++++++++++++++- patacrep/errors.py | 10 +++++----- patacrep/songbook/__main__.py | 20 ++++++++++++++++++++ 4 files changed, 47 insertions(+), 6 deletions(-) diff --git a/patacrep/build.py b/patacrep/build.py index bf1e2918..f0b5f7d5 100644 --- a/patacrep/build.py +++ b/patacrep/build.py @@ -114,7 +114,12 @@ class Songbook: self._config['filename'] = output.name[:-4] renderer.render_tex(output, self._config) + + # Get all errors, and maybe exit program self._errors.extend(renderer.errors) + if self.config['_error'] == "failonbook": + if self.has_errors(): + raise errors.SongbookError("Some songs contain errors. Stopping as requested.") def has_errors(self): """Return `True` iff errors have been encountered in the book. diff --git a/patacrep/content/song.py b/patacrep/content/song.py index 8e9519dc..71a399ba 100755 --- a/patacrep/content/song.py +++ b/patacrep/content/song.py @@ -24,6 +24,12 @@ class SongRenderer(ContentItem): """Iterate over song errors.""" yield from self.song.errors + def has_errors(self): + """Return `True` iff errors has been found.""" + for _ in self.iter_errors(): + return True + return False + def begin_new_block(self, previous, __context): """Return a boolean stating if a new block is to be created.""" return not isinstance(previous, SongRenderer) @@ -57,7 +63,7 @@ class SongRenderer(ContentItem): """Order by song path""" return self.song.fullpath < other.song.fullpath -#pylint: disable=unused-argument +#pylint: disable=unused-argument, too-many-branches def parse(keyword, argument, contentlist, config): """Parse data associated with keyword 'song'. @@ -107,7 +113,17 @@ def parse(keyword, argument, contentlist, config): )) except ContentError as error: songlist.append_error(error) + if config['_error'] == "failonsong": + raise errors.SongbookError( + "Error in song '{}'. Stopping as requested." + .format(os.path.join(songdir.fullpath, filename)) + ) continue + if renderer.has_errors() and config['_error'] == "failonsong": + raise errors.SongbookError( + "Error in song '{}'. Stopping as requested." + .format(os.path.join(songdir.fullpath, filename)) + ) songlist.append(renderer) config["_langs"].add(renderer.song.lang) if len(songlist) > before: diff --git a/patacrep/errors.py b/patacrep/errors.py index c111ca3b..19c92087 100644 --- a/patacrep/errors.py +++ b/patacrep/errors.py @@ -5,11 +5,6 @@ class SongbookError(Exception): Songbook errors should inherit from this one. """ - pass - -class YAMLError(SongbookError): - """Error during songbook file decoding""" - def __init__(self, message=None): super().__init__() self.message = message @@ -17,6 +12,11 @@ class YAMLError(SongbookError): def __str__(self): return self.message + +class YAMLError(SongbookError): + """Error during songbook file decoding""" + pass + class TemplateError(SongbookError): """Error during template generation""" diff --git a/patacrep/songbook/__main__.py b/patacrep/songbook/__main__.py index 9de2a520..33cabee7 100644 --- a/patacrep/songbook/__main__.py +++ b/patacrep/songbook/__main__.py @@ -86,6 +86,25 @@ def argument_parser(args): default=[True], ) + parser.add_argument( + '--error', '-e', nargs=1, + help=textwrap.dedent("""\ + By default, this program tries hard to fix or ignore song and book errors. This option changes this behaviour: + - failonsong: stop as soon as a song contains (at least) one error; + - failonbook: stop when all the songs have been parsed and rendered, if any error was met; + - fix: tries to fix (or ignore) errors. + + Note that compilation *may* fail even with `--error=fix`. + """), + type=str, + choices=[ + "failonsong", + "failonbook", + "fix", + ], + default=["fix"], + ) + parser.add_argument( '--steps', '-s', nargs=1, type=str, action=ParseStepsAction, @@ -127,6 +146,7 @@ def main(args): for datadir in reversed(options.datadir): songbook['datadir'].insert(0, datadir) songbook['_cache'] = options.cache[0] + songbook['_error'] = options.error[0] sb_builder = SongbookBuilder(songbook) sb_builder.unsafe = True