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)",
'date',
type=date_from('%Y-%m-%d'), metavar='YYYY-MM-DD',
'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])
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'))