diff --git a/oxrlib/commands/historical.py b/oxrlib/commands/historical.py index 828054b7f9b5b7d12726cdddf7aad0e61b7e98dc..71ba00e9934c6478a35fa4163b096076435c56d0 100644 --- a/oxrlib/commands/historical.py +++ b/oxrlib/commands/historical.py @@ -14,7 +14,7 @@ except ImportError: class Formatter: def __init__(self, cost_rates, price_rates=None, signed_currencies=(), base_fmt='#,##0.###', - rate_precision=5, denomination=None): + rate_precision=6, denomination=None): self.cost_rates = cost_rates self.price_rates = price_rates self.base_fmt = base_fmt @@ -95,27 +95,13 @@ class BeancountFormatter(Formatter): qrate = rate return qrate.normalize() - def normalize_enough(self, rate, curr, from_amt, to_amt, prec=None): - if prec is None: - prec = self.rate_prec - # Starting from prec, find the least amount of precision to - # make sure from_amt converts exactly to to_amt. - for try_prec in itertools.count(prec): - try_rate = self.normalize_rate(rate, try_prec) - got_amt = self.currency_decimal(from_amt * try_rate, curr) - # If got_amt == to_amt, this is enough precision to do the - # conversion exactly, so we're done. - # If try_rate == rate, there's no more precision available, so stop. - if (got_amt == to_amt) or (try_rate == rate): - break - return try_rate - - def _pretty_rate(self, fmt, rate, curr, from_amt=None, to_amt=None): - if to_amt is None: - rate = self.normalize_rate(rate) - else: - rate = self.normalize_enough(rate, curr, from_amt, to_amt) - return fmt.format(self.format_currency(rate, curr, currency_digits=False)) + def _pretty_rate(self, fmt, rate, curr): + rate_s = self.format_currency( + self.normalize_rate(rate), + curr, + currency_digits=False, + ) + return fmt.format(rate_s) def format_rate_pair(self, from_curr, to_curr): from_amt = 1 @@ -151,12 +137,10 @@ class BeancountFormatter(Formatter): if price is None: price_s = '' else: - price_s = self._pretty_rate( - self.PRICE_FMT, price, denomination, amount, to_amt, - ) + price_s = self._pretty_rate(self.PRICE_FMT, price, denomination) return "{} {}{}".format( amt_s, - self._pretty_rate(self.COST_FMT, cost, denomination, amount, to_amt), + self._pretty_rate(self.COST_FMT, cost, denomination), price_s, ) diff --git a/setup.py b/setup.py index 09fda1599c1bafb23faf76d744c67c7c4cc57fee..623d196752690f3e6866385cc0112ef864716dbb 100755 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ from setuptools import setup setup( name='oxrlib', description="Library to query the Open Exchange Rates (OXR) API", - version='2.0', + version='2.1', author='Brett Smith', author_email='brettcsmith@brettcsmith.org', license='GNU AGPLv3+', diff --git a/tests/test_historical.py b/tests/test_historical.py index 951aa737fb0c92ada813afc76980a67c01bccfdf..e226c8e1055bbead0c5cd0c04e279546ae754b6a 100644 --- a/tests/test_historical.py +++ b/tests/test_historical.py @@ -239,3 +239,24 @@ def test_from_date_conversion(alternate_responder, output, any_date, output_form check_fx_amount(config, lines, '10.00 ANG', '0.558', 'USD', '$', '0.507') check_fx_amount(config, lines, '20.52 AED', '0.272', 'USD', '$', '0.265') assert next(lines, None) is None + +@parametrize_format +def test_rate_consistent_as_cost_and_price(alternate_responder, any_date, output_format): + config_kwargs = { + 'responder': alternate_responder, + 'amount': 65000, + 'from_currency': 'RUB', + 'output_format': output_format, + 'signed_currencies': (), + } + config = build_config(date=any_date, **config_kwargs) + with io.StringIO() as output: + lines = lines_from_run(config, output) + match = re.search(r'\{=?(\d+\.\d+ USD)\}', next(lines, "")) + assert match + expect_rate = f' @ {match.group(1)}\n' + future_date = any_date.replace(year=any_date.year + 1) + config = build_config(date=future_date, from_date=any_date, **config_kwargs) + with io.StringIO() as output: + lines = lines_from_run(config, output) + assert next(lines, "").endswith(expect_rate)