diff --git a/.gitignore b/.gitignore index 56fc682..e0dbc19 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,4 @@ venv /dist/* /AUTHORS /ChangeLog -/.eggs +/.eggs \ No newline at end of file diff --git a/airtable/__init__.py b/airtable/__init__.py index ab7a974..05e3e53 100644 --- a/airtable/__init__.py +++ b/airtable/__init__.py @@ -5,6 +5,7 @@ import warnings import requests +from requests.packages.urllib3.util import retry import six API_URL = 'https://api.airtable.com/v%s/' @@ -94,7 +95,10 @@ def __init__(self, base_id, api_key, dict_class=OrderedDict): def __request(self, method, url, params=None, payload=None): if method in ['POST', 'PUT', 'PATCH']: self.headers.update({'Content-type': 'application/json'}) - response = requests.request( + retries = retry.Retry(total=10, backoff_factor=1, status_forcelist=[429, 500, 502, 503, 504]) + session = requests.Session() + session.mount('https://', requests.adapters.HTTPAdapter(max_retries=retries)) + response = session.request( method, posixpath.join(self.base_url, url), params=params, diff --git a/requirements-test.txt b/requirements-test.txt index b03a90a..868281f 100644 --- a/requirements-test.txt +++ b/requirements-test.txt @@ -1,3 +1,4 @@ pylint flake8 requests-mock +httpretty diff --git a/test_airtable.py b/test_airtable.py index a7469b7..b7f3a90 100644 --- a/test_airtable.py +++ b/test_airtable.py @@ -1,9 +1,11 @@ from typing import Any, Dict import unittest +import json import requests_mock - +import httpretty import airtable +import re FAKE_TABLE_NAME = 'TableName' FAKE_BASE_ID = 'app12345' @@ -33,6 +35,43 @@ def test_build_headers(self): self.assertEqual(self.airtable.headers['Authorization'], 'Bearer fake_api_key') + @httpretty.activate + def test_retries(self): + httpretty.register_uri( + httpretty.GET, + re.compile(r'https://.*'), + responses=[ + httpretty.Response( + body='{}', + status=429, + ), + httpretty.Response( + body='{}', + status=500, + ), + httpretty.Response( + body=json.dumps({ + 'records': [ + { + 'id': 'reccA6yaHKzw5Zlp0', + 'fields': { + 'Name': 'John', + 'Number': '(987) 654-3210' + } + } + ], + 'offset': 'reccg3Kke0QvTDW0H' + }), + status=200, + ), + ] + ) + + res = self.get() + self.assertEqual(3, len(httpretty.latest_requests())) + self.assertEqual(len(res['records']), 1) + self.assertEqual(res['offset'], 'reccg3Kke0QvTDW0H') + @requests_mock.mock() def test_get_all(self, mock_requests): mock_requests.get('https://api.airtable.com/v0/app12345/TableName', json={