Skip to content

Commit d6f62a2

Browse files
committed
Raise exception when rate date is not the requested
The API return the latest rate when requesting a rate for a date for which it is not yet available like in the future.
1 parent 2bcc504 commit d6f62a2

File tree

2 files changed

+25
-9
lines changed

2 files changed

+25
-9
lines changed

forex_python/converter.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,21 @@ def _get_date_string(self, date_obj):
3232
date_str = date_obj.strftime('%Y-%m-%d')
3333
return date_str
3434

35-
def _decode_rates(self, response, use_decimal=False):
35+
def _decode_rates(self, response, use_decimal=False, date_str=None):
3636
if self._force_decimal or use_decimal:
37-
decoded_data = json.loads(response.text, use_decimal=True).get('rates', {})
37+
decoded_data = json.loads(response.text, use_decimal=True)
3838
else:
39-
decoded_data = response.json().get('rates', {})
40-
return decoded_data
39+
decoded_data = response.json()
40+
if (date_str and date_str != 'latest'
41+
and date_str != decoded_data.get('date')):
42+
raise RatesNotAvailableError("Currency Rates Source Not Ready")
43+
return decoded_data.get('rates', {})
4144

42-
def _get_decoded_rate(self, response, dest_cur, use_decimal=False):
43-
return self._decode_rates(response, use_decimal=use_decimal).get(dest_cur, None)
45+
def _get_decoded_rate(
46+
self, response, dest_cur, use_decimal=False, date_str=None):
47+
return self._decode_rates(
48+
response, use_decimal=use_decimal, date_str=date_str).get(
49+
dest_cur, None)
4450

4551

4652
class CurrencyRates(Common):
@@ -51,7 +57,7 @@ def get_rates(self, base_cur, date_obj=None):
5157
source_url = self._source_url() + date_str
5258
response = requests.get(source_url, params=payload)
5359
if response.status_code == 200:
54-
rates = self._decode_rates(response)
60+
rates = self._decode_rates(response, date_str=date_str)
5561
return rates
5662
raise RatesNotAvailableError("Currency Rates Source Not Ready")
5763

@@ -65,7 +71,7 @@ def get_rate(self, base_cur, dest_cur, date_obj=None):
6571
source_url = self._source_url() + date_str
6672
response = requests.get(source_url, params=payload)
6773
if response.status_code == 200:
68-
rate = self._get_decoded_rate(response, dest_cur)
74+
rate = self._get_decoded_rate(response, dest_cur, date_str=date_str)
6975
if not rate:
7076
raise RatesNotAvailableError("Currency Rate {0} => {1} not available for Date {2}".format(
7177
base_cur, dest_cur, date_str))
@@ -88,7 +94,8 @@ def convert(self, base_cur, dest_cur, amount, date_obj=None):
8894
source_url = self._source_url() + date_str
8995
response = requests.get(source_url, params=payload)
9096
if response.status_code == 200:
91-
rate = self._get_decoded_rate(response, dest_cur, use_decimal=use_decimal)
97+
rate = self._get_decoded_rate(
98+
response, dest_cur, use_decimal=use_decimal, date_str=date_str)
9299
if not rate:
93100
raise RatesNotAvailableError("Currency {0} => {1} rate not available for Date {2}.".format(
94101
source_url, dest_cur, date_str))

tests/test.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ def test_get_rates_with_date(self):
3939
def test_get_rates_invalid_code(self):
4040
self.assertRaises(RatesNotAvailableError, get_rates, 'XYZ')
4141

42+
def test_get_rates_in_future(self):
43+
future = datetime.date.today() + datetime.timedelta(days=1)
44+
self.assertRaises(RatesNotAvailableError, get_rates, 'USD', future)
45+
4246

4347
class TestGetRate(TestCase):
4448
"""
@@ -67,6 +71,11 @@ def test_get_rate_with_invalid_codes(self):
6771
# raise exception for invalid currency codes
6872
self.assertRaises(RatesNotAvailableError, get_rate, 'ABCD', 'XYZ')
6973

74+
def test_get_rates_in_future(self):
75+
future = datetime.date.today() + datetime.timedelta(days=1)
76+
self.assertRaises(
77+
RatesNotAvailableError, get_rate, 'EUR', 'USD', future)
78+
7079

7180
class TestAmountConvert(TestCase):
7281
"""

0 commit comments

Comments
 (0)