diff --git a/README.rst b/README.rst index 1729dfb..1aa4c64 100644 --- a/README.rst +++ b/README.rst @@ -38,15 +38,14 @@ This examples demonstrates the most basic usage of ``sprockets.mixins.http`` .. code:: python - from tornado import gen, ioloop, web + from tornado import ioloop, web from sprockets.mixins import http class RequestHandler(http.HTTPClientMixin, web.RequestHandler): - @gen.coroutine - def get(self, *args, **kwargs): - response = yield self.http_fetch('https://api.github.com') + async def get(self, *args, **kwargs): + response = await self.http_fetch('https://api.github.com') if not response.ok: self.set_status(response.code) self.write(response.body) @@ -62,7 +61,7 @@ As with Tornado, to use the curl client which has numerous benefits: .. code:: python - from tornado import gen, httpclient, ioloop, web + from tornado import httpclient, ioloop, web from sprockets.mixins import http httpclient.AsyncHTTPClient.configure( @@ -71,9 +70,8 @@ As with Tornado, to use the curl client which has numerous benefits: class RequestHandler(http.HTTPClientMixin, web.RequestHandler): - @gen.coroutine - def get(self, *args, **kwargs): - response = yield self.http_fetch('https://api.github.com') + async def get(self, *args, **kwargs): + response = await self.http_fetch('https://api.github.com') if not response.ok: self.set_status(response.code) self.write(response.body) diff --git a/sprockets/mixins/http/__init__.py b/sprockets/mixins/http/__init__.py index 717ad88..bd9abef 100644 --- a/sprockets/mixins/http/__init__.py +++ b/sprockets/mixins/http/__init__.py @@ -5,6 +5,7 @@ A Tornado Request Handler Mixin that provides functions for making HTTP requests. """ +import asyncio import collections import logging import os @@ -13,7 +14,7 @@ import time from ietfparse import algorithms, errors, headers from sprockets.mixins.mediatype import transcoders -from tornado import gen, httpclient +from tornado import httpclient __version__ = '1.1.0' @@ -44,7 +45,7 @@ slightly higher level of functionality than Tornado's """ -class HTTPClientMixin(object): +class HTTPClientMixin: """Mixin for making http requests. Requests using the asynchronous :meth:`HTTPClientMixin.http_fetch` method """ @@ -61,22 +62,21 @@ class HTTPClientMixin(object): self.__json_transcoder = transcoders.JSONTranscoder() self.__msgpack_transcoder = transcoders.MsgPackTranscoder() - @gen.coroutine - def http_fetch(self, url, - method='GET', - request_headers=None, - body=None, - content_type=CONTENT_TYPE_MSGPACK, - follow_redirects=False, - max_redirects=MAX_REDIRECTS, - connect_timeout=DEFAULT_CONNECT_TIMEOUT, - request_timeout=DEFAULT_REQUEST_TIMEOUT, - max_http_attempts=MAX_HTTP_RETRIES, - auth_username=None, - auth_password=None, - user_agent=None, - validate_cert=True, - allow_nonstandard_methods=False): + async def http_fetch(self, url, + method='GET', + request_headers=None, + body=None, + content_type=CONTENT_TYPE_MSGPACK, + follow_redirects=False, + max_redirects=MAX_REDIRECTS, + connect_timeout=DEFAULT_CONNECT_TIMEOUT, + request_timeout=DEFAULT_REQUEST_TIMEOUT, + max_http_attempts=MAX_HTTP_RETRIES, + auth_username=None, + auth_password=None, + user_agent=None, + validate_cert=True, + allow_nonstandard_methods=False): """Perform a HTTP request Will retry up to ``self.MAX_HTTP_RETRIES`` times. @@ -127,7 +127,7 @@ class HTTPClientMixin(object): method, url, attempt + 1, max_http_attempts, request_headers) try: - response = yield client.fetch( + response = await client.fetch( url, method=method, headers=request_headers, @@ -155,24 +155,22 @@ class HTTPClientMixin(object): method, url, response.code, attempt + 1, max_http_attempts, warning_header) if 200 <= response.code < 400: - raise gen.Return( - HTTPResponse( + return HTTPResponse( True, response.code, dict(response.headers), self._http_resp_deserialize(response), - response, attempt + 1, time.time() - start_time)) + response, attempt + 1, time.time() - start_time) elif response.code in {423, 429}: - yield self._http_resp_rate_limited(response) + await self._http_resp_rate_limited(response) elif 400 <= response.code < 500: error = self._http_resp_error_message(response) LOGGER.debug('HTTP Response Error for %s to %s' 'attempt %i of %i (%s): %s', method, url, response.code, attempt + 1, max_http_attempts, error) - raise gen.Return( - HTTPResponse( + return HTTPResponse( False, response.code, dict(response.headers), error, response, attempt + 1, - time.time() - start_time)) + time.time() - start_time) elif response.code >= 500: LOGGER.error('HTTP Response Error for %s to %s, ' 'attempt %i of %i (%s): %s', @@ -183,16 +181,14 @@ class HTTPClientMixin(object): LOGGER.warning('HTTP Get %s failed after %i attempts', url, max_http_attempts) if response: - raise gen.Return( - HTTPResponse( + return HTTPResponse( False, response.code, dict(response.headers), self._http_resp_error_message(response) or response.body, response, max_http_attempts, - time.time() - start_time)) - raise gen.Return( - HTTPResponse( + time.time() - start_time) + return HTTPResponse( False, 599, None, None, None, max_http_attempts, - time.time() - start_time)) + time.time() - start_time) def _http_req_apply_default_headers(self, request_headers, content_type, body): @@ -321,4 +317,4 @@ class HTTPClientMixin(object): """ duration = int(response.headers.get('Retry-After', 3)) LOGGER.warning('Rate Limited by, retrying in %i seconds', duration) - return gen.sleep(duration) + return asyncio.sleep(duration) diff --git a/tests.py b/tests.py index 2d2ddd8..c71564b 100644 --- a/tests.py +++ b/tests.py @@ -110,7 +110,7 @@ class TestHandler(web.RequestHandler): class MixinTestCase(testing.AsyncHTTPTestCase): def setUp(self): - super(MixinTestCase, self).setUp() + super().setUp() self.correlation_id = str(uuid.uuid4()) self.mixin = self.create_mixin()