Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 43 additions & 16 deletions forex_python/converter.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import os
from decimal import Decimal
import simplejson as json

import requests
import simplejson as json


class RatesNotAvailableError(Exception):
Expand All @@ -11,6 +12,13 @@ class RatesNotAvailableError(Exception):
pass


class BaseCurrencyAccessRestricted(Exception):
"""
Custome Exception if access key doesn't have permission to change base currency
"""
pass


class DecimalFloatMismatchError(Exception):
"""
A float has been supplied when force_decimal was set to True
Expand All @@ -20,11 +28,12 @@ class DecimalFloatMismatchError(Exception):

class Common:

def __init__(self, force_decimal=False):
def __init__(self, force_decimal=False, use_https=False):
self._force_decimal = force_decimal
self.protocol = "https://" if use_https else "http://"

def _source_url(self):
return "https://api.ratesapi.io/api/"
return self.protocol + "api.exchangeratesapi.io/v1/"

def _get_date_string(self, date_obj):
if date_obj is None:
Expand All @@ -44,15 +53,23 @@ def _get_decoded_rate(self, response, dest_cur, use_decimal=False):


class CurrencyRates(Common):
def __init__(self, access_key, use_https=False, force_decimal=False):
super().__init__(force_decimal, use_https)
self.access_key = access_key

def get_rates(self, base_cur, date_obj=None):
date_str = self._get_date_string(date_obj)
payload = {'base': base_cur, 'rtype': 'fpy'}
source_url = self._source_url() + date_str
response = requests.get(source_url, params=payload)

source_url = self._source_url() + date_str \
+ "?access_key=%s" % self.access_key \
+ "&base=%s" % base_cur
response = requests.get(source_url)
if response.status_code == 200:
rates = self._decode_rates(response)
return rates
if response.json()['error']['code'] == "base_currency_access_restricted":
raise BaseCurrencyAccessRestricted("Source currency switching is not allowed with this access "
"key")
raise RatesNotAvailableError("Currency Rates Source Not Ready")

def get_rate(self, base_cur, dest_cur, date_obj=None):
Expand All @@ -61,15 +78,20 @@ def get_rate(self, base_cur, dest_cur, date_obj=None):
return Decimal(1)
return 1.
date_str = self._get_date_string(date_obj)
payload = {'base': base_cur, 'symbols': dest_cur, 'rtype': 'fpy'}
source_url = self._source_url() + date_str
response = requests.get(source_url, params=payload)
source_url = self._source_url() + date_str \
+ "?access_key=%s" % self.access_key \
+ "&base=%s" % base_cur \
+ "&symbols=%s" % dest_cur
response = requests.get(source_url)
if response.status_code == 200:
rate = self._get_decoded_rate(response, dest_cur)
if not rate:
raise RatesNotAvailableError("Currency Rate {0} => {1} not available for Date {2}".format(
base_cur, dest_cur, date_str))
return rate
if response.json()['error']['code'] == "base_currency_access_restricted":
raise BaseCurrencyAccessRestricted("Source currency switching is not allowed with this access "
"key")
raise RatesNotAvailableError("Currency Rates Source Not Ready")

def convert(self, base_cur, dest_cur, amount, date_obj=None):
Expand All @@ -84,9 +106,10 @@ def convert(self, base_cur, dest_cur, amount, date_obj=None):
return float(amount)

date_str = self._get_date_string(date_obj)
payload = {'base': base_cur, 'symbols': dest_cur, 'rtype': 'fpy'}
source_url = self._source_url() + date_str
response = requests.get(source_url, params=payload)
source_url = self._source_url() + date_str + "?access_key=%s" % self.access_key \
+ "&base=%s" % base_cur \
+ "&symbols=%s" % dest_cur
response = requests.get(source_url)
if response.status_code == 200:
rate = self._get_decoded_rate(response, dest_cur, use_decimal=use_decimal)
if not rate:
Expand All @@ -96,11 +119,16 @@ def convert(self, base_cur, dest_cur, amount, date_obj=None):
converted_amount = rate * amount
return converted_amount
except TypeError:
raise DecimalFloatMismatchError("convert requires amount parameter is of type Decimal when force_decimal=True")
raise DecimalFloatMismatchError(
"convert requires amount parameter is of type Decimal when force_decimal=True")
if response.json()['error']['code'] == "base_currency_access_restricted":
raise BaseCurrencyAccessRestricted("Source currency switching is not allowed with this access "
"key")
raise RatesNotAvailableError("Currency Rates Source Not Ready")


_CURRENCY_FORMATTER = CurrencyRates()
# Please add your access key here
_CURRENCY_FORMATTER = CurrencyRates("your_access_key")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the access key should be read from on environtment variable.
This will allow to make it work without alterint the source code.

Probably the same should be done to activate the SSL access.


get_rates = _CURRENCY_FORMATTER.get_rates
get_rate = _CURRENCY_FORMATTER.get_rate
Expand All @@ -114,7 +142,7 @@ def __init__(self):

def _get_data(self, currency_code):
file_path = os.path.dirname(os.path.abspath(__file__))
with open(file_path+'/raw_data/currencies.json') as f:
with open(file_path + '/raw_data/currencies.json') as f:
currency_data = json.loads(f.read())
currency_dict = next((item for item in currency_data if item["cc"] == currency_code), None)
return currency_dict
Expand Down Expand Up @@ -147,7 +175,6 @@ def get_currency_code_from_symbol(self, symbol):

_CURRENCY_CODES = CurrencyCodes()


get_symbol = _CURRENCY_CODES.get_symbol
get_currency_name = _CURRENCY_CODES.get_currency_name
get_currency_code_from_symbol = _CURRENCY_CODES.get_currency_code_from_symbol
2 changes: 1 addition & 1 deletion tests/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ class TestForceDecimalAmountConvert(TestCase):
"""

def setUp(self):
self.c = CurrencyRates(force_decimal=True)
self.c = CurrencyRates("your_access_key", force_decimal=True)

def test_amount_decimal_convert(self):
amount = self.c.convert('USD', 'INR', Decimal('10.45'))
Expand Down