Skip to content

Commit 82a43c4

Browse files
author
Ravi kumar
authored
Merge pull request #22 from ravigadila/bitcoin-decimal
Added force_decimal option for Bitcoin rates
2 parents 6a45e51 + b432b3b commit 82a43c4

File tree

6 files changed

+257
-45
lines changed

6 files changed

+257
-45
lines changed

README.rst

+25-1
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,37 @@ Usage Examples:
8686
>>> c.convert('USD', 'INR', 10)
8787
674.73
8888
89+
- Force use of Decimal
90+
91+
.. code-block:: python
92+
93+
python
94+
>>> from forex_python.converter import CurrencyRates
95+
>>> c = CurrencyRates(force_decimal=True)
96+
>>> c.convert('USD', 'INR', Decimal('10.45'))
97+
705.09
98+
>>> c.convert('USD', 'INR', 10)
99+
DecimalFloatMismatchError: convert requires amount parameter is of type Decimal when use_decimal=True
100+
101+
- Detect use of Decimal
102+
103+
.. code-block:: python
104+
105+
python
106+
>>> from forex_python.converter import CurrencyRates
107+
>>> c = CurrencyRates()
108+
>>> c.convert('USD', 'INR', Decimal('10.45'))
109+
705.09
110+
>>> c.convert('USD', 'INR', 10)
111+
674.73
112+
89113
- Get latest Bitcoin price.
90114

91115
.. code-block:: python
92116
93117
python
94118
>>> from forex_python.bitcoin import BtcConverter
95-
>>> b = BtcConverter()
119+
>>> b = BtcConverter() # force_decimal=True to get Decimal rates
96120
>>> b.get_latest_price('USD')
97121
533.913
98122

docs/source/usage.rst

+10-4
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,15 @@ Currency Rates
3939
>>> from forex_python.converter import CurrencyRates
4040
>>> c = CurrencyRates(force_decimal=True)
4141
>>> c.convert('USD', 'INR', Decimal('10.45'))
42-
705.09
42+
Decimal('705.09')
4343
>>> c.convert('USD', 'INR', 10)
4444
DecimalFloatMismatchError: convert requires amount parameter is of type Decimal when use_decimal=True
4545

4646
8. Detect use of Decimal::
4747
>>> from forex_python.converter import CurrencyRates
4848
>>> c = CurrencyRates()
4949
>>> c.convert('USD', 'INR', Decimal('10.45'))
50-
705.09
50+
Decimal('705.09')
5151
>>> c.convert('USD', 'INR', 10)
5252
674.73
5353

@@ -56,7 +56,7 @@ Bitcoin Prices:
5656
---------------
5757
1. Get latest price of one Bitcoin::
5858
>>> from forex_python.bitcoin import BtcConverter
59-
>>> b = BtcConverter()
59+
>>> b = BtcConverter() # add "force_decimal=True" parmeter to get Decimal rates
6060
>>> b.get_latest_price('EUR') # you can directly call get_latest_price('EUR')
6161
476.5225 # return type float
6262

@@ -94,7 +94,13 @@ Bitcoin Prices:
9494
>>> b.get_previous_price_list('INR', start_date, end_date) # get_previous_price_list('INR', start_date, end_date)
9595
{u'2016-05-19': 29371.7579, u'2016-05-18': 30402.3169, u'2016-05-22': 29586.3631, u'2016-05-23': 29925.3272, u'2016-05-20': 29864.0256, u'2016-05-21': 29884.7449}
9696

97-
8. Get Bitcoin symbol::
97+
8. Force use of Decimal::
98+
>>> from forex_python.bitcoin import BtcConverter
99+
>>> b = BtcConverter(force_decimal=True)
100+
>>> b.get_latest_price('EUR') # you can directly call get_latest_price('EUR')
101+
Decimal('942.245000000000004547') # return type Decimal
102+
103+
9. Get Bitcoin symbol::
98104
>>> print(b.get_symbol()) # get_btc_symbol()
99105
฿
100106

forex_python/bitcoin.py

+71-19
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
1+
from decimal import Decimal
2+
import simplejson as json
13
import requests
4+
from .converter import RatesNotAvailableError, DecimalFloatMismatchError
25

36

47
class BtcConverter(object):
58
"""
69
Get bit coin rates and convertion
710
"""
11+
def __init__(self, force_decimal=False):
12+
self._force_decimal = force_decimal
13+
14+
def _decode_rates(self, response, use_decimal=False):
15+
if self._force_decimal or use_decimal:
16+
decoded_data = json.loads(response.text, use_decimal=True)
17+
else:
18+
decoded_data = response.json()
19+
return decoded_data
820

