comparison piecrust/data/linker.py @ 247:d9d5c5de02a8

data: Add a top level wrapper for `Linker`. The `family` object is special in that it's "attached" to the current page, so make an object dedicated to that. It removes special code in `Linker`, and makes it possible to go `family.children` directly to get a page's children (i.e. pages in a directory of the same name).
author Ludovic Chabant <ludovic@chabant.com>
date Thu, 19 Feb 2015 23:33:54 -0800
parents f130365568ff
children 311447fe3dd0
comparison
equal deleted inserted replaced
242:f130365568ff 247:d9d5c5de02a8
5 from piecrust.sources.base import build_pages 5 from piecrust.sources.base import build_pages
6 from piecrust.sources.interfaces import IPaginationSource, IListableSource 6 from piecrust.sources.interfaces import IPaginationSource, IListableSource
7 7
8 8
9 logger = logging.getLogger(__name__) 9 logger = logging.getLogger(__name__)
10
11
12 class PageLinkerData(object):
13 """ Entry template data to get access to related pages from a given
14 root page.
15 """
16 def __init__(self, source, page_path):
17 self._linker = Linker(source, page_path)
18
19 @property
20 def siblings(self):
21 return self._linker
22
23 @property
24 def children(self):
25 self._linker._load()
26 print("GOT ", self._linker._items.keys())
27 if self._linker._self_item is None:
28 return None
29 return self._linker._self_item.config.get('__linker_child')
30
31 @property
32 def root(self):
33 return self._linker.root
34
35 def forpath(self, rel_path):
36 return self._linker.forpath(rel_path)
10 37
11 38
12 class LinkedPageData(PaginationData): 39 class LinkedPageData(PaginationData):
13 """ Class whose instances get returned when iterating on a `Linker` 40 """ Class whose instances get returned when iterating on a `Linker`
14 or `RecursiveLinker`. It's just like what gets usually returned by 41 or `RecursiveLinker`. It's just like what gets usually returned by
75 102
76 103
77 class Linker(object): 104 class Linker(object):
78 debug_render_doc = """Provides access to sibling and children pages.""" 105 debug_render_doc = """Provides access to sibling and children pages."""
79 106
80 def __init__(self, source, *, name=None, dir_path=None, page_path=None): 107 def __init__(self, source, root_page_path, *, name=None, dir_path=None):
81 self._source = source 108 self._source = source
109 self._root_page_path = root_page_path
82 self._name = name 110 self._name = name
83 self._dir_path = dir_path 111 self._dir_path = dir_path
84 self._root_page_path = page_path
85 self._items = None 112 self._items = None
113 self._self_item = None
86 114
87 self.is_dir = True 115 self.is_dir = True
88 self.is_page = False 116 self.is_page = False
89 self.is_self = False 117 self.is_self = False
90 118
136 @property 164 @property
137 def root(self): 165 def root(self):
138 return self.forpath('/') 166 return self.forpath('/')
139 167
140 def forpath(self, rel_path): 168 def forpath(self, rel_path):
141 return Linker(self._source, 169 return Linker(self._source, self._root_page_path,
142 name='.', dir_path=rel_path, 170 name='.', dir_path=rel_path)
143 page_path=self._root_page_path)
144 171
145 def _iterItems(self, max_depth=-1, filter_func=None): 172 def _iterItems(self, max_depth=-1, filter_func=None):
146 items = walk_linkers(self, max_depth=max_depth, 173 items = walk_linkers(self, max_depth=max_depth,
147 filter_func=filter_func) 174 filter_func=filter_func)
148 src = LinkerSource(items, self._source) 175 src = LinkerSource(items, self._source)
154 181
155 is_listable = isinstance(self._source, IListableSource) 182 is_listable = isinstance(self._source, IListableSource)
156 if not is_listable: 183 if not is_listable:
157 raise Exception("Source '%s' can't be listed." % self._source.name) 184 raise Exception("Source '%s' can't be listed." % self._source.name)
158 185
159 if self._root_page_path is not None: 186 if self._name is None:
160 if self._name is None: 187 self._name = self._source.getBasename(self._root_page_path)
161 self._name = self._source.getBasename(self._root_page_path) 188 if self._dir_path is None:
162 if self._dir_path is None: 189 self._dir_path = self._source.getDirpath(self._root_page_path)
163 self._dir_path = self._source.getDirpath(self._root_page_path)
164 190
165 if self._dir_path is None: 191 if self._dir_path is None:
166 raise Exception("This linker has no directory to start from.") 192 raise Exception("This linker has no directory to start from.")
167 193
168 items = list(self._source.listPath(self._dir_path)) 194 items = list(self._source.listPath(self._dir_path))
170 with self._source.app.env.page_repository.startBatchGet(): 196 with self._source.app.env.page_repository.startBatchGet():
171 for is_dir, name, data in items: 197 for is_dir, name, data in items:
172 # If `is_dir` is true, `data` will be the directory's source 198 # If `is_dir` is true, `data` will be the directory's source
173 # path. If not, it will be a page factory. 199 # path. If not, it will be a page factory.
174 if is_dir: 200 if is_dir:
175 item = Linker(self._source, 201 item = Linker(self._source, self._root_page_path,
176 name=name, dir_path=data) 202 name=name, dir_path=data)
177 else: 203 else:
178 item = data.buildPage() 204 item = data.buildPage()
205 is_self = (item.rel_path == self._root_page_path)
179 item.config.set('__linker_name', name) 206 item.config.set('__linker_name', name)
180 item.config.set('__linker_is_self', 207 item.config.set('__linker_is_self', is_self)
181 item.rel_path == self._root_page_path) 208 if is_self:
209 self._self_item = item
182 210
183 existing = self._items.get(name) 211 existing = self._items.get(name)
184 if existing is None: 212 if existing is None:
185 self._items[name] = item 213 self._items[name] = item
186 elif is_dir: 214 elif is_dir: