hooks: Hooks declare what order they run in.
This commit is contained in:
parent
e8bcbd5f99
commit
85b665200c
9 changed files with 47 additions and 6 deletions
3
CODE.rst
3
CODE.rst
|
@ -59,6 +59,9 @@ Hooks make arbitrary transformations to entry data dicts. Every entry data dict
|
||||||
|
|
||||||
If this method returns any other value, the program replaces the entry data with the return value, and continues processing.
|
If this method returns any other value, the program replaces the entry data with the return value, and continues processing.
|
||||||
|
|
||||||
|
Class attribute ``KIND``
|
||||||
|
This should be one of the values of the ``hooks.HOOK_KINDS`` enum. This information determines what order hooks run in.
|
||||||
|
|
||||||
Templates
|
Templates
|
||||||
~~~~~~~~~
|
~~~~~~~~~
|
||||||
|
|
||||||
|
|
4
TODO.rst
4
TODO.rst
|
@ -8,10 +8,6 @@ The big idea: make it easier for hooks to customize *what* template(s) are rende
|
||||||
|
|
||||||
Required:
|
Required:
|
||||||
|
|
||||||
* Add some sort of ordering for hooks
|
|
||||||
Thinking an enum of named stages: data adders, data mungers, filters, actions.
|
|
||||||
The return value of ``hooks.load_all()`` must respect this ordering.
|
|
||||||
|
|
||||||
* Make the main loop seed the entry data with information about the importer used.
|
* Make the main loop seed the entry data with information about the importer used.
|
||||||
|
|
||||||
* Move template rendering into a hook, where the template to load is determined by a value in the entry data.
|
* Move template rendering into a hook, where the template to load is determined by a value in the entry data.
|
||||||
|
|
|
@ -1,6 +1,27 @@
|
||||||
import operator
|
import operator
|
||||||
|
|
||||||
|
try:
|
||||||
|
import enum
|
||||||
|
except ImportError:
|
||||||
|
import enum34 as enum
|
||||||
|
|
||||||
from .. import dynload
|
from .. import dynload
|
||||||
|
|
||||||
|
HOOK_KINDS = enum.Enum('HOOK_KINDS', [
|
||||||
|
# Hooks will run in the order that their KIND appears in this list.
|
||||||
|
|
||||||
|
# DATA_ADDER hooks should add data to the entry from outside sources like
|
||||||
|
# the user's configuration.
|
||||||
|
'DATA_ADDER',
|
||||||
|
# DATA_MUNGER hooks should add or change data in the entry based on what's
|
||||||
|
# already in it.
|
||||||
|
'DATA_MUNGER',
|
||||||
|
# DATA_FILTER hooks make a decision about whether or not to proceed with
|
||||||
|
# processing the entry.
|
||||||
|
'DATA_FILTER',
|
||||||
|
])
|
||||||
|
|
||||||
def load_all():
|
def load_all():
|
||||||
return dynload.submodule_items_named(__file__, operator.methodcaller('endswith', 'Hook'))
|
hooks = list(dynload.submodule_items_named(__file__, operator.methodcaller('endswith', 'Hook')))
|
||||||
|
hooks.sort(key=operator.attrgetter('KIND.value'))
|
||||||
|
return hooks
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
import re
|
import re
|
||||||
import unicodedata
|
import unicodedata
|
||||||
|
|
||||||
|
from . import HOOK_KINDS
|
||||||
|
|
||||||
class AddEntityHook:
|
class AddEntityHook:
|
||||||
|
KIND = HOOK_KINDS.DATA_MUNGER
|
||||||
NAME_PREFIXES = frozenset([
|
NAME_PREFIXES = frozenset([
|
||||||
'da',
|
'da',
|
||||||
'de',
|
'de',
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
|
from . import HOOK_KINDS
|
||||||
|
|
||||||
class DefaultDateHook:
|
class DefaultDateHook:
|
||||||
|
KIND = HOOK_KINDS.DATA_ADDER
|
||||||
|
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
self.config = config
|
self.config = config
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
|
from . import HOOK_KINDS
|
||||||
|
|
||||||
class FilterByDateHook:
|
class FilterByDateHook:
|
||||||
|
KIND = HOOK_KINDS.DATA_FILTER
|
||||||
|
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
self.config = config
|
self.config = config
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
|
from . import HOOK_KINDS
|
||||||
|
|
||||||
class InvoicePaymentHook:
|
class InvoicePaymentHook:
|
||||||
|
KIND = HOOK_KINDS.DATA_MUNGER
|
||||||
|
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
4
setup.py
4
setup.py
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import itertools
|
import itertools
|
||||||
|
import sys
|
||||||
|
|
||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
|
@ -12,6 +13,9 @@ REQUIREMENTS = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if sys.version_info < (3, 4):
|
||||||
|
REQUIREMENTS['install_requires'].extend(['enum34'])
|
||||||
|
|
||||||
REQUIREMENTS['tests_require'] = [
|
REQUIREMENTS['tests_require'] = [
|
||||||
'pytest',
|
'pytest',
|
||||||
'PyYAML',
|
'PyYAML',
|
||||||
|
|
|
@ -9,7 +9,9 @@ from import2ledger.hooks import add_entity, default_date, filter_by_date
|
||||||
|
|
||||||
def test_load_all():
|
def test_load_all():
|
||||||
all_hooks = list(hooks.load_all())
|
all_hooks = list(hooks.load_all())
|
||||||
assert add_entity.AddEntityHook in all_hooks
|
positions = {hook: index for index, hook in enumerate(all_hooks)}
|
||||||
|
assert positions[default_date.DefaultDateHook] < positions[add_entity.AddEntityHook]
|
||||||
|
assert positions[add_entity.AddEntityHook] < positions[filter_by_date.FilterByDateHook]
|
||||||
|
|
||||||
@pytest.mark.parametrize('in_key,payee,out_key,expected', [
|
@pytest.mark.parametrize('in_key,payee,out_key,expected', [
|
||||||
('payee', 'Alex Smith', 'entity', 'Smith-Alex'),
|
('payee', 'Alex Smith', 'entity', 'Smith-Alex'),
|
||||||
|
|
Loading…
Add table
Reference in a new issue