Source code for swimlane.core.cursor
import itertools
[docs]class Cursor(object):
def __init__(self):
self._elements = []
def __len__(self):
return len(list(self._evaluate()))
def __iter__(self):
for element in self._evaluate():
yield element
def __getitem__(self, item):
return self._evaluate()[item]
def _evaluate(self):
"""Hook to allow lazy evaluation or retrieval of cursor's elements
Defaults to simply returning list of self._elements
"""
return self._elements
[docs]class PaginatedCursor(Cursor):
"""Handle paginated lists, exposes hooks to simplify retrieval and parsing of paginated data"""
default_limit = 0
default_page_size = 10
default_page_start = None
default_page_end = None
def __init__(self, limit=default_limit, page_size=default_page_size,
page_start=default_page_start, page_end=default_page_end):
super(PaginatedCursor, self).__init__()
self.__limit = limit
self.page_size = page_size
self.page_start = page_start
self.page_end = page_end
if self.__limit:
self.page_size = min(self.page_size, self.__limit)
if self.page_start and self.page_start <= 0:
raise ValueError('page_start should be greater than 0')
if self.page_end and self.page_end <= 0:
raise ValueError('page_end should be greater than 0')
if (self.page_start and self.page_end) and (self.page_start > self.page_end):
raise ValueError('page_end cannot be less than page_start')
if (self.page_start or self.page_end) and self.__limit != 0:
raise ValueError(' page_start or page_end param is applicable only when limit is 0')
def _evaluate(self):
"""Lazily retrieve and paginate report results and build Record instances from returned data"""
if self._elements:
for element in self._elements:
yield element
else:
# Determine pagination range based on parameters
if self.page_start and self.page_end:
page_range = range(self.page_start-1, self.page_end)
elif self.page_start:
page_range = itertools.count(self.page_start-1)
elif self.page_end:
page_range = range(0, self.page_end)
else:
page_range = itertools.count()
for page in page_range:
raw_elements = self._retrieve_raw_elements(page)
for raw_element in raw_elements:
element = self._parse_raw_element(raw_element)
self._elements.append(element)
yield element
if self.__limit and len(self._elements) >= self.__limit:
break
# Break conditions for ending pagination
if any([
len(raw_elements) < self.page_size,
self.__limit and len(self._elements) >= self.__limit,
self.page_size == 0
]):
break
def _retrieve_raw_elements(self, page):
"""Send request and return response for single page of data"""
raise NotImplementedError
def _parse_raw_element(self, raw_element):
"""Hook to override parsing individual raw elements just before yielding"""
return raw_element