diff --git a/conservancy_beancount/plugin/__init__.py b/conservancy_beancount/plugin/__init__.py index 3c88423..cbcb880 100644 --- a/conservancy_beancount/plugin/__init__.py +++ b/conservancy_beancount/plugin/__init__.py @@ -86,8 +86,8 @@ def run(entries, options_map, config='', hook_registry=HOOK_REGISTRY): for hook in hooks[entry_type]: errors.extend(hook.run(entry)) if entry_type == 'Transaction': - for post in entry.postings: + for index, post in enumerate(entry.postings): for hook in hooks['Posting']: - errors.extend(hook.run(entry, post)) + errors.extend(hook.run(entry, post, index)) return entries, errors diff --git a/conservancy_beancount/plugin/core.py b/conservancy_beancount/plugin/core.py index fc8a130..ddf2437 100644 --- a/conservancy_beancount/plugin/core.py +++ b/conservancy_beancount/plugin/core.py @@ -132,10 +132,11 @@ class PostingChecker: except (KeyError, TypeError): return txn.meta.get(key, default) - def _meta_set(self, post, key, value): + def _meta_set(self, txn, post, post_index, key, value): if post.meta is None: - post.meta = {} - post.meta[key] = value + txn.postings[post_index] = Posting(*post[:5], {key: value}) + else: + post.meta[key] = value # If the posting does not specify METADATA_KEY, the hook calls # _default_value to get a default. This method should either return diff --git a/tests/test_meta_expenseAllocation.py b/tests/test_meta_expenseAllocation.py index 33240dc..2c01e41 100644 --- a/tests/test_meta_expenseAllocation.py +++ b/tests/test_meta_expenseAllocation.py @@ -42,7 +42,7 @@ def test_valid_values_on_postings(src_value, set_value): ('Expenses:General', 25, {'expenseAllocation': src_value}), ]) checker = meta_expense_allocation.MetaExpenseAllocation() - errors = checker.run(txn, txn.postings[-1]) + errors = checker.run(txn, txn.postings[-1], -1) assert not errors assert txn.postings[-1].meta.get('expenseAllocation') == set_value @@ -53,7 +53,7 @@ def test_invalid_values_on_postings(src_value): ('Expenses:General', 25, {'expenseAllocation': src_value}), ]) checker = meta_expense_allocation.MetaExpenseAllocation() - errors = checker.run(txn, txn.postings[-1]) + errors = checker.run(txn, txn.postings[-1], -1) assert errors @pytest.mark.parametrize('src_value,set_value', VALID_VALUES.items()) @@ -63,7 +63,7 @@ def test_valid_values_on_transactions(src_value, set_value): ('Expenses:General', 25), ]) checker = meta_expense_allocation.MetaExpenseAllocation() - errors = checker.run(txn, txn.postings[-1]) + errors = checker.run(txn, txn.postings[-1], -1) assert not errors assert txn.postings[-1].meta.get('expenseAllocation') == set_value @@ -74,7 +74,7 @@ def test_invalid_values_on_transactions(src_value): ('Expenses:General', 25), ]) checker = meta_expense_allocation.MetaExpenseAllocation() - errors = checker.run(txn, txn.postings[-1]) + errors = checker.run(txn, txn.postings[-1], -1) assert errors @pytest.mark.parametrize('account', [ @@ -90,7 +90,7 @@ def test_non_expense_accounts_skipped(account): ('Expenses:General', 25, {'expenseAllocation': 'program'}), ]) checker = meta_expense_allocation.MetaExpenseAllocation() - errors = checker.run(txn, txn.postings[0]) + errors = checker.run(txn, txn.postings[0], 0) assert not errors @pytest.mark.parametrize('account,set_value', [ @@ -106,7 +106,7 @@ def test_default_values(account, set_value): (account, 25), ]) checker = meta_expense_allocation.MetaExpenseAllocation() - errors = checker.run(txn, txn.postings[-1]) + errors = checker.run(txn, txn.postings[-1], -1) assert not errors assert txn.postings[-1].meta['expenseAllocation'] == set_value @@ -123,7 +123,7 @@ def test_default_value_set_in_date_range(date, set_value): ('Expenses:General', 25), ]) checker = meta_expense_allocation.MetaExpenseAllocation() - errors = checker.run(txn, txn.postings[-1]) + errors = checker.run(txn, txn.postings[-1], -1) assert not errors got_value = (txn.postings[-1].meta or {}).get('expenseAllocation') assert bool(got_value) == bool(set_value) diff --git a/tests/test_meta_taxImplication.py b/tests/test_meta_taxImplication.py index fe2a794..d745a16 100644 --- a/tests/test_meta_taxImplication.py +++ b/tests/test_meta_taxImplication.py @@ -54,7 +54,7 @@ def test_valid_values_on_postings(src_value, set_value): ('Assets:Cash', -25, {'taxImplication': src_value}), ]) checker = meta_tax_implication.MetaTaxImplication() - errors = checker.run(txn, txn.postings[-1]) + errors = checker.run(txn, txn.postings[-1], -1) assert not errors assert txn.postings[-1].meta.get('taxImplication') == set_value @@ -65,7 +65,7 @@ def test_invalid_values_on_postings(src_value): ('Assets:Cash', -25, {'taxImplication': src_value}), ]) checker = meta_tax_implication.MetaTaxImplication() - errors = checker.run(txn, txn.postings[-1]) + errors = checker.run(txn, txn.postings[-1], -1) assert errors @pytest.mark.parametrize('src_value,set_value', VALID_VALUES.items()) @@ -75,7 +75,7 @@ def test_valid_values_on_transactions(src_value, set_value): ('Assets:Cash', -25), ]) checker = meta_tax_implication.MetaTaxImplication() - errors = checker.run(txn, txn.postings[-1]) + errors = checker.run(txn, txn.postings[-1], -1) assert not errors assert txn.postings[-1].meta.get('taxImplication') == set_value @@ -86,7 +86,7 @@ def test_invalid_values_on_transactions(src_value): ('Assets:Cash', -25), ]) checker = meta_tax_implication.MetaTaxImplication() - errors = checker.run(txn, txn.postings[-1]) + errors = checker.run(txn, txn.postings[-1], -1) assert errors @pytest.mark.parametrize('account', [ @@ -100,7 +100,7 @@ def test_non_asset_accounts_skipped(account): ('Assets:Cash', -25, {'taxImplication': 'USA-Corporation'}), ]) checker = meta_tax_implication.MetaTaxImplication() - errors = checker.run(txn, txn.postings[0]) + errors = checker.run(txn, txn.postings[0], 0) assert not errors def test_asset_credits_skipped(): @@ -109,7 +109,7 @@ def test_asset_credits_skipped(): ('Assets:Cash', 25), ]) checker = meta_tax_implication.MetaTaxImplication() - errors = checker.run(txn, txn.postings[-1]) + errors = checker.run(txn, txn.postings[-1], -1) assert not errors assert not txn.postings[-1].meta @@ -126,5 +126,5 @@ def test_default_value_set_in_date_range(date, need_value): ('Assets:Cash', -25), ]) checker = meta_tax_implication.MetaTaxImplication() - errors = checker.run(txn, txn.postings[-1]) + errors = checker.run(txn, txn.postings[-1], -1) assert bool(errors) == bool(need_value) diff --git a/tests/test_plugin_run.py b/tests/test_plugin_run.py index 5211934..4283829 100644 --- a/tests/test_plugin_run.py +++ b/tests/test_plugin_run.py @@ -35,7 +35,7 @@ class TransactionCounter: class PostingCounter(TransactionCounter): HOOK_GROUPS = frozenset(['Posting', 'counter']) - def run(self, txn, post): + def run(self, txn, post, post_index): return ['post:{}'.format(id(post))] diff --git a/tests/testutil.py b/tests/testutil.py index c113e1b..7fc3815 100644 --- a/tests/testutil.py +++ b/tests/testutil.py @@ -33,6 +33,8 @@ def parse_date(s, fmt='%Y-%m-%d'): def Posting(account, number, currency='USD', cost=None, price=None, flag=None, **meta): + if not meta: + meta = None return bc_data.Posting( account, bc_amount.Amount(Decimal(number), currency),