From 2668ef604a7b9e24894c7a162f3bfb412363597e Mon Sep 17 00:00:00 2001 From: David McMackins II Date: Fri, 27 May 2016 19:52:42 -0500 Subject: Improve exception handling --- cfetch/__init__.py | 35 +++++++++++++++++++++++++++-------- cfetch/plugins/bitcoinaverage.py | 11 ++++++----- cfetch/plugins/bitstamp.py | 7 ++++--- cfetch/plugins/bter.py | 18 ++++++++++++++++-- cfetch/plugins/ccc.py | 15 ++++++++++++++- coinfetch | 13 ++++++------- 6 files changed, 73 insertions(+), 26 deletions(-) diff --git a/cfetch/__init__.py b/cfetch/__init__.py index 281555a..ad01e57 100644 --- a/cfetch/__init__.py +++ b/cfetch/__init__.py @@ -23,6 +23,12 @@ from requests import get __version__ = '5.2.0' +class NoSuchPairException(Exception): + pass + +class NoSuchKindException(Exception): + pass + ## A cryptocurrency exchange rate ticker. class Ticker(): ## Constructor for this class. @@ -47,9 +53,25 @@ class Ticker(): else: raise TypeError('pair cannot be {}'.format(type(pair))) - def _get_single_rate(self, a, b, amt, power, kind): + ## Gets the exchange rate between two currencies raised to a power. + # @param a The first currency. + # @param b The second currency. + # @param amt The number quantity of 'a' currency. + # @param power The power to which the calculation will be raised. + # @param kind The type of rate to calculate. + # @return The exchange rate between 'a' and 'b' currencies raised to + # 'power'. + def get_rate_pow(self, a, b, amt, power, kind): r = get(self.path + self.get_pair(a, b)) - res = self.get_pair_data(r, (a, b)) + + try: + res = self.get_pair_data(r, (a, b)) + except KeyError as e: + raise NoSuchPairException(str(e)) + + if kind not in res: + raise NoSuchKindException(kind) + return (float(res[kind]) ** power) * amt ## Calculates the exchange rate between two currencies. @@ -60,12 +82,9 @@ class Ticker(): # @return The exchange rate between 'a' and 'b' currencies. def get_rate(self, a, b, amt=1, kind='avg'): try: - return self._get_single_rate(a, b, amt, 1, kind) - except (KeyError, TypeError): - try: - return self._get_single_rate(b, a, amt, -1, kind) - except (KeyError, TypeError) as e: - raise ValueError(str(e)) # currency pair not found + return self.get_rate_pow(a, b, amt, 1, kind) + except NoSuchPairException: + return self.get_rate_pow(b, a, amt, -1, kind) _INDEX = { 'description': 0, diff --git a/cfetch/plugins/bitcoinaverage.py b/cfetch/plugins/bitcoinaverage.py index df1cebd..2e045af 100644 --- a/cfetch/plugins/bitcoinaverage.py +++ b/cfetch/plugins/bitcoinaverage.py @@ -15,7 +15,8 @@ ## along with this program. If not, see . ## -from cfetch import register_ticker, Ticker +from cfetch import register_ticker, NoSuchKindException, NoSuchPairException +from cfetch import Ticker from requests import get class BitcoinAverageTicker(Ticker): @@ -28,7 +29,7 @@ class BitcoinAverageTicker(Ticker): def get_rate(self, a, b, amt=1, kind='24h_avg'): a = a.upper() b = b.upper() - if 'BTC' not in (a, b): + if 'BTC' not in (a, b) or 'USD' not in (a, b): self._fail(a, b) r = get(self.path) @@ -47,11 +48,11 @@ class BitcoinAverageTicker(Ticker): res = res[a] return (float(res[kind]) ** -1) * amt - except (KeyError, TypeError) as e: - raise ValueError(str(e)) + except KeyError as e: + raise NoSuchKindException(str(e)) def _fail(self, a, b): - raise ValueError('{}/{}'.format(a, b)) + raise NoSuchPairException('{}/{}'.format(a, b)) register_ticker('ba', 'The BitcoinAverage ticker (built-in)', BitcoinAverageTicker('https://api.bitcoinaverage.com/ticker/all')) diff --git a/cfetch/plugins/bitstamp.py b/cfetch/plugins/bitstamp.py index 7af3883..c808995 100644 --- a/cfetch/plugins/bitstamp.py +++ b/cfetch/plugins/bitstamp.py @@ -15,7 +15,8 @@ ## along with this program. If not, see . ## -from cfetch import register_ticker, Ticker +from cfetch import register_ticker, NoSuchKindException, NoSuchPairException +from cfetch import Ticker from requests import get class BitstampTicker(Ticker): @@ -29,14 +30,14 @@ class BitstampTicker(Ticker): r = get(self.path) res = self.get_pair_data(r) if kind not in res: - raise ValueError('Kind {} not available'.format(kind)) + raise NoSuchKindException('Kind {} not available'.format(kind)) if a == 'btc' and b == 'usd': return float(res[kind]) * amt elif a == 'usd' and b == 'btc': return (float(res[kind]) ** -1) * amt else: - raise ValueError('{}/{}'.format(a, b)) + raise NoSuchPairException('{}/{}'.format(a, b)) register_ticker('bs', 'The Bitstamp ticker (built-in)', BitstampTicker('https://www.bitstamp.net/api/ticker/')) diff --git a/cfetch/plugins/bter.py b/cfetch/plugins/bter.py index e18c9f1..2346591 100644 --- a/cfetch/plugins/bter.py +++ b/cfetch/plugins/bter.py @@ -1,6 +1,6 @@ ## ## coinfetch-api-bter - BTer API plugin for coinfetch -## Copyright (C) 2015 Delwink, LLC +## Copyright (C) 2015-2016 Delwink, LLC ## ## This program is free software: you can redistribute it and/or modify ## it under the terms of the GNU Affero General Public License as published by @@ -15,11 +15,25 @@ ## along with this program. If not, see . ## -from cfetch import register_ticker, Ticker +from cfetch import register_ticker, NoSuchKindException, NoSuchPairException +from cfetch import Ticker +from requests import get class BterTicker(Ticker): def get_pair_data(self, response, pair=None): return response.json() + def get_rate_pow(self, a, b, amt, power, kind): + r = get(self.path + self.get_pair(a, b)) + res = self.get_pair_data(r) + + if kind not in res: + if res['result'] == 'false': + raise NoSuchPairException('{}/{}'.format(a, b)) + + raise NoSuchKindException(kind) + + return (float(res[kind]) ** power) * amt + register_ticker('bter', 'The BTer ticker (built-in)', BterTicker('http://data.bter.com/api/1/ticker/')) diff --git a/cfetch/plugins/ccc.py b/cfetch/plugins/ccc.py index 07bdb99..3104c46 100644 --- a/cfetch/plugins/ccc.py +++ b/cfetch/plugins/ccc.py @@ -15,7 +15,8 @@ ## along with this program. If not, see . ## -from cfetch import register_ticker, Ticker +from cfetch import register_ticker, NoSuchKindException, NoSuchPairException +from cfetch import Ticker class CccTicker(Ticker): def __init__(self, path): @@ -24,6 +25,18 @@ class CccTicker(Ticker): def get_pair_data(self, response, pair=None): return response.json() + def get_rate_pow(self, a, b, amt, power, kind): + r = get(self.path + self.get_pair(a, b)) + res = self.get_pair_data(r, (a, b)) + + if kind not in res: + raise NoSuchKindException(kind) + + if res[kind] is None: + raise NoSuchPairException('{}/{}'.format(a, b)) + + return (float(res[kind]) ** power) * amt + def get_rate(self, a, b, amt=1, kind='price'): return super().get_rate(a, b, amt, kind) diff --git a/coinfetch b/coinfetch index 6618ed6..8edd10b 100755 --- a/coinfetch +++ b/coinfetch @@ -19,7 +19,8 @@ from argparse import Action, ArgumentParser from configparser import ConfigParser from cfetch import __version__, get_ticker, get_registered_tickers -from cfetch import load_default_plugins +from cfetch import load_default_plugins, NoSuchKindException +from cfetch import NoSuchPairException from os.path import expanduser, join, exists from os import makedirs @@ -105,12 +106,10 @@ try: rate = ticker.get_rate(*rate_args) print(format(rate, '.8f')) -except ValueError: - if args.kind: - print('The', args.kind, 'rate is not available with the', args.api, - 'API.') - exit(10) - +except NoSuchKindException: + print('The', args.kind, 'rate is not available with the', args.api, 'API.') + exit(10) +except NoSuchPairException: pair = '/'.join([args.src, args.dest]) print('The pair', pair, 'was not found using the', args.api, 'API.') exit(11) -- cgit v1.2.3