Mercurial > piecrust2
changeset 867:757fba54bfd3
refactor: Improve pagination and iterators to work with other sources.
This makes the assets work as a pagination source again.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Mon, 12 Jun 2017 22:20:58 -0700 |
parents | d9059257743c |
children | 8d25f76fce98 |
files | piecrust/data/assetor.py piecrust/data/paginator.py piecrust/dataproviders/pageiterator.py |
diffstat | 3 files changed, 61 insertions(+), 41 deletions(-) [+] |
line wrap: on
line diff
--- a/piecrust/data/assetor.py Mon Jun 12 22:10:50 2017 -0700 +++ b/piecrust/data/assetor.py Mon Jun 12 22:20:58 2017 -0700 @@ -21,7 +21,7 @@ self.uri = uri -class Assetor(collections.abc.Mapping): +class Assetor(collections.abc.Sequence): debug_render_doc = """Helps render URLs to files in the current page's asset folder.""" debug_render = [] @@ -29,7 +29,8 @@ def __init__(self, page): self._page = page - self._cache = None + self._cache_map = None + self._cache_list = None def __getattr__(self, name): try: @@ -38,36 +39,32 @@ except KeyError: raise AttributeError() - def __getitem__(self, key): + def __getitem__(self, i): self._cacheAssets() - return self._cache[key].uri - - def __iter__(self): - self._cacheAssets() - return self._cache.keys() + return self._cache_list[i] def __len__(self): self._cacheAssets() - return len(self._cache) + return len(self._cache_list) def _debugRenderAssetNames(self): self._cacheAssets() return list(self._cache.keys()) def _cacheAssets(self): - if self._cache is not None: + if self._cache_map is not None: return source = self._page.source content_item = self._page.content_item + assets = source.getRelatedContents(content_item, REL_ASSETS) - assets = source.getRelatedContents(content_item, REL_ASSETS) + self._cache_map = {} + self._cache_list = [] + if assets is None: - self._cache = {} return - self._cache = {} - app = source.app root_dir = app.root_dir asset_url_format = app.config.get('site/asset_url_format') @@ -85,7 +82,7 @@ for a in assets: name = a.metadata['name'] - if name in self._cache: + if name in self._cache_map: raise UnsupportedAssetsError( "An asset with name '%s' already exists for item '%s'. " "Do you have multiple assets with colliding names?" % @@ -97,7 +94,8 @@ uri_build_tokens['%filename%'] = a.metadata['filename'], uri = multi_replace(asset_url_format, uri_build_tokens) - self._cache[name] = _AssetInfo(a, uri) + self._cache_map[name] = _AssetInfo(a, uri) + self._cache_list.append(uri) stack = app.env.render_ctx_stack cur_ctx = stack.current_ctx
--- a/piecrust/data/paginator.py Mon Jun 12 22:10:50 2017 -0700 +++ b/piecrust/data/paginator.py Mon Jun 12 22:20:58 2017 -0700 @@ -90,9 +90,11 @@ if ipp is not None: return ipp - ipp = self._source.config.get('items_per_page') - if ipp is not None: - return ipp + from piecrust.sources.base import ContentSource + if isinstance(self._source, ContentSource): + ipp = self._source.config.get('items_per_page') + if ipp is not None: + return ipp raise Exception("No way to figure out how many items to display " "per page.") @@ -188,11 +190,11 @@ from piecrust.data.filters import PaginationFilter from piecrust.dataproviders.pageiterator import ( PageIterator, HardCodedFilterIterator) + from piecrust.sources.base import ContentSource self._iterator = PageIterator( self._source, current_page=self._page) - #self._iterator._iter_event += self._onIteration if self._pgn_filter is not None: pag_fil = PaginationFilter() @@ -206,7 +208,8 @@ self._iterator._lockIterator() - self._onIteration(self._iterator) + if isinstance(self._source, ContentSource): + self._onIteration(self._iterator) def _getPageUri(self, index): return self._page.getUri(index)
--- a/piecrust/dataproviders/pageiterator.py Mon Jun 12 22:10:50 2017 -0700 +++ b/piecrust/dataproviders/pageiterator.py Mon Jun 12 22:20:58 2017 -0700 @@ -3,7 +3,7 @@ from piecrust.data.paginationdata import PaginationData from piecrust.events import Event from piecrust.dataproviders.base import DataProvider -from piecrust.sources.base import AbortedSourceUseError +from piecrust.sources.base import ContentSource, AbortedSourceUseError logger = logging.getLogger(__name__) @@ -13,6 +13,7 @@ def __init__(self): self.it = None self.iterated = False + self.source_name = None class PageIteratorDataProvider(DataProvider): @@ -51,13 +52,14 @@ i = _ItInfo() i.it = PageIterator(source, current_page=self._page) i.it._iter_event += self._onIteration + i.source_name = source.name self._its.append(i) def _onIteration(self, it): ii = next(filter(lambda i: i.it == it, self._its)) if not ii.iterated: rcs = self._app.env.render_ctx_stack - rcs.current_ctx.addUsedSource(self._source.name) + rcs.current_ctx.addUsedSource(ii.source_name) ii.iterated = True def _debugRenderDoc(self): @@ -67,6 +69,7 @@ class PageIterator: def __init__(self, source, *, current_page=None): self._source = source + self._is_content_source = isinstance(source, ContentSource) self._cache = None self._pagination_slicer = None self._has_sorter = False @@ -75,7 +78,7 @@ self._locked = False self._iter_event = Event() self._current_page = current_page - self._it = PageContentSourceIterator(self._source) + self._initIterator() @property def total_count(self): @@ -215,11 +218,18 @@ def _ensureSorter(self): if self._has_sorter: return - self._it = DateSortIterator(self._it, reverse=True) + if self._is_content_source: + self._it = DateSortIterator(self._it, reverse=True) self._has_sorter = True + def _initIterator(self): + if self._is_content_source: + self._it = PageContentSourceIterator(self._source) + else: + self._it = GenericSourceIterator(self._source) + def _unload(self): - self._it = PageContentSourceIterator(self._source) + self._initIterator() self._cache = None self._paginationSlicer = None self._has_sorter = False @@ -230,27 +240,29 @@ if self._cache is not None: return - if self._source.app.env.abort_source_use: - if self._current_page is not None: - logger.debug("Aborting iteration of '%s' from: %s." % - (self._source.name, - self._current_page.content_spec)) - else: - logger.debug("Aborting iteration of '%s'." % - self._source.name) - raise AbortedSourceUseError() + if self._is_content_source: + if self._source.app.env.abort_source_use: + if self._current_page is not None: + logger.debug("Aborting iteration of '%s' from: %s." % + (self._source.name, + self._current_page.content_spec)) + else: + logger.debug("Aborting iteration of '%s'." % + self._source.name) + raise AbortedSourceUseError() self._ensureSorter() - tail_it = PaginationDataBuilderIterator(self._it, self._source.route) - self._cache = list(tail_it) + if self._is_content_source: + self._it = PaginationDataBuilderIterator(self._it) + + self._cache = list(self._it) if (self._current_page is not None and self._pagination_slicer is not None): pn = [self._pagination_slicer.prev_page, self._pagination_slicer.next_page] - pn_it = PaginationDataBuilderIterator(iter(pn), - self._source.route) + pn_it = PaginationDataBuilderIterator(iter(pn)) self._prev_page, self._next_page = (list(pn_it)) self._iter_event.fire(self) @@ -367,9 +379,8 @@ class PaginationDataBuilderIterator: - def __init__(self, it, route): + def __init__(self, it): self.it = it - self.route = route def __iter__(self): for page in self.it: @@ -378,3 +389,11 @@ else: yield None + +class GenericSourceIterator: + def __init__(self, source): + self.source = source + self.it = None + + def __iter__(self): + yield from self.source