From 695134d5e35b11a828bcf4cebade2cdbd3839461 Mon Sep 17 00:00:00 2001 From: rintaro Date: Tue, 20 Mar 2018 15:54:58 +0900 Subject: [PATCH 1/3] add async API --- pybitflyer/async.py | 61 +++++++++++++++++++++++++++++++++++++++++++++ setup.py | 2 +- 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 pybitflyer/async.py diff --git a/pybitflyer/async.py b/pybitflyer/async.py new file mode 100644 index 0000000..8c8fc5e --- /dev/null +++ b/pybitflyer/async.py @@ -0,0 +1,61 @@ +import time +import json +import hmac +import urllib +import hashlib +import asyncio +import aiohttp +import pybitflyer + + +class API(pybitflyer.API): + + def __init__(self, api_key=None, api_secret=None, timeout=None, loop=None): + super(API, self).__init__(api_key, api_secret, timeout) + self.loop = loop if loop else asyncio.get_event_loop() + + def _create_header_and_body(self, endpoint, method, params): + if method == "POST": + body = json.dumps(params) + else: + if params: + body = "?" + urllib.parse.urlencode(params) + else: + body = "" + + if self.api_key and self.api_secret: + access_timestamp = str(time.time()) + api_secret = str.encode(self.api_secret) + text = str.encode(access_timestamp + method + endpoint + body) + access_sign = hmac.new(api_secret, + text, + hashlib.sha256).hexdigest() + auth_header = { + "ACCESS-KEY": self.api_key, + "ACCESS-TIMESTAMP": access_timestamp, + "ACCESS-SIGN": access_sign, + "Content-Type": "application/json" + } + + else: + auth_header = {} + + return auth_header, body + + # override + async def request(self, endpoint, method="GET", params=None): + url = self.api_url + endpoint + header, body = self._create_header_and_body(endpoint, method, params) + async with aiohttp.ClientSession(loop=self.loop) as s: + try: + if method == 'GET': + async with s.get(url, params=params, timeout=self.timeout, headers=header) as r: + contents_json = await r.json() + return contents_json + else: # method == "POST": + async with s.post(url, data=json.dumps(params), timeout=self.timeout, headers=header) as r: + contents_json = await r.json() + return contents_json + except Exception as e: + print(e) + raise e diff --git a/setup.py b/setup.py index 45ba9ff..463a931 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ author="yag_ays", author_email="yanagi.ayase@gmail.com", url="https://github.com/yagays/pybitflyer", - install_requires=['requests'], + install_requires=['requests', 'aiohttp'], keywords=["bitcoin", "bitflyer", "wrapper", "REST API"], classifiers=[ "Programming Language :: Python", From 89e14abda981820e327c9ead15bd55a1f393e87a Mon Sep 17 00:00:00 2001 From: rintaro Date: Sun, 25 Mar 2018 15:05:37 +0900 Subject: [PATCH 2/3] update README --- README.rst | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/README.rst b/README.rst index 4042c9a..20311dc 100644 --- a/README.rst +++ b/README.rst @@ -67,6 +67,31 @@ You need to specify API key and API Secret by creating pybitflyer.API instance. time_in_force="GTC" ) +Async Module +~~~~~~~~~~~~ + +If you use Python 3.5.3 or higher, you can use asynchronous client. + +.. code:: python + + import asyncio + import pybitflyer.async + + loop = asyncio.get_event_loop() + api = pybitflyer.async.API(loop=loop) + + # send a single request + loop.run_until_complete(api.ticker()) + + # you can send multiple requests asynchronously + coros = [api.gethealth(), api.ticker()] + results = loop.run_until_complete(asyncio.gather(*coros)) + # the results are stored in the same order as coros + for result in results: + print(result) + + + More detail ~~~~~~~~~~~ From 2ada76df178bad49286fe782809d3d9dc3a447e3 Mon Sep 17 00:00:00 2001 From: rintaro Date: Sun, 25 Mar 2018 20:29:48 +0900 Subject: [PATCH 3/3] fix case of empty response --- pybitflyer/async.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/pybitflyer/async.py b/pybitflyer/async.py index 8c8fc5e..e2f3be6 100644 --- a/pybitflyer/async.py +++ b/pybitflyer/async.py @@ -50,12 +50,18 @@ async def request(self, endpoint, method="GET", params=None): try: if method == 'GET': async with s.get(url, params=params, timeout=self.timeout, headers=header) as r: - contents_json = await r.json() - return contents_json + try: + contents = await r.json() + except: + contents = await r.text() + return contents else: # method == "POST": async with s.post(url, data=json.dumps(params), timeout=self.timeout, headers=header) as r: - contents_json = await r.json() - return contents_json + try: + contents = await r.json() + except: + contents = await r.text() + return contents except Exception as e: print(e) raise e