921
def get_latest_price(self, currency):
1022
"""
@@ -15,6 +27,8 @@ def get_latest_price(self, currency):
1527
if response.status_code == 200:
1628
data = response.json()
1729
price = data.get('bpi').get(currency, {}).get('rate_float', None)
30+
if self._force_decimal:
31+
return Decimal(price)
1832
return price
1933
return None
2034

@@ -34,8 +48,10 @@ def get_previous_price(self, currency, date_obj):
3448
if response.status_code == 200:
3549
data = response.json()
3650
price = data.get('bpi', {}).get(start, None)
51+
if self._force_decimal:
52+
return Decimal(price)
3753
return price
38-
return None
54+
raise RatesNotAvailableError("BitCoin Rates Source Not Ready For Given date")
3955

4056
def get_previous_price_list(self, currency, start_date, end_date):
4157
"""
@@ -51,7 +67,7 @@ def get_previous_price_list(self, currency, start_date, end_date):
5167
)
5268
response = requests.get(url)
5369
if response.status_code == 200:
54-
data = response.json()
70+
data = self._decode_rates(response)
5571
price_dict = data.get('bpi', {})
5672
return price_dict
5773
return {}
@@ -60,36 +76,59 @@ def convert_to_btc(self, amount, currency):
6076
"""
6177
Convert X amount to Bit Coins
6278
"""
79+
if isinstance(amount, Decimal):
80+
use_decimal = True
81+
else:
82+
use_decimal = self._force_decimal
83+
6384
url = 'https://api.coindesk.com/v1/bpi/currentprice/{}.json'.format(currency)
6485
response = requests.get(url)
6586
if response.status_code == 200:
6687
data = response.json()
6788
price = data.get('bpi').get(currency, {}).get('rate_float', None)
6889
if price:
69-
converted_btc = amount/price
70-
return converted_btc
71-
return None
72-
return None
90+
if use_decimal:
91+
price = Decimal(price)
92+
try:
93+
converted_btc = amount/price
94+
return converted_btc
95+
except TypeError:
96+
raise DecimalFloatMismatchError("convert_to_btc requires amount parameter is of type Decimal when force_decimal=True")
97+
raise RatesNotAvailableError("BitCoin Rates Source Not Ready For Given date")
7398

7499
def convert_btc_to_cur(self, coins, currency):
75100
"""
76101
Convert X bit coins to valid currency amount
77102
"""
103+
if isinstance(coins, Decimal):
104+
use_decimal = True
105+
else:
106+
use_decimal = self._force_decimal
107+
78108
url = 'https://api.coindesk.com/v1/bpi/currentprice/{}.json'.format(currency)
79109
response = requests.get(url)
80110
if response.status_code == 200:
81111
data = response.json()
82112
price = data.get('bpi').get(currency, {}).get('rate_float', None)
83113
if price:
84-
converted_amount = coins * price
85-
return converted_amount
86-
return None
87-
return None
114+
if use_decimal:
115+
price = Decimal(price)
116+
try:
117+
converted_amount = coins * price
118+
return converted_amount
119+
except TypeError:
120+
raise DecimalFloatMismatchError("convert_btc_to_cur requires coins parameter is of type Decimal when force_decimal=True")
121+
raise RatesNotAvailableError("BitCoin Rates Source Not Ready For Given date")
88122

89123
def convert_to_btc_on(self, amount, currency, date_obj):
90124
"""
91125
Convert X amount to BTC based on given date rate
92126
"""
127+
if isinstance(amount, Decimal):
128+
use_decimal = True
129+
else:
130+
use_decimal = self._force_decimal
131+
93132
start = date_obj.strftime('%Y-%m-%d')
94133
end = date_obj.strftime('%Y-%m-%d')
95134
url = (
@@ -103,15 +142,24 @@ def convert_to_btc_on(self, amount, currency, date_obj):
103142
data = response.json()
104143
price = data.get('bpi', {}).get(start, None)
105144
if price:
106-
converted_btc = amount/price
107-
return converted_btc
108-
return None
109-
return None
145+
if use_decimal:
146+
price = Decimal(price)
147+
try:
148+
converted_btc = amount/price
149+
return converted_btc
150+
except TypeError:
151+
raise DecimalFloatMismatchError("convert_to_btc_on requires amount parameter is of type Decimal when force_decimal=True")
152+
raise RatesNotAvailableError("BitCoin Rates Source Not Ready For Given Date")
110153

111154
def convert_btc_to_cur_on(self, coins, currency, date_obj):
112155
"""
113156
Convert X BTC to valid currency amount based on given date
114157
"""
158+
if isinstance(coins, Decimal):
159+
use_decimal = True
160+
else:
161+
use_decimal = self._force_decimal
162+
115163
start = date_obj.strftime('%Y-%m-%d')
116164
end = date_obj.strftime('%Y-%m-%d')
117165
url = (
@@ -125,14 +173,18 @@ def convert_btc_to_cur_on(self, coins, currency, date_obj):
125173
data = response.json()
126174
price = data.get('bpi', {}).get(start, None)
127175
if price:
128-
converted_btc = coins*price
129-
return converted_btc
130-
return None
131-
return None
176+
if use_decimal:
177+
price = Decimal(price)
178+
try:
179+
converted_btc = coins*price
180+
return converted_btc
181+
except TypeError:
182+
raise DecimalFloatMismatchError("convert_btc_to_cur_on requires amount parameter is of type Decimal when force_decimal=True")
183+
raise RatesNotAvailableError("BitCoin Rates Source Not Ready For Given Date")
132184

133185
def get_symbol(self):
134186
"""
135-
Here is Unicode symbol for bit coin
187+
Here is Unicode symbol for bitcoin
136188
"""
137189
return "\u0E3F"
138190

forex_python/converter.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import os
2+
from decimal import Decimal
23
import simplejson as json
34
import requests
4-
from decimal import Decimal
55

66

77
class RatesNotAvailableError(Exception):

tests/test.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import datetime
2+
from decimal import Decimal
23
from unittest import TestCase
34
from forex_python.converter import (get_rates, get_rate, convert, get_symbol,
45
get_currency_name, RatesNotAvailableError,
56
CurrencyRates, DecimalFloatMismatchError)
6-
from decimal import Decimal
77

88

99
class TestGetRates(TestCase):

0 commit comments

Comments
 (0)