From abeeb4612b33647df49820f6795b36655ccc795f Mon Sep 17 00:00:00 2001 From: Jason Woodrich Date: Thu, 13 Dec 2018 12:01:50 -0700 Subject: [PATCH 1/2] Implement optional timeouts for REST API requests, add check and exception for rate limits. --- pytumblr/__init__.py | 4 ++-- pytumblr/request.py | 30 ++++++++++++++++++++++++++---- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/pytumblr/__init__.py b/pytumblr/__init__.py index ddeb956..707d80a 100644 --- a/pytumblr/__init__.py +++ b/pytumblr/__init__.py @@ -10,7 +10,7 @@ class TumblrRestClient(object): A Python Client for the Tumblr API """ - def __init__(self, consumer_key, consumer_secret="", oauth_token="", oauth_secret="", host="https://api.tumblr.com"): + def __init__(self, consumer_key, consumer_secret="", oauth_token="", oauth_secret="", host="https://api.tumblr.com", connect_timeout=None, read_timeout=None): """ Initializes the TumblrRestClient object, creating the TumblrRequest object which deals with all request formatting. @@ -28,7 +28,7 @@ def __init__(self, consumer_key, consumer_secret="", oauth_token="", oauth_secre :returns: None """ - self.request = TumblrRequest(consumer_key, consumer_secret, oauth_token, oauth_secret, host) + self.request = TumblrRequest(consumer_key, consumer_secret, oauth_token, oauth_secret, host, connect_timeout=connect_timeout, read_timeout=read_timeout) def info(self): """ diff --git a/pytumblr/request.py b/pytumblr/request.py index 05f4445..250a689 100644 --- a/pytumblr/request.py +++ b/pytumblr/request.py @@ -11,6 +11,19 @@ from requests.exceptions import TooManyRedirects, HTTPError +class RateLimitError(IOError): + """Thrown when errors related to rate limiting occur.""" + + def __init__(self, *args, **kwargs): + """Initialize RateLimitError with `request` and `response` objects.""" + response = kwargs.pop('response', None) + self.response = response + self.request = kwargs.pop('request', None) + if (response is not None and not self.request and + hasattr(response, 'request')): + self.request = self.response.request + super(RateLimitError, self).__init__(*args, **kwargs) + class TumblrRequest(object): """ A simple request object that lets us query the Tumblr API @@ -18,7 +31,7 @@ class TumblrRequest(object): __version = "0.0.8" - def __init__(self, consumer_key, consumer_secret="", oauth_token="", oauth_secret="", host="https://api.tumblr.com"): + def __init__(self, consumer_key, consumer_secret="", oauth_token="", oauth_secret="", host="https://api.tumblr.com", connect_timeout=None, read_timeout=None): self.host = host self.oauth = OAuth1( consumer_key, @@ -27,6 +40,7 @@ def __init__(self, consumer_key, consumer_secret="", oauth_token="", oauth_secre resource_owner_secret=oauth_secret ) self.consumer_key = consumer_key + self.timeout=(connect_timeout,read_timeout) if connect_timeout or read_timeout else None self.headers = { "User-Agent": "pytumblr/" + self.__version, @@ -46,7 +60,9 @@ def get(self, url, params): url = url + "?" + urllib.parse.urlencode(params) try: - resp = requests.get(url, allow_redirects=False, headers=self.headers, auth=self.oauth) + resp = requests.get(url, allow_redirects=False, headers=self.headers, auth=self.oauth, timeout=self.timeout) + if resp.status_code == 429: + raise RateLimitError(resp.reason, response=resp) except TooManyRedirects as e: resp = e.response @@ -71,7 +87,9 @@ def post(self, url, params={}, files=[]): data = urllib.parse.urlencode(params) if not PY3: data = str(data) - resp = requests.post(url, data=data, headers=self.headers, auth=self.oauth) + resp = requests.post(url, data=data, headers=self.headers, auth=self.oauth, timeout=self.timeout) + if resp.status_code == 429: + raise RateLimitError(resp.reason, response=resp) return self.json_parse(resp) except HTTPError as e: return self.json_parse(e.response) @@ -114,6 +132,10 @@ def post_multipart(self, url, params, files): files=files, headers=self.headers, allow_redirects=False, - auth=self.oauth + auth=self.oauth, + timeout=self.timeout ) + if resp.status_code == 429: + raise RateLimitError(resp.reason, response=resp) + return self.json_parse(resp) From f6fe6ac2c1180fae18401a54ad7b22bd3bd3c59d Mon Sep 17 00:00:00 2001 From: "Jason D. Woodrich" Date: Thu, 13 Dec 2018 12:10:37 -0700 Subject: [PATCH 2/2] Add another commit to re-trigger CLA check. --- pytumblr/request.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pytumblr/request.py b/pytumblr/request.py index 250a689..3d66dd1 100644 --- a/pytumblr/request.py +++ b/pytumblr/request.py @@ -139,3 +139,5 @@ def post_multipart(self, url, params, files): raise RateLimitError(resp.reason, response=resp) return self.json_parse(resp) + +