From af78471a225bde3c790b30c3d388145b012c3138 Mon Sep 17 00:00:00 2001 From: Kyle Hornberg Date: Thu, 13 Jun 2019 09:18:39 -0500 Subject: [PATCH 1/3] Bug Fix: Parse pagination links with % and + --- src/octokit/__init__.py | 2 +- tests/test_octokit.py | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/octokit/__init__.py b/src/octokit/__init__.py index 4eb56f5..051f00e 100644 --- a/src/octokit/__init__.py +++ b/src/octokit/__init__.py @@ -11,7 +11,7 @@ from octokit import errors from octokit import utils from routes import specifications -page_regex = re.compile(r'[\?\&]page=(\d+)[_&=\w\d]*>; rel="(\w+)"') +page_regex = re.compile(r'[\?\&]page=(\d+)[_&=%+\w\d]*>; rel="(\w+)"') class Base(object): diff --git a/tests/test_octokit.py b/tests/test_octokit.py index a629370..b7fa21e 100644 --- a/tests/test_octokit.py +++ b/tests/test_octokit.py @@ -1,7 +1,7 @@ class MockHeaders(object): def __init__(self, requested_page): - Link = 'Links ; rel="next", ; rel="last"'.format( # noqa E501 + Link = 'Links ; rel="next", ; rel="last"'.format( # noqa E501 min(requested_page + 1, 4) ) self.headers = {'Link': Link} @@ -12,8 +12,6 @@ class MockObject(object): def __init__(self, page, kwargs): self._response = MockHeaders(page) self.json = {'page': page, 'kwargs': kwargs} - # self.is_last_page = True if page == 4 else False - # self.next_page = min(page + 1, 4) if page else 2 def MockResponse(page=None, **kwargs): From 7c502c176d193c595f0f69d64a9763ecaf322be2 Mon Sep 17 00:00:00 2001 From: Kyle Hornberg Date: Thu, 13 Jun 2019 09:33:53 -0500 Subject: [PATCH 2/3] Bug Fix: Do not break pagination for single page links --- src/octokit/__init__.py | 7 ++++--- tests/test_octokit.py | 25 ++++++++++++++++++++----- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/octokit/__init__.py b/src/octokit/__init__.py index 051f00e..d38a054 100644 --- a/src/octokit/__init__.py +++ b/src/octokit/__init__.py @@ -250,6 +250,7 @@ class Octokit(Base): def paginate(self, obj, page=1, **kwargs): response = self.set_pages(obj(page=page, **kwargs)) yield response.json - while not response.is_last_page: - response = self.set_pages(obj(page=response.next_page, **kwargs), response.next_page) - yield response.json + if hasattr(response, 'is_last_page'): + while not response.is_last_page: + response = self.set_pages(obj(page=response.next_page, **kwargs), response.next_page) + yield response.json diff --git a/tests/test_octokit.py b/tests/test_octokit.py index b7fa21e..d0784d2 100644 --- a/tests/test_octokit.py +++ b/tests/test_octokit.py @@ -1,21 +1,28 @@ +import pytest + + class MockHeaders(object): - def __init__(self, requested_page): - Link = 'Links ; rel="next", ; rel="last"'.format( # noqa E501 + def __init__(self, requested_page, **kwargs): + link = 'Links ; rel="next", ; rel="last"'.format( # noqa E501 min(requested_page + 1, 4) ) - self.headers = {'Link': Link} + self.headers = {'Link': kwargs.get('link', link)} class MockObject(object): def __init__(self, page, kwargs): - self._response = MockHeaders(page) + self._response = MockHeaders(page, **kwargs) self.json = {'page': page, 'kwargs': kwargs} def MockResponse(page=None, **kwargs): - print('mr', page, kwargs) + return MockObject(page, kwargs) + + +def MockResponseWithoutLinks(page=None, **kwargs): + kwargs['link'] = '' return MockObject(page, kwargs) @@ -46,6 +53,14 @@ class TestOctokit(object): assert next(p) == {'page': 3, 'kwargs': {'param': 'value'}} assert next(p) == {'page': 4, 'kwargs': {'param': 'value'}} + def test_pagination_does_break_when_iterating_over_a_single_page(self): + from octokit import Octokit + sut_obj = MockResponseWithoutLinks + p = Octokit().paginate(sut_obj, param='value') + assert next(p) == {'page': 1, 'kwargs': {'param': 'value', 'link': ''}} + with pytest.raises(StopIteration): + assert next(p) + def test_can_speficy_the_route_specifications_used(self): from octokit import Octokit octokit = Octokit(routes='ghe-2.15') From c72464147577c37046468aa955b8956a2e2b6f6a Mon Sep 17 00:00:00 2001 From: Kyle Hornberg Date: Thu, 13 Jun 2019 09:19:44 -0500 Subject: [PATCH 3/3] Version: 0.11.1 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 0fc5180..589c93e 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ def read(*names, **kwargs): setup( name='octokitpy', - version='0.11.0', + version='0.11.1', license='MIT license', description='Python client for GitHub API', long_description='%s\n%s' % (