more methods and tests
This commit is contained in:
parent
aec65e5364
commit
d382c332e3
2 changed files with 145 additions and 12 deletions
|
|
@ -4,7 +4,12 @@ from decimal import Decimal
|
||||||
from money.currency import Currency
|
from money.currency import Currency
|
||||||
from money.money import Money
|
from money.money import Money
|
||||||
|
|
||||||
from xexe.exchange_rates import ExchangeRate, ExchangeRates, add_equal_rates
|
from xexe.exchange_rates import (
|
||||||
|
ExchangeRate,
|
||||||
|
ExchangeRates,
|
||||||
|
add_equal_rates,
|
||||||
|
add_inverse_rates,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_exchange_rate_creation_works():
|
def test_exchange_rate_creation_works():
|
||||||
|
|
@ -124,6 +129,26 @@ def test_present_dates_works_fine():
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_exchange_rates_is_rate_present_method_works_fine():
|
||||||
|
a_rate = ExchangeRate(
|
||||||
|
from_currency=Currency.USD,
|
||||||
|
to_currency=Currency.EUR,
|
||||||
|
rate=Decimal("1.2"),
|
||||||
|
rate_date=datetime.date(2020, 3, 10),
|
||||||
|
)
|
||||||
|
another_rate = ExchangeRate(
|
||||||
|
from_currency=Currency.GBP,
|
||||||
|
to_currency=Currency.JPY,
|
||||||
|
rate=Decimal("10"),
|
||||||
|
rate_date=datetime.date(2019, 10, 3),
|
||||||
|
)
|
||||||
|
|
||||||
|
rates = ExchangeRates({a_rate})
|
||||||
|
|
||||||
|
assert rates.is_rate_present(a_rate)
|
||||||
|
assert not rates.is_rate_present(another_rate)
|
||||||
|
|
||||||
|
|
||||||
def test_add_equal_rates_returns_expected_values():
|
def test_add_equal_rates_returns_expected_values():
|
||||||
a_rate = ExchangeRate(
|
a_rate = ExchangeRate(
|
||||||
from_currency=Currency.USD,
|
from_currency=Currency.USD,
|
||||||
|
|
@ -170,3 +195,73 @@ def test_add_equal_rates_runs_on_empty_rates():
|
||||||
empty_rates = add_equal_rates(empty_rates)
|
empty_rates = add_equal_rates(empty_rates)
|
||||||
|
|
||||||
assert True
|
assert True
|
||||||
|
|
||||||
|
|
||||||
|
def test_add_equal_rates_overwrites():
|
||||||
|
a_rate = ExchangeRate(
|
||||||
|
from_currency=Currency.USD,
|
||||||
|
to_currency=Currency.USD,
|
||||||
|
rate=Decimal("1.2"),
|
||||||
|
rate_date=datetime.date(2020, 3, 10),
|
||||||
|
)
|
||||||
|
|
||||||
|
rates = ExchangeRates([a_rate])
|
||||||
|
|
||||||
|
assert len(rates) == 1
|
||||||
|
|
||||||
|
rates = add_equal_rates(rates, overwrite=True)
|
||||||
|
|
||||||
|
assert len(rates) == 1
|
||||||
|
assert list(rates)[0].amount == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_add_equal_rates_does_not_overwrite():
|
||||||
|
a_rate = ExchangeRate(
|
||||||
|
from_currency=Currency.USD,
|
||||||
|
to_currency=Currency.USD,
|
||||||
|
rate=Decimal("1.2"),
|
||||||
|
rate_date=datetime.date(2020, 3, 10),
|
||||||
|
)
|
||||||
|
|
||||||
|
rates = ExchangeRates([a_rate])
|
||||||
|
|
||||||
|
assert len(rates) == 1
|
||||||
|
|
||||||
|
rates = add_equal_rates(rates, overwrite=False)
|
||||||
|
|
||||||
|
assert len(rates) == 1
|
||||||
|
assert list(rates)[0].amount == Decimal("1.2")
|
||||||
|
|
||||||
|
|
||||||
|
def test_add_inverse_rates_returns_expected():
|
||||||
|
a_rate = ExchangeRate(
|
||||||
|
from_currency=Currency.EUR,
|
||||||
|
to_currency=Currency.USD,
|
||||||
|
rate=Decimal("1.25"),
|
||||||
|
rate_date=datetime.date(2020, 3, 10),
|
||||||
|
)
|
||||||
|
inverse_rate = ExchangeRate(
|
||||||
|
from_currency=Currency.USD,
|
||||||
|
to_currency=Currency.EUR,
|
||||||
|
rate=Decimal("0.8"),
|
||||||
|
rate_date=datetime.date(2020, 3, 10),
|
||||||
|
)
|
||||||
|
|
||||||
|
rates = ExchangeRates([a_rate])
|
||||||
|
|
||||||
|
assert len(rates) == 1
|
||||||
|
|
||||||
|
rates = add_inverse_rates(rates)
|
||||||
|
|
||||||
|
assert len(rates) == 2
|
||||||
|
|
||||||
|
assert rates.is_rate_present(inverse_rate)
|
||||||
|
assert rates[inverse_rate.descriptor].amount == Decimal("0.8")
|
||||||
|
|
||||||
|
|
||||||
|
def test_add_inverse_rates_runs_on_empty_rates():
|
||||||
|
empty_rates = ExchangeRates()
|
||||||
|
|
||||||
|
empty_rates = add_inverse_rates(empty_rates)
|
||||||
|
|
||||||
|
assert True
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ from decimal import Decimal
|
||||||
from numbers import Number
|
from numbers import Number
|
||||||
from typing import Iterable, Set, Union
|
from typing import Iterable, Set, Union
|
||||||
|
|
||||||
from money.currency import Currency
|
from money.currency import Currency, CurrencyHelper
|
||||||
from money.money import Money
|
from money.money import Money
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -13,7 +13,7 @@ class ExchangeRate:
|
||||||
self,
|
self,
|
||||||
from_currency: Currency,
|
from_currency: Currency,
|
||||||
to_currency: Currency,
|
to_currency: Currency,
|
||||||
rate: Union[Money, Number],
|
rate: Union[Money, Number, str],
|
||||||
rate_date: datetime.date,
|
rate_date: datetime.date,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.from_currency = from_currency
|
self.from_currency = from_currency
|
||||||
|
|
@ -66,26 +66,64 @@ class ExchangeRates:
|
||||||
self._rate_index[new_rate.descriptor] = new_rate
|
self._rate_index[new_rate.descriptor] = new_rate
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return iter(self._rate_index.values())
|
return iter(list(self._rate_index.values()))
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
return len(self._rate_index)
|
return len(self._rate_index)
|
||||||
|
|
||||||
|
def __contains__(self, rate) -> bool:
|
||||||
|
if not isinstance(rate, ExchangeRate):
|
||||||
|
raise TypeError("ExchangeRates can only hold Rates.")
|
||||||
|
|
||||||
def add_equal_rates(rates: ExchangeRates) -> ExchangeRates:
|
if rate.descriptor in self._rate_index:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
def is_rate_present(self, rate: ExchangeRate) -> bool:
|
||||||
|
if rate.descriptor in self._rate_index:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
def __getitem__(self, rate_descriptor) -> ExchangeRate:
|
||||||
|
return self._rate_index[rate_descriptor]
|
||||||
|
|
||||||
|
|
||||||
|
def add_equal_rates(rates: ExchangeRates, overwrite: bool = False) -> ExchangeRates:
|
||||||
|
|
||||||
present_currencies = rates.present_currencies
|
present_currencies = rates.present_currencies
|
||||||
present_dates = rates.present_dates
|
present_dates = rates.present_dates
|
||||||
|
|
||||||
for date in present_dates:
|
for date in present_dates:
|
||||||
for currency in present_currencies:
|
for currency in present_currencies:
|
||||||
rates.add_rate(
|
new_rate = ExchangeRate(
|
||||||
ExchangeRate(
|
from_currency=currency,
|
||||||
from_currency=currency,
|
to_currency=currency,
|
||||||
to_currency=currency,
|
rate=Money(1, currency),
|
||||||
rate=Money(1, currency),
|
rate_date=date,
|
||||||
rate_date=date,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
if new_rate in rates and not overwrite:
|
||||||
|
continue
|
||||||
|
rates.add_rate(new_rate)
|
||||||
|
|
||||||
|
return rates
|
||||||
|
|
||||||
|
|
||||||
|
def add_inverse_rates(rates: ExchangeRates) -> ExchangeRates:
|
||||||
|
|
||||||
|
# Hey, I haven't thought properly what happens here if the inverse rate is
|
||||||
|
# *already* present in the rates set. It's probably going to be fucky. I
|
||||||
|
# would advise only running this against sets where you don't have inverse
|
||||||
|
# rates already present.
|
||||||
|
|
||||||
|
for rate in rates:
|
||||||
|
inverse_rate = ExchangeRate(
|
||||||
|
from_currency=rate.to_currency,
|
||||||
|
to_currency=rate.from_currency,
|
||||||
|
rate_date=rate.rate_date,
|
||||||
|
rate=f"{1 / rate.amount:.{CurrencyHelper.decimal_precision_for_currency(rate.from_currency)}f}",
|
||||||
|
)
|
||||||
|
rates.add_rate(inverse_rate)
|
||||||
|
|
||||||
return rates
|
return rates
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue