Skip to content

Commit

Permalink
Rebased with master and updated everything to be CBPRO instead of GDA…
Browse files Browse the repository at this point in the history
…X. Updated to check errors in send_message instead of _get
  • Loading branch information
bpross committed Nov 30, 2018
1 parent e0467b1 commit 6d020e7
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 433 deletions.
32 changes: 13 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,6 @@ time.sleep(10)
order_book.close()
```

<<<<<<< HEAD
### Testing
Unit tests are under development using the pytest framework. Contributions are
welcome!
Expand All @@ -365,37 +364,32 @@ directory run:
python -m pytest
```

## Change Log
*1.1.2* **Current PyPI release**
- Refactor project for Coinbase Pro
- Major overhaul on how pagination is handled

*1.0*
=======
### Error Handling
Error handling has been added in version 2.0. Currently, the only HTTP error codes that
are handled are the ones documented on the GDAX API error section: [here](https://docs.gdax.com/?python#errors)

- HTTP STATUS CODE 400: Raises InvalidGdaxRequest
- HTTP STATUS CODE 401: Raises UnauthorizedGdaxRequest
- HTTP STATUS CODE 403: Raises ForbiddenGdaxRequest
- HTTP STATUS CODE 404: Raises NotFoundGdaxRequest
- HTTP STATUS CODE 429: Raises GdaxRateLimitRequest
- HTTP STATUS CODE 4XX: Raises UnknownGdaxClientRequest
- HTTP STATUS CODE 5XX: Raises InternalErrorGdaxRequest
- HTTP STATUS CODE 400: Raises InvalidCbproRequest
- HTTP STATUS CODE 401: Raises UnauthorizedCbproRequest
- HTTP STATUS CODE 403: Raises ForbiddenCbproRequest
- HTTP STATUS CODE 404: Raises NotFoundCbproRequest
- HTTP STATUS CODE 429: Raises CbproRateLimitRequest
- HTTP STATUS CODE 4XX: Raises UnknownCbproClientRequest
- HTTP STATUS CODE 5XX: Raises InternalErrorCbproRequest

All HTTP requests from both the public client and authenticated client run through `_determine_response`, which
either returns the JSON body or raises the appropriate error.

Please consider creating new Exception classes and mapping as Gdax error states are discovered.

Please consider creating new Exception classes and mapping as Cbpro error states are discovered.

## Change Log
*2.0*
- Added error handling to all HTTP requests [Error Handling Docs](#error-handling)

*1.0* **Current PyPI release**
>>>>>>> Added README info, added self to contributors, bumped version
*1.1.2* **Current PyPI release**
- Refactor project for Coinbase Pro
- Major overhaul on how pagination is handled

*1.0*
- The first release that is not backwards compatible
- Refactored to follow PEP 8 Standards
- Improved Documentation
Expand Down
1 change: 1 addition & 0 deletions cbpro/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
from cbpro.websocket_client import WebsocketClient
from cbpro.order_book import OrderBook
from cbpro.cbpro_auth import CBProAuth
from cbpro.exceptions import InvalidCbproRequest, UnauthorizedCbproRequest, ForbiddenCbproRequest, NotFoundCbproRequest, CbproRateLimitRequest, UnknownCbproClientRequest, InternalErrorCbproRequest
81 changes: 81 additions & 0 deletions cbpro/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
class CbproException(Exception):
"""
Base Coinbase Pro Exception
Raised when Bad Response returned from Coinbase Pro
See: https://docs.pro.coinbase.com/?r=1#errors
"""

def __init__(self, message, code):
"""
:param message: Message from Coinbase Pro response
:type message: str
:param code: HTTP Code
:type code: int
"""
self._message = message
self._code = code

@property
def message(self):
return self._message

@message.setter
def message(self, message):
self._message = message

@property
def code(self):
return self._code

@message.setter
def code(self, code):
self._code = code


class InvalidCbproRequest(CbproException):
"""
Raised on 400 response from Coinbase Pro
"""
pass


class UnauthorizedCbproRequest(CbproException):
"""
Raised on 401 response from Coinbase Pro
"""
pass


class ForbiddenCbproRequest(CbproException):
"""
Raised on 403 response from Coinbase Pro
"""
pass


class NotFoundCbproRequest(CbproException):
"""
Raised on 404 response from Coinbase Pro
"""
pass


class CbproRateLimitRequest(CbproException):
"""
Raised on 429 response from Coinbase Pro
"""
pass


class UnknownCbproClientRequest(CbproException):
"""
Raised on 4XX responses not tracked
"""
pass


class InternalErrorCbproRequest(CbproException):
"""
Raised on 500 response from Coinbase Pro
"""
pass
30 changes: 12 additions & 18 deletions cbpro/public_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from http import HTTPStatus
import requests
from gdax import exceptions
from cbpro import exceptions


class PublicClient(object):
Expand Down Expand Up @@ -46,45 +46,39 @@ def _is_http_server_error(self, code):

def _determine_response(self, response):
"""
Determines if GDAX response is success or error
Determines if CBPRO response is success or error
If success, returns response json
If error, raises appropriate GdaxException
If error, raises appropriate CbproException
"""
if self._is_http_success(response.status_code):
return response.json()
elif self._is_http_client_error(response.status_code):
body = response.json()
message = body.get('message')
if response.status_code == HTTPStatus.BAD_REQUEST:
raise exceptions.InvalidGdaxRequest(message,
raise exceptions.InvalidCbproRequest(message,
HTTPStatus.BAD_REQUEST)
elif response.status_code == HTTPStatus.UNAUTHORIZED:
raise exceptions.UnauthorizedGdaxRequest(message,
raise exceptions.UnauthorizedCbproRequest(message,
HTTPStatus.UNAUTHORIZED)
elif response.status_code == HTTPStatus.FORBIDDEN:
raise exceptions.ForbiddenGdaxRequest(message,
raise exceptions.ForbiddenCbproRequest(message,
HTTPStatus.FORBIDDEN)
elif response.status_code == HTTPStatus.NOT_FOUND:
raise exceptions.NotFoundGdaxRequest(message,
raise exceptions.NotFoundCbproRequest(message,
HTTPStatus.NOT_FOUND)
elif response.status_code == HTTPStatus.TOO_MANY_REQUESTS:
raise exceptions.GdaxRateLimitRequest(message,
raise exceptions.CbproRateLimitRequest(message,
HTTPStatus.TOO_MANY_REQUESTS)
else: # Other 4XX response not yet mapped
raise exceptions.UnknownGdaxClientRequest(message,
raise exceptions.UnknownCbproClientRequest(message,
response.status_code)

elif self._is_http_server_error(response.status_code):
body = response.json()
raise exceptions.InternalErrorGdaxRequest(body.get('message'),
raise exceptions.InternalErrorCbproRequest(body.get('message'),
HTTPStatus.INTERNAL_SERVER_ERROR)

def _get(self, path, params=None):
"""Perform get request"""

r = requests.get(self.url + path, params=params, timeout=self.timeout)
return self._determine_response(r)

def get_products(self):
"""Get a list of available currency pairs for trading.
Expand Down Expand Up @@ -323,7 +317,7 @@ def _send_message(self, method, endpoint, params=None, data=None):
url = self.url + endpoint
r = self.session.request(method, url, params=params, data=data,
auth=self.auth, timeout=30)
return r.json()
return self._determine_response(r)

def _send_paginated_message(self, endpoint, params=None):
""" Send API message that results in a paginated response.
Expand Down Expand Up @@ -353,7 +347,7 @@ def _send_paginated_message(self, endpoint, params=None):
url = self.url + endpoint
while True:
r = self.session.get(url, params=params, auth=self.auth, timeout=30)
results = r.json()
results = self._determine_response(r)
for result in results:
yield result
# If there are no more pages, we're done. Otherwise update `after`
Expand Down
Loading

0 comments on commit 6d020e7

Please sign in to comment.