config: Accept a source date for displaying rates.
For output formats that can show both a cost and a price, this will be used to distinguish them.
This commit is contained in:
parent
9b6d562d46
commit
27dbe14b94
2 changed files with 58 additions and 16 deletions
|
@ -26,7 +26,7 @@ class Configuration:
|
||||||
DEFAULT_CONFIG_PATH = pathlib.Path(HOME_PATH, '.config', 'oxrlib.ini')
|
DEFAULT_CONFIG_PATH = pathlib.Path(HOME_PATH, '.config', 'oxrlib.ini')
|
||||||
LOCALE = babel.core.Locale.default()
|
LOCALE = babel.core.Locale.default()
|
||||||
SENTINEL = object()
|
SENTINEL = object()
|
||||||
PREPOSITIONS = frozenset(['in', 'to', 'into'])
|
CURRENCY_PREPOSITIONS = frozenset(['in', 'to', 'into'])
|
||||||
TODAY = datetime.date.today()
|
TODAY = datetime.date.today()
|
||||||
|
|
||||||
def __init__(self, arglist):
|
def __init__(self, arglist):
|
||||||
|
@ -152,7 +152,13 @@ class Configuration:
|
||||||
help="Convert or show rates to this currency, in three-letter code format. "
|
help="Convert or show rates to this currency, in three-letter code format. "
|
||||||
"If not specified, defaults to the user's preferred currency.",
|
"If not specified, defaults to the user's preferred currency.",
|
||||||
)
|
)
|
||||||
hist_parser.add_argument('word4', nargs='?', help=argparse.SUPPRESS)
|
hist_parser.add_argument(
|
||||||
|
'word4', nargs='?', metavar='from date',
|
||||||
|
help="Include source rates for this date, if provided. "
|
||||||
|
"Raw output format does not show source rates.",
|
||||||
|
)
|
||||||
|
hist_parser.add_argument('word5', nargs='?', help=argparse.SUPPRESS)
|
||||||
|
hist_parser.add_argument('word6', nargs='?', help=argparse.SUPPRESS)
|
||||||
|
|
||||||
return prog_parser
|
return prog_parser
|
||||||
|
|
||||||
|
@ -208,7 +214,7 @@ class Configuration:
|
||||||
self._read_from_conffile('signed_currencies', 'Historical', pref_currency,
|
self._read_from_conffile('signed_currencies', 'Historical', pref_currency,
|
||||||
currency_list, convert_fallback=True)
|
currency_list, convert_fallback=True)
|
||||||
self._read_from_conffile('ledger', 'Historical', False, getter='getboolean')
|
self._read_from_conffile('ledger', 'Historical', False, getter='getboolean')
|
||||||
raw_words = iter(getattr(self.args, 'word' + c) for c in '1234')
|
raw_words = iter(getattr(self.args, 'word' + c) for c in '123456')
|
||||||
words = iter(word for word in raw_words if word is not None)
|
words = iter(word for word in raw_words if word is not None)
|
||||||
try:
|
try:
|
||||||
next_word = next(words)
|
next_word = next(words)
|
||||||
|
@ -221,11 +227,35 @@ class Configuration:
|
||||||
# If it wasn't, set a value that can't be parsed as a currency.
|
# If it wasn't, set a value that can't be parsed as a currency.
|
||||||
next_word = next(words, 'none given')
|
next_word = next(words, 'none given')
|
||||||
self.args.from_currency = self._convert_or_error(currency_code, next_word)
|
self.args.from_currency = self._convert_or_error(currency_code, next_word)
|
||||||
next_word = next(words)
|
|
||||||
if next_word.lower() in self.PREPOSITIONS:
|
|
||||||
next_word = next(words, next_word)
|
|
||||||
self.args.to_currency = self._convert_or_error(currency_code, next_word)
|
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
|
pass
|
||||||
|
self.args.to_currency = None
|
||||||
|
self.args.from_date = None
|
||||||
|
for next_word in words:
|
||||||
|
next_lower = next_word.lower()
|
||||||
|
if next_lower in self.CURRENCY_PREPOSITIONS:
|
||||||
|
attr_to_set = 'to_currency'
|
||||||
|
next_word = next(words, 'none given')
|
||||||
|
elif next_lower == 'from':
|
||||||
|
attr_to_set = 'from_date'
|
||||||
|
next_word = next(words, 'none given')
|
||||||
|
elif next_word.isalpha():
|
||||||
|
attr_to_set = 'to_currency'
|
||||||
|
else:
|
||||||
|
attr_to_set = 'from_date'
|
||||||
|
have_arg = getattr(self.args, attr_to_set)
|
||||||
|
if have_arg is not None:
|
||||||
|
self.error(f"tried to set {attr_to_set.replace('_', ' ')} multiple times")
|
||||||
|
elif attr_to_set == 'from_date':
|
||||||
|
convert_func = lambda s: self._date_from_s(s)[0]
|
||||||
|
typename = 'date'
|
||||||
|
else:
|
||||||
|
convert_func = currency_code
|
||||||
|
typename = None
|
||||||
|
setattr(self.args, attr_to_set, self._convert_or_error(
|
||||||
|
convert_func, next_word, attr_to_set, typename,
|
||||||
|
))
|
||||||
|
if self.args.to_currency is None:
|
||||||
self.args.to_currency = pref_currency
|
self.args.to_currency = pref_currency
|
||||||
if ((len(date_spec) == 1)
|
if ((len(date_spec) == 1)
|
||||||
and self.args.from_currency
|
and self.args.from_currency
|
||||||
|
|
|
@ -46,26 +46,34 @@ def test_historical_default_base(ini_filename, expected_currency, use_switch, an
|
||||||
config = config_from(ini_filename, arglist)
|
config = config_from(ini_filename, arglist)
|
||||||
assert config.args.base == expected_currency
|
assert config.args.base == expected_currency
|
||||||
|
|
||||||
@pytest.mark.parametrize('amount,from_curr,preposition,to_curr', [
|
@pytest.mark.parametrize('amount,from_curr,prep1,to_curr,prep2,from_date', [
|
||||||
(None, 'JPY', None, None),
|
(None, 'JPY', None, None, None, None),
|
||||||
(None, 'gbp', None, 'Aud'),
|
(None, 'gbp', None, 'Aud', None, None),
|
||||||
(None, 'CHF', 'to', 'eur'),
|
(None, 'CHF', 'to', 'eur', None, None),
|
||||||
(decimal.Decimal('1000'), 'chf', None, None),
|
(decimal.Decimal('1000'), 'chf', None, None, None, None),
|
||||||
(decimal.Decimal('999'), 'Eur', None, 'Chf'),
|
(decimal.Decimal('999'), 'Eur', None, 'Chf', None, None),
|
||||||
(decimal.Decimal('12.34'), 'gbp', 'IN', 'eur'),
|
(decimal.Decimal('12.34'), 'gbp', 'IN', 'eur', None, None),
|
||||||
|
(None, 'JPY', None, None, None, '12-15'),
|
||||||
|
(None, 'gbp', None, 'Aud', 'From', '12.15'),
|
||||||
|
(None, 'CHF', 'to', 'eur', 'from', '15'),
|
||||||
|
(decimal.Decimal('1000'), 'chf', None, None, None, '12-15'),
|
||||||
|
(decimal.Decimal('999'), 'Eur', None, 'Chf', None, '2016.12.15'),
|
||||||
|
(decimal.Decimal('12.34'), 'gbp', 'IN', 'eur', 'from', '2016-12-15'),
|
||||||
])
|
])
|
||||||
def test_historical_argparsing_success(amount, from_curr, preposition, to_curr, any_date):
|
def test_historical_argparsing_success(amount, from_curr, prep1, to_curr, prep2, from_date, any_date):
|
||||||
oxrlib.config.Configuration.TODAY = datetime.date(2017, 1, 1)
|
oxrlib.config.Configuration.TODAY = datetime.date(2017, 1, 1)
|
||||||
# This locale's currency should not be used in any test cases above.
|
# This locale's currency should not be used in any test cases above.
|
||||||
oxrlib.config.Configuration.LOCALE = babel.core.Locale('en', 'IN')
|
oxrlib.config.Configuration.LOCALE = babel.core.Locale('en', 'IN')
|
||||||
arglist = ['historical', any_date.isoformat()]
|
arglist = ['historical', any_date.isoformat()]
|
||||||
arglist.extend(str(s) for s in [amount, from_curr, preposition, to_curr]
|
arglist.extend(str(s) for s in [amount, from_curr, prep1, to_curr, prep2, from_date]
|
||||||
if s is not None)
|
if s is not None)
|
||||||
config = config_from(os.devnull, arglist)
|
config = config_from(os.devnull, arglist)
|
||||||
expect_to_curr = 'INR' if to_curr is None else to_curr.upper()
|
expect_to_curr = 'INR' if to_curr is None else to_curr.upper()
|
||||||
assert config.args.amount == amount
|
assert config.args.amount == amount
|
||||||
assert config.args.from_currency == from_curr.upper()
|
assert config.args.from_currency == from_curr.upper()
|
||||||
assert config.args.to_currency == expect_to_curr
|
assert config.args.to_currency == expect_to_curr
|
||||||
|
expect_from_date = None if from_date is None else datetime.date(2016, 12, 15)
|
||||||
|
assert config.args.from_date == expect_from_date
|
||||||
|
|
||||||
@pytest.mark.parametrize('arglist', [
|
@pytest.mark.parametrize('arglist', [
|
||||||
['100'],
|
['100'],
|
||||||
|
@ -76,6 +84,10 @@ def test_historical_argparsing_success(amount, from_curr, preposition, to_curr,
|
||||||
['44', 'eur', 'in', 'chf', 'pronto'],
|
['44', 'eur', 'in', 'chf', 'pronto'],
|
||||||
['eur', 'into'],
|
['eur', 'into'],
|
||||||
['50', 'jpy', 'in'],
|
['50', 'jpy', 'in'],
|
||||||
|
['115', 'usd', 'in', '12-15'],
|
||||||
|
['125', 'jpy', 'from', 'chf'],
|
||||||
|
['135', 'chf', 'eur', 'gbp'],
|
||||||
|
['145', 'brl', '12-16', '2020-12-18'],
|
||||||
])
|
])
|
||||||
def test_historical_argparsing_failure(arglist, any_date):
|
def test_historical_argparsing_failure(arglist, any_date):
|
||||||
arglist = ['historical', any_date.isoformat()] + arglist
|
arglist = ['historical', any_date.isoformat()] + arglist
|
||||||
|
|
Loading…
Reference in a new issue