Mercurial > piecrust2
changeset 172:4fc1d306046b
linker: Actually implement the `Linker` class, and use it in the page data.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Sat, 03 Jan 2015 20:52:19 -0800 |
parents | d5991525801d |
children | 0a86a7a6b284 |
files | piecrust/data/builder.py piecrust/data/linker.py |
diffstat | 2 files changed, 106 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/piecrust/data/builder.py Sat Jan 03 20:51:34 2015 -0800 +++ b/piecrust/data/builder.py Sat Jan 03 20:52:19 2015 -0800 @@ -5,7 +5,7 @@ from piecrust.configuration import merge_dicts from piecrust.data.assetor import Assetor from piecrust.data.debug import build_debug_info -from piecrust.data.linker import Linker +from piecrust.data.linker import Linker, RecursiveLinker from piecrust.data.paginator import Paginator from piecrust.uriutil import get_slug, get_first_sub_uri @@ -36,14 +36,15 @@ paginator = Paginator(page, pgn_source, first_uri, ctx.page_num, ctx.pagination_filter) assetor = Assetor(page, first_uri) - linker = Linker(page) + flat_linker = Linker(page.source, page_path=page.rel_path) + recursive_linker = RecursiveLinker(page.source, page_path=page.rel_path) data = { 'piecrust': pc_data, 'page': dict(page.config.get()), 'assets': assetor, 'pagination': paginator, - 'siblings': linker, - 'family': linker + 'siblings': flat_linker, + 'family': recursive_linker } page_data = data['page'] page_data['url'] = ctx.uri
--- a/piecrust/data/linker.py Sat Jan 03 20:51:34 2015 -0800 +++ b/piecrust/data/linker.py Sat Jan 03 20:52:19 2015 -0800 @@ -1,6 +1,105 @@ +import logging +import collections +from piecrust.data.base import PaginationData +from piecrust.sources.base import IListableSource, build_pages + + +logger = logging.getLogger(__name__) + + +class LinkedPageData(PaginationData): + debug_render = ['name', 'is_dir', 'is_self'] + + def __init__(self, name, page, is_self=False): + super(LinkedPageData, self).__init__(page) + self.name = name + self.is_self = is_self + + @property + def is_dir(self): + return False class Linker(object): - def __init__(self, page): - self.page = page + debug_render_doc = """Provides access to sibling and children pages.""" + + def __init__(self, source, *, name=None, dir_path=None, page_path=None): + self.source = source + self._name = name + self._dir_path = dir_path + self._root_page_path = page_path + self._cache = None + self._is_listable = None + + def __iter__(self): + self._load() + return iter(self._cache.values()) + + def __getattr__(self, name): + self._load() + try: + return self._cache[name] + except KeyError: + raise AttributeError() + + @property + def name(self): + if not self._name: + self._load() + return self._name + + @property + def is_dir(self): + return True + + @property + def is_self(self): + return False + + def _load(self): + if self._cache is not None: + return + self._is_listable = isinstance(self.source, IListableSource) + if self._is_listable and self._root_page_path is not None: + if self._name is None: + self._name = self.source.getBasename(self._root_page_path) + if self._dir_path is None: + self._dir_path = self.source.getDirpath(self._root_page_path) + + self._cache = collections.OrderedDict() + if not self._is_listable or self._dir_path is None: + return + + items = self.source.listPath(self._dir_path) + with self.source.app.env.page_repository.startBatchGet(): + for is_dir, name, data in items: + if is_dir: + self._cache[name] = Linker(self.source, + name=name, dir_path=data) + else: + page = data.buildPage() + is_root_page = (self._root_page_path == data.rel_path) + self._cache[name] = LinkedPageData(name, page, + is_root_page) + + +class RecursiveLinker(Linker): + def __init__(self, source, page_path): + super(RecursiveLinker, self).__init__(source, page_path=page_path) + + def __iter__(self): + self._load() + if not self._is_listable: + return + yield from walk_linkers(self) + + +def walk_linkers(linker): + linker._load() + for item in linker._cache.values(): + if item.is_dir: + yield from walk_linkers(item) + else: + yield item +