diff --git a/oandapy/__init__.py b/oandapy/__init__.py index d24db84..9921375 100644 --- a/oandapy/__init__.py +++ b/oandapy/__init__.py @@ -1,3 +1,3 @@ from .oandapy import API -from .exceptions import OandaError, BadEnvironment +from .exceptions import OandaError, BadEnvironment, ClientError from .stream.stream import Streamer diff --git a/oandapy/exceptions.py b/oandapy/exceptions.py index b19a76f..c2d0358 100644 --- a/oandapy/exceptions.py +++ b/oandapy/exceptions.py @@ -13,6 +13,28 @@ def __init__(self, error_response): super(OandaError, self).__init__(msg) +class ClientError(Exception): + """Client error class. + + Lookup the error in a list of known errors. If it is not there + make it "Unknown". Additional message information can be appended + by passing additionMsg="..." + """ + __eid = { + "204": "No data", + "Unknown": "Unknown error" + } + + def __init__(self, error, additionalMsg=""): + errmsg = self.__eid['Unknown'] + if str(error) in self.__eid: + errmsg = self.__eid[str(error)] + msg = "client error: {}".format(errmsg) + if additionalMsg: + msg += additionalMsg + super(ClientError, self).__init__(msg) + + class BadEnvironment(Exception): """environment should be: sandbox, practice or live.""" def __init__(self, environment): diff --git a/oandapy/oandapy.py b/oandapy/oandapy.py index e75a6af..7af9511 100644 --- a/oandapy/oandapy.py +++ b/oandapy/oandapy.py @@ -1,6 +1,6 @@ import json import requests -from .exceptions import BadEnvironment, OandaError +from .exceptions import BadEnvironment, OandaError, ClientError """ OANDA API wrapper for OANDA's REST API """ @@ -268,7 +268,14 @@ def request(self, endpoint, method='GET', params=None): print (str(e)) content = response.content.decode('utf-8') - content = json.loads(content) + # we should have content: either data or an error description + if not response.content: + raise ClientError(response.status_code) + + try: + content = json.loads(content) + except Exception as e: + raise ClientError(response.status_code, "{}".format(e)) # error message if response.status_code >= 400: diff --git a/tests/test_exception.py b/tests/test_exception.py new file mode 100644 index 0000000..2357485 --- /dev/null +++ b/tests/test_exception.py @@ -0,0 +1,55 @@ +import unittest +import oandapy +import sys +from datetime import datetime +from . import unittestsetup +from .unittestsetup import environment as environment + +try: + from nose_parameterized import parameterized, param +except: + print("*** Please install 'nose_parameterized' to run these tests ***") + exit(0) + +access_token = None +account = None +api = None + + +class TestClientError(unittest.TestCase): + + def setUp(self): + global access_token + global account + global api + + try: + account, access_token = unittestsetup.auth() + except Exception as e: + print("%s" % e) + exit(0) + + api = oandapy.API(environment=environment, access_token=access_token) + + def test_client_exception(self): + """test ClientError.""" + instrument = 'EUR_USD' + start = datetime(1990, 1, 1, 16, 0, 1) + end = datetime(1990, 1, 3, 16, 0, 1) + + clErr = None + with self.assertRaises(oandapy.ClientError) as clErr: + candles = api.get_history( + instrument=instrument, + granularity='M1', + candleFormat='midpoint', + alignmentTimezone='GMT', + start=start.isoformat(), + end=end.isoformat() + ) + self.assertEqual("{}".format(clErr.exception), "client error: No data") + + +if __name__ == "__main__": + + unittest.main()