Mercurial > piecrust2
comparison piecrust/data/linker.py @ 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 | f485ba500df3 |
children | 701591ebfcba |
comparison
equal
deleted
inserted
replaced
171:d5991525801d | 172:4fc1d306046b |
---|---|
1 import logging | |
2 import collections | |
3 from piecrust.data.base import PaginationData | |
4 from piecrust.sources.base import IListableSource, build_pages | |
5 | |
6 | |
7 logger = logging.getLogger(__name__) | |
8 | |
9 | |
10 class LinkedPageData(PaginationData): | |
11 debug_render = ['name', 'is_dir', 'is_self'] | |
12 | |
13 def __init__(self, name, page, is_self=False): | |
14 super(LinkedPageData, self).__init__(page) | |
15 self.name = name | |
16 self.is_self = is_self | |
17 | |
18 @property | |
19 def is_dir(self): | |
20 return False | |
1 | 21 |
2 | 22 |
3 class Linker(object): | 23 class Linker(object): |
4 def __init__(self, page): | 24 debug_render_doc = """Provides access to sibling and children pages.""" |
5 self.page = page | |
6 | 25 |
26 def __init__(self, source, *, name=None, dir_path=None, page_path=None): | |
27 self.source = source | |
28 self._name = name | |
29 self._dir_path = dir_path | |
30 self._root_page_path = page_path | |
31 self._cache = None | |
32 self._is_listable = None | |
33 | |
34 def __iter__(self): | |
35 self._load() | |
36 return iter(self._cache.values()) | |
37 | |
38 def __getattr__(self, name): | |
39 self._load() | |
40 try: | |
41 return self._cache[name] | |
42 except KeyError: | |
43 raise AttributeError() | |
44 | |
45 @property | |
46 def name(self): | |
47 if not self._name: | |
48 self._load() | |
49 return self._name | |
50 | |
51 @property | |
52 def is_dir(self): | |
53 return True | |
54 | |
55 @property | |
56 def is_self(self): | |
57 return False | |
58 | |
59 def _load(self): | |
60 if self._cache is not None: | |
61 return | |
62 | |
63 self._is_listable = isinstance(self.source, IListableSource) | |
64 if self._is_listable and self._root_page_path is not None: | |
65 if self._name is None: | |
66 self._name = self.source.getBasename(self._root_page_path) | |
67 if self._dir_path is None: | |
68 self._dir_path = self.source.getDirpath(self._root_page_path) | |
69 | |
70 self._cache = collections.OrderedDict() | |
71 if not self._is_listable or self._dir_path is None: | |
72 return | |
73 | |
74 items = self.source.listPath(self._dir_path) | |
75 with self.source.app.env.page_repository.startBatchGet(): | |
76 for is_dir, name, data in items: | |
77 if is_dir: | |
78 self._cache[name] = Linker(self.source, | |
79 name=name, dir_path=data) | |
80 else: | |
81 page = data.buildPage() | |
82 is_root_page = (self._root_page_path == data.rel_path) | |
83 self._cache[name] = LinkedPageData(name, page, | |
84 is_root_page) | |
85 | |
86 | |
87 class RecursiveLinker(Linker): | |
88 def __init__(self, source, page_path): | |
89 super(RecursiveLinker, self).__init__(source, page_path=page_path) | |
90 | |
91 def __iter__(self): | |
92 self._load() | |
93 if not self._is_listable: | |
94 return | |
95 yield from walk_linkers(self) | |
96 | |
97 | |
98 def walk_linkers(linker): | |
99 linker._load() | |
100 for item in linker._cache.values(): | |
101 if item.is_dir: | |
102 yield from walk_linkers(item) | |
103 else: | |
104 yield item | |
105 |