Changeset - 0d370c445b9e
[Not reviewed]
0 8 0
Brett Smith - 4 years ago 2020-03-19 21:23:27
brettcsmith@brettcsmith.org
plugin: User configuration is passed to hooks on initialization.
8 files changed with 62 insertions and 9 deletions:
0 comments (0 inline, 0 general)
conservancy_beancount/errors.py
Show inline comments
...
 
@@ -32,7 +32,19 @@ class Error(Exception):
 
        )
 

	
 
    def _fill_source(self, source, filename='conservancy_beancount', lineno=0):
 
        source.setdefault('filename', filename)
 
        source.setdefault('lineno', lineno)
 

	
 

	
 
Iter = Iterable[Error]
 

	
 
class ConfigurationError(Error):
 
    def __init__(self, message, entry=None, source=None):
 
        if source is None:
 
            source = {}
 
        self._fill_source(source)
 
        super().__init__(message, entry, source)
 

	
 

	
 
class InvalidMetadataError(Error):
 
    def __init__(self, txn, post, key, value=None, source=None):
conservancy_beancount/plugin/__init__.py
Show inline comments
...
 
@@ -33,4 +33,5 @@ from ..beancount_types import (
 
    Directive,
 
)
 
from .. import config as configmod
 
from .core import (
 
    Hook,
...
 
@@ -101,6 +102,12 @@ def run(
 
    errors: List[Error] = []
 
    hooks: Dict[HookName, List[Hook]] = {}
 
    user_config = configmod.Config()
 
    for key, hook_type in hook_registry.group_by_directive(config):
 
        hooks.setdefault(key, []).append(hook_type())
 
        try:
 
            hook = hook_type(user_config)
 
        except Error as error:
 
            errors.append(error)
 
        else:
 
            hooks.setdefault(key, []).append(hook)
 
    for entry in entries:
 
        entry_type = type(entry).__name__
conservancy_beancount/plugin/core.py
Show inline comments
...
 
@@ -19,4 +19,5 @@ import datetime
 
import re
 

	
 
from .. import config as configmod
 
from .. import data
 
from .. import errors as errormod
...
 
@@ -61,4 +62,9 @@ class Hook(Generic[Entry], metaclass=abc.ABCMeta):
 
    HOOK_GROUPS: FrozenSet[HookName] = frozenset()
 

	
 
    def __init__(self, config: configmod.Config) -> None:
 
        pass
 
        # Subclasses that need configuration should override __init__ to check
 
        # and store it.
 

	
 
    @abc.abstractmethod
 
    def run(self, entry: Entry) -> errormod.Iter: ...
tests/test_meta_expense_allocation.py
Show inline comments
...
 
@@ -40,5 +40,6 @@ TEST_KEY = 'expense-allocation'
 
@pytest.fixture(scope='module')
 
def hook():
 
    return meta_expense_allocation.MetaExpenseAllocation()
 
    config = testutil.TestConfig()
 
    return meta_expense_allocation.MetaExpenseAllocation(config)
 

	
 
@pytest.mark.parametrize('src_value,set_value', VALID_VALUES.items())
tests/test_meta_income_type.py
Show inline comments
...
 
@@ -40,5 +40,6 @@ TEST_KEY = 'income-type'
 
@pytest.fixture(scope='module')
 
def hook():
 
    return meta_income_type.MetaIncomeType()
 
    config = testutil.TestConfig()
 
    return meta_income_type.MetaIncomeType(config)
 

	
 
@pytest.mark.parametrize('src_value,set_value', VALID_VALUES.items())
tests/test_meta_tax_implication.py
Show inline comments
...
 
@@ -52,5 +52,6 @@ TEST_KEY = 'tax-implication'
 
@pytest.fixture(scope='module')
 
def hook():
 
    return meta_tax_implication.MetaTaxImplication()
 
    config = testutil.TestConfig()
 
    return meta_tax_implication.MetaTaxImplication(config)
 

	
 
@pytest.mark.parametrize('src_value,set_value', VALID_VALUES.items())
tests/test_plugin.py
Show inline comments
...
 
@@ -19,16 +19,31 @@ import pytest
 
from . import testutil
 

	
 
from conservancy_beancount import beancount_types, plugin
 
from conservancy_beancount import beancount_types, errors as errormod, plugin
 

	
 
HOOK_REGISTRY = plugin.HookRegistry()
 

	
 
class NonError(errormod.Error):
 
    pass
 

	
 

	
 
class TransactionHook:
 
    DIRECTIVE = beancount_types.Transaction
 
    HOOK_GROUPS = frozenset()
 

	
 
    def __init__(self, config):
 
        self.config = config
 

	
 
    def run(self, txn):
 
        assert False, "something called base class run method"
 

	
 

	
 
@HOOK_REGISTRY.add_hook
 
class ConfigurationError(TransactionHook):
 
    HOOK_GROUPS = frozenset(['unconfigured'])
 

	
 
    def __init__(self, config):
 
        raise errormod.ConfigurationError("testing error")
 

	
 

	
 
@HOOK_REGISTRY.add_hook
 
class TransactionError(TransactionHook):
...
 
@@ -36,5 +51,5 @@ class TransactionError(TransactionHook):
 

	
 
    def run(self, txn):
 
        return ['txn:{}'.format(id(txn))]
 
        return [NonError('txn:{}'.format(id(txn)), txn)]
 

	
 

	
...
 
@@ -44,5 +59,6 @@ class PostingError(TransactionHook):
 

	
 
    def run(self, txn):
 
        return ['post:{}'.format(id(post)) for post in txn.postings]
 
        return [NonError('post:{}'.format(id(post)), txn)
 
                for post in txn.postings]
 

	
 

	
...
 
@@ -66,6 +82,6 @@ def easy_entries():
 
def map_errors(errors):
 
    retval = {}
 
    for errkey in errors:
 
        key, _, errid = errkey.partition(':')
 
    for error in errors:
 
        key, _, errid = error.message.partition(':')
 
        retval.setdefault(key, set()).add(errid)
 
    return retval
tests/testutil.py
Show inline comments
...
 
@@ -21,4 +21,5 @@ import beancount.core.data as bc_data
 

	
 
from decimal import Decimal
 
from pathlib import Path
 

	
 
EXTREME_FUTURE_DATE = datetime.date(datetime.MAXYEAR, 12, 30)
...
 
@@ -95,2 +96,10 @@ class Transaction:
 
            posting = arg
 
        self.postings.append(posting)
 

	
 

	
 
class TestConfig:
 
    def __init__(self, repo_path=None):
 
        self.repo_path = None if repo_path is None else Path(repo_path)
 

	
 
    def repository_path(self):
 
        return self.repo_path
0 comments (0 inline, 0 general)