diff --git a/import2ledger/hooks/ledger_entry.py b/import2ledger/hooks/ledger_entry.py index d5a6d97cdab024cb5c409c05912bd7c676f55d4c..17ff7f28b5ba72cef04d4fb2cbd8b589b1f6a56d 100644 --- a/import2ledger/hooks/ledger_entry.py +++ b/import2ledger/hooks/ledger_entry.py @@ -168,11 +168,17 @@ class AccountSplitter: def _build_amounts(self, template_vars): amount_vars = {k: v for k, v in template_vars.items() if isinstance(v, decimal.Decimal)} amount_vars['Decimal'] = decimal.Decimal - amounts = [ - (account, self._currency_decimal(eval(amount_expr, amount_vars), - template_vars['currency'])) - for account, amount_expr in self.splits - ] + try: + amounts = [ + (account, self._currency_decimal(eval(amount_expr, amount_vars), + template_vars['currency'])) + for account, amount_expr in self.splits + ] + except (ArithmeticError, NameError, TypeError, ValueError) as error: + raise errors.UserInputConfigurationError( + "{}: {}".format(type(error).__name__, error), + "template {!r}".format(self.template_name) + ) from error self._balance_amounts(amounts, template_vars['amount']) self._balance_amounts(amounts, -template_vars['amount']) return amounts diff --git a/tests/data/templates.ini b/tests/data/templates.ini index cf705446ddc283c644597acdee7108ece12f3c24..5b8ce60dcc93e80dbcdbf63120316b9b80f4ade0 100644 --- a/tests/data/templates.ini +++ b/tests/data/templates.ini @@ -53,6 +53,16 @@ template = Expenses:Banking Fees (6 if {amount} > 50 else 3) Income:Sales -{amount} +[NondecimalWord] +template = + Income:Sales -5 + Assets:Cash foo + +[NondecimalVariable] +template = + Income:Sales -5 + Assets:Cash {payee} + [Empty] template = diff --git a/tests/test_hook_ledger_entry.py b/tests/test_hook_ledger_entry.py index fd233929f040bb7dd62b843d2ee68ed4f38b1863..ffa723500d8da62fa56b18f09fd33cc08f527a40 100644 --- a/tests/test_hook_ledger_entry.py +++ b/tests/test_hook_ledger_entry.py @@ -259,3 +259,12 @@ def test_hook_handles_template_undefined(): entry_data = template_vars('DD', 1) assert not run_hook(entry_data, 'Nonexistent') +def test_string_value_is_user_error(): + entry_data = template_vars('EE', 1) + with pytest.raises(errors.UserInputConfigurationError): + run_hook(entry_data, 'NondecimalWord') + +def test_string_variable_is_user_error(): + entry_data = template_vars('FF', 1) + with pytest.raises(errors.UserInputConfigurationError): + run_hook(entry_data, 'NondecimalVariable')