diff --git a/conservancy_beancount/cliutil.py b/conservancy_beancount/cliutil.py index 40f5190646d5cf84707af8bc237d276fde98630c..ec44ab06da57cca5b4848171a07c1f135edfc192 100644 --- a/conservancy_beancount/cliutil.py +++ b/conservancy_beancount/cliutil.py @@ -28,8 +28,10 @@ import types from pathlib import Path import rt.exceptions as rt_error +import yaml from . import data +from . import errors from . import filters from . import rtutil @@ -148,6 +150,11 @@ class ExceptHook: elif isinstance(exc_value, rt_error.RtError): exitcode = os.EX_UNAVAILABLE error_type = f"RT {error_type}" + elif isinstance(exc_value, errors.RewriteRuleError): + exitcode = ExitCode.RewriteRulesError + msg = str(exc_value) + if exc_value.source is not None: + msg += f"\n\n source: {yaml.safe_dump(exc_value.source)}" elif isinstance(exc_value, OSError): if exc_value.filename is None: exitcode = os.EX_OSERR diff --git a/tests/test_cliutil.py b/tests/test_cliutil.py index de95f1150f1488a75bb21da57883589dad3f2403..b4013b6777c1d5c3a8ade47e1c5dc10aed736c19 100644 --- a/tests/test_cliutil.py +++ b/tests/test_cliutil.py @@ -1,5 +1,5 @@ """Test CLI utilities""" -# Copyright © 2020 Brett Smith +# Copyright © 2020, 2021 Brett Smith # License: AGPLv3-or-later WITH Beancount-Plugin-Additional-Permission-1.0 # # Full copyright and licensing details can be found at toplevel file @@ -23,7 +23,7 @@ from pathlib import Path from . import testutil -from conservancy_beancount import cliutil +from conservancy_beancount import cliutil, errors FILE_NAMES = ['-foobar', '-foo.bin'] STREAM_PATHS = [None, Path('-')] @@ -163,6 +163,25 @@ def test_excepthook_oserror(errnum, caplog): assert log.levelname == 'CRITICAL' assert log.message == f"I/O error: {error.filename}: {error.strerror}" +@pytest.mark.parametrize('errcls', [ + errors.RewriteRuleActionError, + errors.RewriteRuleConditionError, + errors.RewriteRuleLoadError, + errors.RewriteRuleValidationError, +]) +def test_excepthook_rewrite_rule_error(errcls, caplog): + name = errcls.__name__ + error = errcls("bad rewrite rule", f"{name}.yml", 170, [name]) + with pytest.raises(SystemExit) as exc_check: + cliutil.ExceptHook()(type(error), error, None) + assert exc_check.value.args[0] == cliutil.ExitCode.RewriteRulesError + assert caplog.records + for log in caplog.records: + assert log.levelname == 'CRITICAL' + lines = log.message.splitlines() + assert lines[0].startswith(f"{name}: bad rewrite rule in {name}.yml rule #170") + assert re.match(rf' source:\W+{name}\b', lines[-1]) + @pytest.mark.parametrize('exc_type', [ AttributeError, RuntimeError,