Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

python-gitlab Issue #63 - implement pagination for list()#64

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
gpocentek merged 3 commits intopython-gitlab:masterfromjantman:issues/63
Aug 21, 2015
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletionsgitlab/__init__.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -189,6 +189,8 @@ def set_url(self, url):
self._url = '%s/api/v3' % url

def _construct_url(self, id_, obj, parameters):
if 'next_url' in parameters:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Could you handle prev, first and last as well?

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

@gpocentek I'm not sure I understand the purpose of that, given how this function is called. Even if I don't use the generator idea, from@dserodio, it's your project but I'd rather not add in additional unused code paths...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

My comment was just plain stupid. Sorry.

return parameters['next_url']
args = _sanitize_dict(parameters)
url = obj._url % args
if id_ is not None:
Expand DownExpand Up@@ -342,8 +344,13 @@ def list(self, obj_class, **kwargs):
if key in cls_kwargs:
del cls_kwargs[key]

return [cls(self, item, **cls_kwargs) for item in r.json()
if item is not None]
results = [cls(self, item, **cls_kwargs) for item in r.json()
if item is not None]
if 'next' in r.links and 'url' in r.links['next']:
args = kwargs.copy()
args['next_url'] = r.links['next']['url']
results.extend(self.list(obj_class, **args))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

This doesn't seem to give a choice to the user, this will always return the full list and do multiple API calls. If a user has hundreds of items this is a problem. It should be optional.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

IMHO, the perfect implementation would use Python generators instead of a list, and only fetch the next page when needed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Sounds like a good plan. I'm a bit short on time to work on this these days but I'd be happy to merge this solution. Thanks!

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I'm not sure I see this as "a problem" - the whole reason why I opened this PR is because I have about 200 users, and will soon have about 300 repositories. I've seen some latency when fetching all that, but not much.

I like@dserodio's idea of using a generator for this. I'm going to have a try at implementing it, though I haven't done much with generators before, and perhaps worse, I've never really worked withunittest orhttmock.

return results
else:
_raise_error_from_response(r, GitlabListError)

Expand Down
51 changes: 51 additions & 0 deletionsgitlab/tests/test_gitlab.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,6 +22,7 @@
import unittest
except ImportError:
import unittest2 as unittest
import json

from httmock import HTTMock # noqa
from httmock import response # noqa
Expand DownExpand Up@@ -178,6 +179,56 @@ def resp_cont(url, request):
self.assertEqual(data.project_id, 1)
self.assertEqual(data.ref, "a")

def test_list_next_link(self):
@urlmatch(scheme="http", netloc="localhost",
path='/api/v3/projects/1/repository/branches', method="get",
query=r'per_page=1')
def resp_one(url, request):
"""
First request:
http://localhost/api/v3/projects/1/repository/branches?per_page=1
"""
headers = {
'content-type': 'application/json',
'link': '<http://localhost/api/v3/projects/1/repository/branc' \
'hes?page=2&per_page=0>; rel="next", <http://localhost/api/v3' \
'/projects/1/repository/branches?page=2&per_page=0>; rel="las' \
't", <http://localhost/api/v3/projects/1/repository/branches?' \
'page=1&per_page=0>; rel="first"'
}
content = ('[{"branch_name": "otherbranch", '
'"project_id": 1, "ref": "b"}]').encode("utf-8")
resp = response(200, content, headers, None, 5, request)
return resp

@urlmatch(scheme="http", netloc="localhost",
path='/api/v3/projects/1/repository/branches', method="get",
query=r'.*page=2.*')
def resp_two(url, request):
headers = {
'content-type': 'application/json',
'link': '<http://localhost/api/v3/projects/1/repository/branc' \
'hes?page=1&per_page=0>; rel="prev", <http://localhost/api/v3' \
'/projects/1/repository/branches?page=2&per_page=0>; rel="las' \
't", <http://localhost/api/v3/projects/1/repository/branches?' \
'page=1&per_page=0>; rel="first"'
}
content = ('[{"branch_name": "testbranch", '
'"project_id": 1, "ref": "a"}]').encode("utf-8")
resp = response(200, content, headers, None, 5, request)
return resp

with HTTMock(resp_one, resp_two):
data = self.gl.list(ProjectBranch, project_id=1,
per_page=1)
self.assertEqual(data[1].branch_name, "testbranch")
self.assertEqual(data[1].project_id, 1)
self.assertEqual(data[1].ref, "a")
self.assertEqual(data[0].branch_name, "otherbranch")
self.assertEqual(data[0].project_id, 1)
self.assertEqual(data[0].ref, "b")
self.assertEqual(len(data), 2)

def test_list_401(self):
@urlmatch(scheme="http", netloc="localhost",
path="/api/v3/projects/1/repository/branches", method="get")
Expand Down

[8]ページ先頭

©2009-2025 Movatter.jp