template: render() takes a single mapping argument.

This lets it receive other mapping types like ChainMap.
This commit is contained in:
Brett Smith 2017-12-19 08:24:46 -05:00
parent 1b98ab2015
commit 34b71baaf7
3 changed files with 51 additions and 26 deletions

View file

@ -61,8 +61,8 @@ Templates receive entry data dicts and format them into final output entries.
``__init__(template_str)``
Initializes the template from a single string, as read from the user's configuration.
``render(payee, amount, currency, date=None, **template_vars)``
Returns a string with the output entry, using the given entry data. This is expected to be called as ``render(**entry_data)``; the arguments take the same types as entry data dicts.
``render(entry_data)``
Returns a string with the output entry, using the given entry data.
Loading importers and hooks
---------------------------

View file

@ -247,19 +247,23 @@ class Template:
else:
self.splitter.set_metadata(str_flat)
def render(self, payee, amount, currency, date=None, **template_vars):
if date is None:
def render(self, template_vars):
# template_vars must have these keys. Raise a KeyError if not.
template_vars['currency']
template_vars['payee']
try:
date = template_vars['date']
except KeyError:
date = datetime.date.today()
template_vars.update(
date=date.strftime(self.date_fmt),
payee=payee,
amount=strparse.currency_decimal(amount),
currency=currency,
)
render_vars = {
'amount': strparse.currency_decimal(template_vars['amount']),
'date': date.strftime(self.date_fmt),
}
for key, value in template_vars.items():
if key.endswith('_date'):
template_vars[key] = value.strftime(self.date_fmt)
return ''.join(f(template_vars) for f in self.format_funcs)
render_vars[key] = value.strftime(self.date_fmt)
all_vars = collections.ChainMap(render_vars, template_vars)
return ''.join(f(all_vars) for f in self.format_funcs)
def is_empty(self):
return not self.format_funcs

View file

@ -1,3 +1,4 @@
import collections
import configparser
import datetime
import decimal
@ -17,8 +18,20 @@ with pathlib.Path(DATA_DIR, 'templates.ini').open() as conffile:
def template_from(section_name, *args, **kwargs):
return template.Template(config[section_name]['template'], *args, **kwargs)
def template_vars(payee, amount, currency='USD', date=DATE, other_vars=None):
call_vars = {
'amount': decimal.Decimal(amount),
'currency': currency,
'date': date,
'payee': payee,
}
if other_vars is None:
return call_vars
else:
return collections.ChainMap(call_vars, other_vars)
def assert_easy_render(tmpl, entity, amount, currency, expect_date, expect_amt):
rendered = tmpl.render(entity, decimal.Decimal(amount), currency, DATE)
rendered = tmpl.render(template_vars(entity, amount, currency))
lines = [normalize_whitespace(s) for s in rendered.splitlines()]
assert lines == [
"",
@ -42,17 +55,17 @@ def test_currency_formatting():
def test_empty_template():
tmpl = template.Template("\n \n")
assert tmpl.render('BB', decimal.Decimal('8.99'), 'USD', DATE) == ''
assert tmpl.render(template_vars('BB', '8.99')) == ''
assert tmpl.is_empty()
def test_complex_template():
template_vars = {
render_vars = template_vars('TT', '125.50', other_vars={
'entity': 'T-T',
'program': 'Spectrum Defense',
'txid': 'ABCDEF',
}
})
tmpl = template_from('Complex', date_fmt='%Y-%m-%d', signed_currencies=['USD'])
rendered = tmpl.render('TT', decimal.Decimal('125.50'), 'USD', DATE, **template_vars)
rendered = tmpl.render(render_vars)
lines = [normalize_whitespace(s) for s in rendered.splitlines()]
assert lines == [
"",
@ -70,7 +83,7 @@ def test_complex_template():
def test_balancing():
tmpl = template_from('FiftyFifty')
rendered = tmpl.render('FF', decimal.Decimal('1.01'), 'USD', DATE)
rendered = tmpl.render(template_vars('FF', '1.01'))
lines = [normalize_whitespace(s) for s in rendered.splitlines()]
assert lines == [
"",
@ -81,9 +94,11 @@ def test_balancing():
]
def test_multivalue():
render_vars = template_vars('DD', '150.00', other_vars={
'tax': decimal.Decimal('12.50'),
})
tmpl = template_from('Multivalue')
rendered = tmpl.render('DD', decimal.Decimal('150.00'), 'USD', DATE,
tax=decimal.Decimal('12.50'))
rendered = tmpl.render(render_vars)
lines = [normalize_whitespace(s) for s in rendered.splitlines()]
assert lines == [
"",
@ -96,9 +111,11 @@ def test_multivalue():
]
def test_zeroed_account_skipped():
render_vars = template_vars('GG', '110.00', other_vars={
'tax': decimal.Decimal(0),
})
tmpl = template_from('Multivalue')
rendered = tmpl.render('GG', decimal.Decimal('110.00'), 'USD', DATE,
tax=decimal.Decimal(0))
rendered = tmpl.render(render_vars)
lines = [normalize_whitespace(s) for s in rendered.splitlines()]
assert lines == [
"",
@ -109,9 +126,11 @@ def test_zeroed_account_skipped():
]
def test_custom_payee_line():
render_vars = template_vars('ZZ', '10.00', other_vars={
'custom_date': datetime.date(2014, 2, 13),
})
tmpl = template_from('Custom Payee')
rendered = tmpl.render('ZZ', decimal.Decimal('10.00'), 'USD', DATE,
custom_date=datetime.date(2014, 2, 13))
rendered = tmpl.render(render_vars)
lines = [normalize_whitespace(s) for s in rendered.splitlines()]
assert lines == [
"",
@ -121,9 +140,11 @@ def test_custom_payee_line():
]
def test_line1_not_custom_payee():
render_vars = template_vars('VV', '15.00', other_vars={
'custom_date': datetime.date(2014, 2, 12),
})
tmpl = template_from('Simplest')
rendered = tmpl.render('VV', decimal.Decimal('15.00'), 'USD', DATE,
custom_date=datetime.date(2014, 2, 12))
rendered = tmpl.render(render_vars)
lines = [normalize_whitespace(s) for s in rendered.splitlines()]
assert lines == [
"",