diff --git a/orangecontrib/text/guardian.py b/orangecontrib/text/guardian.py index 4c872d96e..a062d9f67 100644 --- a/orangecontrib/text/guardian.py +++ b/orangecontrib/text/guardian.py @@ -29,6 +29,10 @@ ARTICLES_PER_PAGE = 10 +class APILimitError(Exception): + pass + + class TheGuardianCredentials: """ The Guardian API credentials. """ def __init__(self, key): @@ -93,6 +97,9 @@ def _search(self, query, from_date, to_date, page=1): data = self._build_query(query, from_date, to_date, page) response = requests.get(BASE_URL, data) + if response.status_code == 429: + raise APILimitError("API limit exceeded") + parsed = json.loads(response.text) if page == 1: # store number of pages diff --git a/orangecontrib/text/tests/test_guardian.py b/orangecontrib/text/tests/test_guardian.py index 72289f1e9..76c0788d4 100644 --- a/orangecontrib/text/tests/test_guardian.py +++ b/orangecontrib/text/tests/test_guardian.py @@ -2,6 +2,7 @@ import os from datetime import date, datetime +from unittest import mock from orangecontrib.text import guardian @@ -10,7 +11,9 @@ class TestCredentials(unittest.TestCase): - def test_valid(self): + @mock.patch('requests.get') + def test_valid(self, mock_get): + mock_get().status_code = 200 credentials = guardian.TheGuardianCredentials(API_KEY) self.assertTrue(credentials.valid) @@ -19,15 +22,26 @@ def test_equal(self): self.assertEquals(credentials, credentials) +def skip_limit_exceeded(fun): + def wrapper(*args, **kwargs): + try: + fun(*args, **kwargs) + except guardian.APILimitError as err: + raise unittest.SkipTest(str(err)) + return wrapper + + class TestGuardian(unittest.TestCase): def setUp(self): c = guardian.TheGuardianCredentials(API_KEY) self.api = guardian.TheGuardianAPI(c) + @skip_limit_exceeded def test_search(self): corp = self.api.search('Slovenia', max_documents=20) self.assertEqual(len(corp), 20) + @skip_limit_exceeded def test_search_from_to_date(self): from_date = date(2016, 12, 1) to_date = date(2016, 12, 31) @@ -41,13 +55,53 @@ def test_search_from_to_date(self): self.assertGreaterEqual(dt.date(), from_date) self.assertLessEqual(dt.date(), to_date) + @skip_limit_exceeded def test_breaking(self): self.api.should_break = lambda: True corp = self.api.search('Slovenia', max_documents=20) self.assertEqual(len(corp), 10) self.api.should_break = lambda: False + @skip_limit_exceeded def test_accumulate(self): self.api.search('Slovenia', max_documents=10, accumulate=True) corp = self.api.search('Ljubljana', max_documents=10, accumulate=True) self.assertEqual(len(corp), 20) + + @mock.patch('requests.get') + def test_api_limit_error(self, mock_get): + mock_get().status_code = 429 + self.assertRaises(guardian.APILimitError, self.api.search, 'Slovenia') + + @mock.patch('requests.get') + def test_search_mock_data(self, mock_get): + mock_get().text = """ + { + "response": { + "pages": 1, + "results": [ + { + "type": "article", + "sectionName": "World news", + "webPublicationDate": "2018-07-05T23:27:25Z", + "webUrl": "https://www.theguardian.com/world/2018/jul/06", + "fields": { + "headline": "Rohingya refugees reject UN-Myanmar repatriati", + "trailText": "Leaders say agreement does not address concer", + "body": "