Mercurial > piecrust2
comparison piecrust/data/iterators.py @ 6:f5ca5c5bed85
More Python 3 fixes, modularization, and new unit tests.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Sat, 16 Aug 2014 08:15:30 -0700 |
parents | f485ba500df3 |
children | cd35d356ccce |
comparison
equal
deleted
inserted
replaced
5:474c9882decf | 6:f5ca5c5bed85 |
---|---|
1 import logging | 1 import logging |
2 from piecrust.data.base import PaginationData | 2 from piecrust.data.base import IPaginationSource |
3 from piecrust.data.filters import PaginationFilter | 3 from piecrust.data.filters import PaginationFilter |
4 from piecrust.events import Event | 4 from piecrust.events import Event |
5 | 5 |
6 | 6 |
7 logger = logging.getLogger(__name__) | 7 logger = logging.getLogger(__name__) |
87 return -1 if v1 < v2 else 1 | 87 return -1 if v1 < v2 else 1 |
88 | 88 |
89 return sorted(self.it, cmp=self._comparer, reverse=self.reverse) | 89 return sorted(self.it, cmp=self._comparer, reverse=self.reverse) |
90 | 90 |
91 | 91 |
92 class DateSortIterator(object): | |
93 def __init__(self, it, reverse=True): | |
94 self.it = it | |
95 self.reverse = reverse | |
96 | |
97 def __iter__(self): | |
98 return iter(sorted(self.it, | |
99 key=lambda x: x.datetime, reverse=self.reverse)) | |
100 | |
101 | |
102 class PaginationFilterIterator(object): | 92 class PaginationFilterIterator(object): |
103 def __init__(self, it, fil): | 93 def __init__(self, it, fil): |
104 self.it = it | 94 self.it = it |
105 self._fil = fil | 95 self._fil = fil |
106 | 96 |
107 def __iter__(self): | 97 def __iter__(self): |
108 for page in self.it: | 98 for page in self.it: |
109 if self._fil.pageMatches(page): | 99 if self._fil.pageMatches(page): |
110 yield page | 100 yield page |
111 | |
112 | |
113 class SourceFactoryIterator(object): | |
114 def __init__(self, source): | |
115 self.source = source | |
116 self.it = None # This is to permit recursive traversal of the | |
117 # iterator chain. It acts as the end. | |
118 | |
119 def __iter__(self): | |
120 for factory in self.source.getPageFactories(): | |
121 yield factory.buildPage() | |
122 | |
123 | |
124 class PaginationDataBuilderIterator(object): | |
125 def __init__(self, it): | |
126 self.it = it | |
127 | |
128 def __iter__(self): | |
129 for page in self.it: | |
130 yield PaginationData(page) | |
131 | 101 |
132 | 102 |
133 class PageIterator(object): | 103 class PageIterator(object): |
134 def __init__(self, source, current_page=None, pagination_filter=None, | 104 def __init__(self, source, current_page=None, pagination_filter=None, |
135 offset=0, limit=-1, locked=False): | 105 offset=0, limit=-1, locked=False): |
136 self._source = source | 106 self._source = source |
137 self._current_page = current_page | 107 self._current_page = current_page |
138 self._locked = False | 108 self._locked = False |
139 self._pages = SourceFactoryIterator(source) | 109 self._pages = source |
140 self._pagesData = None | 110 self._pagesData = None |
141 self._pagination_slicer = None | 111 self._pagination_slicer = None |
142 self._has_sorter = False | 112 self._has_sorter = False |
143 self._next_page = None | 113 self._next_page = None |
144 self._prev_page = None | 114 self._prev_page = None |
145 self._iter_event = Event() | 115 self._iter_event = Event() |
146 | 116 |
117 if isinstance(source, IPaginationSource): | |
118 src_it = source.getSourceIterator() | |
119 if src_it is not None: | |
120 self._pages = src_it | |
121 | |
147 # Apply any filter first, before we start sorting or slicing. | 122 # Apply any filter first, before we start sorting or slicing. |
148 if pagination_filter is not None: | 123 if pagination_filter is not None: |
149 self._simpleNonSortedWrap(PaginationFilterIterator, | 124 self._simpleNonSortedWrap(PaginationFilterIterator, |
150 pagination_filter) | 125 pagination_filter) |
151 | 126 |
201 def has_filter(value): | 176 def has_filter(value): |
202 conf = {'has_%s' % name[5:]: value} | 177 conf = {'has_%s' % name[5:]: value} |
203 return self._simpleNonSortedWrap(SettingFilterIterator, conf) | 178 return self._simpleNonSortedWrap(SettingFilterIterator, conf) |
204 return has_filter | 179 return has_filter |
205 | 180 |
206 raise AttributeError() | 181 return self.__getattribute__(name) |
207 | 182 |
208 def skip(self, count): | 183 def skip(self, count): |
209 return self._simpleWrap(SliceIterator, count) | 184 return self._simpleWrap(SliceIterator, count) |
210 | 185 |
211 def limit(self, count): | 186 def limit(self, count): |
266 "you're trying to tamper with pagination data.") | 241 "you're trying to tamper with pagination data.") |
267 | 242 |
268 def _ensureSorter(self): | 243 def _ensureSorter(self): |
269 if self._has_sorter: | 244 if self._has_sorter: |
270 return | 245 return |
271 self._pages = DateSortIterator(self._pages) | 246 if isinstance(self._source, IPaginationSource): |
247 sort_it = self._source.getSorterIterator(self._pages) | |
248 if sort_it is not None: | |
249 self._pages = sort_it | |
272 self._has_sorter = True | 250 self._has_sorter = True |
273 | 251 |
274 def _unload(self): | 252 def _unload(self): |
275 self._pagesData = None | 253 self._pagesData = None |
276 self._next_page = None | 254 self._next_page = None |
280 if self._pagesData is not None: | 258 if self._pagesData is not None: |
281 return | 259 return |
282 | 260 |
283 self._ensureSorter() | 261 self._ensureSorter() |
284 | 262 |
285 it_chain = PaginationDataBuilderIterator(self._pages) | 263 it_chain = self._pages |
264 is_pgn_source = False | |
265 if isinstance(self._source, IPaginationSource): | |
266 is_pgn_source = True | |
267 tail_it = self._source.getTailIterator(self._pages) | |
268 if tail_it is not None: | |
269 it_chain = tail_it | |
270 | |
286 self._pagesData = list(it_chain) | 271 self._pagesData = list(it_chain) |
287 | 272 |
288 if self._current_page and self._pagination_slicer: | 273 if is_pgn_source and self._current_page and self._pagination_slicer: |
289 self._prev_page = PaginationData(self._pagination_slicer.prev_page) | 274 pn = [self._pagination_slicer.prev_page, |
290 self._next_page = PaginationData(self._pagination_slicer.next_page) | 275 self._pagination_slicer.next_page] |
291 | 276 pn_it = self._source.getTailIterator(iter(pn)) |
277 self._prev_page, self._next_page = (list(pn_it)) | |
278 |