Changeset - 08073f752bc8
[Not reviewed]
0 2 0
Brett Smith - 7 years ago 2017-05-17 15:32:05
brettcsmith@brettcsmith.org
Configuration: Parse more conversion arguments for historical subcommand.
2 files changed with 80 insertions and 2 deletions:
0 comments (0 inline, 0 general)
oxrlib/config.py
Show inline comments
 
import argparse
 
import configparser
 
import datetime
 
import decimal
 
import os.path
 
import pathlib
 

	
...
 
@@ -13,7 +14,7 @@ base=USD
 
"""
 

	
 
def currency_code(s):
 
    if not (len(s) == 3) and s.isalpha():
 
    if not ((len(s) == 3) and s.isalpha()):
 
        raise ValueError("bad currency code: {!r}".format(s))
 
    return s.upper()
 

	
...
 
@@ -24,6 +25,7 @@ def date_from(fmt_s):
 

	
 
class Configuration:
 
    DEFAULT_CONFIG_PATH = pathlib.Path(HOME_PATH, '.config', 'oxrlib.ini')
 
    PREPOSITIONS = frozenset(['in', 'to', 'into'])
 

	
 
    def __init__(self, arglist):
 
        argparser = self._build_argparser()
...
 
@@ -56,15 +58,24 @@ class Configuration:
 
        subparsers = prog_parser.add_subparsers()
 

	
 
        hist_parser = subparsers.add_parser('historical', aliases=['hist'])
 
        hist_parser.set_defaults(command='historical')
 
        hist_parser.set_defaults(
 
            command='historical',
 
            amount=None,
 
            from_currency=None,
 
        )
 
        hist_parser.add_argument(
 
            '--base',
 
            type=currency_code,
 
            help="Base currency (default USD)",
 
        )
 
        hist_parser.add_argument(
 
            'date',
 
            type=date_from('%Y-%m-%d'), metavar='YYYY-MM-DD',
 
        )
 
        hist_parser.add_argument(
 
            'remainder',
 
            nargs=argparse.REMAINDER,
 
        )
 

	
 
        return prog_parser
 

	
...
 
@@ -73,9 +84,42 @@ class Configuration:
 
        conffile.read_string(CONFFILE_SEED)
 
        return conffile
 

	
 
    def _convert_or_error(self, argtype, s_value, argname=None, typename=None):
 
        try:
 
            return argtype(s_value)
 
        except (decimal.InvalidOperation, TypeError, ValueError):
 
            errmsg = []
 
            if argname:
 
                errmsg.append("argument {}".format(argname))
 
            if typename is None:
 
                typename = argtype.__name__.replace('_', ' ')
 
            errmsg.append("invalid {} value".format(typename))
 
            errmsg.append(repr(s_value))
 
            self.error(': '.join(errmsg))
 

	
 
    def _post_hook_historical(self):
 
        if self.args.base is None:
 
            self.args.base = self.conffile.get('Historical', 'base')
 
        self.args.to_currency = self.args.base
 
        remain_len = len(self.args.remainder)
 
        if (remain_len > 3) and (self.args.remainder[2].lower() in self.PREPOSITIONS):
 
            del self.args.remainder[2]
 
            remain_len -= 1
 
        if remain_len == 0:
 
            pass
 
        elif remain_len == 1:
 
            self.args.from_currency = self._convert_or_error(
 
                currency_code, self.args.remainder[0])
 
        elif remain_len < 4:
 
            self.args.amount = self._convert_or_error(
 
                decimal.Decimal, self.args.remainder[0])
 
            self.args.from_currency = self._convert_or_error(
 
                currency_code, self.args.remainder[1])
 
            if remain_len == 3:
 
                self.args.to_currency = self._convert_or_error(
 
                    currency_code, self.args.remainder[2])
 
        else:
 
            self.error("too many arguments")
 

	
 
    def _build_cache_loader(self):
 
        kwargs = dict(self.conffile.items('Cache'))
tests/test_Configuration.py
Show inline comments
 
import decimal
 
import os
 

	
 
import pytest
...
 
@@ -42,3 +43,36 @@ def test_historical_default_base(ini_filename, expected_currency, use_switch, an
 
    arglist.append(any_date.isoformat())
 
    config = config_from(ini_filename, arglist)
 
    assert config.args.base == expected_currency
 

	
 
@pytest.mark.parametrize('amount,from_curr,preposition,to_curr', [
 
    (None, 'JPY', None, None),
 
    (decimal.Decimal('1000'), 'chf', None, None),
 
    (decimal.Decimal('999'), 'Eur', None, 'Chf'),
 
    (decimal.Decimal('12.34'), 'gbp', 'IN', 'eur'),
 
])
 
def test_historical_argparsing_success(amount, from_curr, preposition, to_curr, any_date):
 
    arglist = ['historical', any_date.isoformat()]
 
    arglist.extend(str(s) for s in [amount, from_curr, preposition, to_curr]
 
                   if s is not None)
 
    config = config_from(os.devnull, arglist)
 
    assert config.args.amount == amount
 
    assert config.args.from_currency == from_curr.upper()
 
    if to_curr is not None:
 
        assert config.args.to_currency == to_curr.upper()
 

	
 
@pytest.mark.parametrize('arglist', [
 
    ['100'],
 
    ['120', 'dollars'],
 
    ['to', '42', 'usd'],
 
    ['99', 'usd', 'minus', 'jpy'],
 
    ['usdjpy'],
 
    ['44', 'eur', 'in', 'chf', 'pronto'],
 
])
 
def test_historical_argparsing_failure(arglist, any_date):
 
    arglist = ['historical', any_date.isoformat()] + arglist
 
    try:
 
        config = config_from(os.devnull, arglist)
 
    except SystemExit:
 
        pass
 
    else:
 
        assert not vars(config.args), "bad arglist succeeded"
0 comments (0 inline, 0 general)