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