Skip to content

Commit 0ea5b5c

Browse files
committed
Encapsulate Link header behaviour
1 parent 8345cf6 commit 0ea5b5c

File tree

2 files changed

+44
-22
lines changed

2 files changed

+44
-22
lines changed

pygithub3/core/link.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/usr/bin/env python
2+
# -*- encoding: utf-8 -*-
3+
4+
from urlparse import urlparse, parse_qs
5+
6+
from .third_libs.link_header import parse_link_value
7+
8+
class Link(str):
9+
10+
class Url(str):
11+
12+
@property
13+
def query(self):
14+
return urlparse(self).query
15+
16+
@property
17+
def params(self):
18+
return dict([
19+
(param, values.pop())
20+
for param, values in parse_qs(self.query).items()])
21+
22+
def __init__(self, object_):
23+
super(Link, self).__init__(object_)
24+
parsed = parse_link_value(self)
25+
for url in parsed:
26+
setattr(self, parsed[url]['rel'], Link.Url(url))

pygithub3/core/result.py

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33

44
from urlparse import urlparse, parse_qs
55

6-
from .third_libs.link_header import parse_link_value
6+
from .link import Link
77

88

99
class Method(object):
10+
""" Lazy support """
1011

1112
def __init__(self, method, request, **method_args):
1213
self.method = method
@@ -15,41 +16,36 @@ def __init__(self, method, request, **method_args):
1516
self.cache = {}
1617

1718
def cached(func):
19+
""" Decorator to don't do a request if it's cached """
1820
def wrapper(self, page=1):
1921
if str(page) in self.cache:
2022
return self.cache[str(page)]
2123
return func(self, page)
2224
return wrapper
2325

2426
def if_needs_lastpage(func):
25-
def wrapper(self, response):
26-
has_link = response.headers.get('link')
27+
""" Decorator to set last page only if it can and it hasn't retrieved
28+
before """
29+
def wrapper(self, has_link):
2730
has_last_page = hasattr(self, 'last_page')
2831
if not has_last_page and has_link:
29-
return func(self, response)
32+
return func(self, has_link)
3033
elif not has_last_page and not has_link:
3134
self.last_page = 1
3235
return wrapper
3336

3437
@if_needs_lastpage
35-
def __set_last_page_from(self, response):
36-
link_parsed = parse_link_value(response.headers['link'])
37-
38-
def get_last(url):
39-
url_rels = link_parsed[url]
40-
return (url_rels.get('rel') == 'last')
41-
url_last = filter(get_last, link_parsed)
42-
query = urlparse(url_last.pop()).query
43-
self.last_page = int(parse_qs(query).get('page').pop())
38+
def __set_last_page_from(self, link_header):
39+
""" Get and set last_page form link header """
40+
link = Link(link_header)
41+
self.last_page = int(link.last.params.get('page'))
4442

4543
@cached
4644
def __call__(self, page=1):
47-
all_args = self.args.copy()
48-
all_args.update(page=page)
49-
response = self.method(self.request, **all_args)
50-
self.__set_last_page_from(response)
51-
resource = self.request.resource
52-
self.cache[str(page)] = resource.loads(response.content)
45+
""" Call a real request """
46+
response = self.method(page=page)
47+
self.__set_last_page_from(response.headers.get('link'))
48+
self.cache[str(page)] = self.resource.loads(response.content)
5349
return self.cache[str(page)]
5450

5551
@property
@@ -60,10 +56,9 @@ def last(self):
6056

6157

6258
class Page(object):
63-
""" """
59+
""" Iterator of resources """
6460

6561
def __init__(self, getter, page=1):
66-
""" """
6762
self.getter = getter
6863
self.page = page
6964

@@ -136,7 +131,8 @@ def __repr__(self):
136131

137132
class Result(object):
138133
"""
139-
Result is a very lazy paginator. It only do a real request when is needed
134+
Result is a very **lazy** paginator beacuse only do a real request when is
135+
needed, besides it's **cached**, so never repeats a request.
140136
141137
You have several ways to consume it
142138

0 commit comments

Comments
 (0)