diff options
Diffstat (limited to 'pygithub3/core')
-rw-r--r-- | pygithub3/core/result.py | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/pygithub3/core/result.py b/pygithub3/core/result.py new file mode 100644 index 0000000..5c1466d --- /dev/null +++ b/pygithub3/core/result.py @@ -0,0 +1,171 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- + +from urlparse import urlparse, parse_qs + +from .third_libs.link_header import parse_link_value + + +class Method(object): + + def __init__(self, method, resource, **method_args): + self.method = method + self.resource = resource + self.args = method_args + self.cache = {} + + def cached(func): + def wrapper(self, page=1): + if self.cache.has_key(str(page)): + return self.cache[str(page)] + return func(self, page) + return wrapper + + def if_needs_lastpage(func): + def wrapper(self, response): + #import ipdb; ipdb.set_trace() + has_link = response.headers.get('link') + has_last_page = hasattr(self, 'last_page') + if not has_last_page and has_link: + return func(self, response) + elif not has_last_page and not has_link: + self.last_page = 1 + return wrapper + + @if_needs_lastpage + def __set_last_page_from(self, response): + #import ipdb; ipdb.set_trace() + link_parsed = parse_link_value(response.headers['link']) + def get_last(url): + url_rels = link_parsed[url] + return (url_rels.get('rel') == 'last') + url_last = filter(get_last, link_parsed) + query = urlparse(url_last.pop()).query + self.last_page = int(parse_qs(query).get('page').pop()) + + @cached + def __call__(self, page=1): + all_args = self.args.copy() + all_args.update(page=page) + response = self.method(self.resource, **all_args) + self.__set_last_page_from(response) + model = self.resource.get_model() + self.cache[str(page)] = model.loads(response.content) + return self.cache[str(page)] + + @property + def last(self): + if not hasattr(self, 'last_page'): + self() + return self.last_page + +class Page(object): + """ """ + + def __init__(self, getter, page=1): + """ """ + self.getter = getter + self.page = page + + def __iter__(self): + return self + + def __add__(self, number): + return self.page + number + + def __radd__(self, number): + return number + self.page + + def __sub__(self, number): + return self.page - number + + def __rsub__(self, number): + return number - self.page + + def __lt__(self, number): + return self.page < number + + def __le__(self, number): + return self.page <= number + + def __eq__(self, number): + return self.page == number + + def __ne__(self, number): + return self.page != number + + def __gt__(self, number): + return self.page > number + + def __ge__(self, number): + return self.page >= number + + @property + def resources(self): + return getattr(self, '_count', None) or u"~" + + def get_content(func): + def wrapper(self): + if not hasattr(self, '_count'): + content = self.getter(self.page) + self._count = len(content) + self.iterable = iter(content) + return func(self) + return wrapper + + @get_content + def __next__(self): + try: + return self.iterable.next() + except StopIteration: + self.iterable = iter(self.getter(self.page)) + raise StopIteration + + def next(self): + return self.__next__() + + def __str__(self): + return '<{name}{page} resources={resources}>'.format( + name=self.__class__.__name__, + page=self.page, + resources=self.resources) + + def __repr__(self): + return "%s[%d]" % (self.__str__(), id(self)) + + +class Result(object): + """ """ + + def __init__(self, client, resource, **kwargs): + """ """ + self.getter = Method(client.get, resource, **kwargs) + self.page = Page(self.getter) + + def __iter__(self): + return self + + def __next__(self): + if self.page <= self.pages: + page_to_return = self.page + self.page = Page(self.getter, page_to_return + 1) + return page_to_return + self.page = Page(self.getter) + raise StopIteration + + def next(self): + return self.__next__() + + @property + def pages(self): + return self.getter.last + + def get_page(self, page): + if page in xrange(1, self.pages + 1): + return Page(self.getter, page) + return None + + def all(self): + for page in self: + for resource in page: + yield resource |