comparison piecrust/data/linker.py @ 212:701591ebfcba

data: Improve the Linker and RecursiveLinker features. Add tests.
author Ludovic Chabant <ludovic@chabant.com>
date Sat, 31 Jan 2015 11:50:50 -0800
parents 4fc1d306046b
children d6d0e4976beb
comparison
equal deleted inserted replaced
211:0b2d8f6df4ce 212:701591ebfcba
1 import logging 1 import logging
2 import collections 2 import collections
3 from piecrust.data.base import PaginationData 3 from piecrust.data.base import PaginationData, IPaginationSource
4 from piecrust.data.iterators import PageIterator
4 from piecrust.sources.base import IListableSource, build_pages 5 from piecrust.sources.base import IListableSource, build_pages
5 6
6 7
7 logger = logging.getLogger(__name__) 8 logger = logging.getLogger(__name__)
8 9
18 @property 19 @property
19 def is_dir(self): 20 def is_dir(self):
20 return False 21 return False
21 22
22 23
24 class LinkedPageDataIterator(object):
25 def __init__(self, items):
26 self._items = list(items)
27 self._index = -1
28
29 def __iter__(self):
30 return self
31
32 def __next__(self):
33 self._index += 1
34 if self._index >= len(self._items):
35 raise StopIteration()
36 return self._items[self._index]
37
38 def sort(self, name):
39 def key_getter(item):
40 return item[name]
41 self._items = sorted(self._item, key=key_getter)
42 return self
43
44
23 class Linker(object): 45 class Linker(object):
24 debug_render_doc = """Provides access to sibling and children pages.""" 46 debug_render_doc = """Provides access to sibling and children pages."""
25 47
26 def __init__(self, source, *, name=None, dir_path=None, page_path=None): 48 def __init__(self, source, *, name=None, dir_path=None, page_path=None):
27 self.source = source 49 self.source = source
31 self._cache = None 53 self._cache = None
32 self._is_listable = None 54 self._is_listable = None
33 55
34 def __iter__(self): 56 def __iter__(self):
35 self._load() 57 self._load()
36 return iter(self._cache.values()) 58 return LinkedPageDataIterator(self._cache.values())
37 59
38 def __getattr__(self, name): 60 def __getattr__(self, name):
39 self._load() 61 self._load()
40 try: 62 try:
41 return self._cache[name] 63 return self._cache[name]
83 self._cache[name] = LinkedPageData(name, page, 105 self._cache[name] = LinkedPageData(name, page,
84 is_root_page) 106 is_root_page)
85 107
86 108
87 class RecursiveLinker(Linker): 109 class RecursiveLinker(Linker):
88 def __init__(self, source, page_path): 110 def __init__(self, source, *args, **kwargs):
89 super(RecursiveLinker, self).__init__(source, page_path=page_path) 111 super(RecursiveLinker, self).__init__(source, *args, **kwargs)
90 112
91 def __iter__(self): 113 def __iter__(self):
114 return iter(PageIterator(self._iterateLinkers()))
115
116 def siblings(self):
117 return PageIterator(self._iterateLinkers(0))
118
119 def frompath(self, rel_path):
120 return RecursiveLinker(self.source, name='.', dir_path=rel_path)
121
122 def _iterateLinkers(self, max_depth=-1):
92 self._load() 123 self._load()
93 if not self._is_listable: 124 if not self._is_listable:
94 return 125 return
95 yield from walk_linkers(self) 126 yield from walk_linkers(self, 0, max_depth)
96 127
97 128
98 def walk_linkers(linker): 129 def walk_linkers(linker, depth=0, max_depth=-1):
99 linker._load() 130 linker._load()
100 for item in linker._cache.values(): 131 for item in linker._cache.values():
101 if item.is_dir: 132 if item.is_dir:
102 yield from walk_linkers(item) 133 if max_depth < 0 or depth + 1 <= max_depth:
134 yield from walk_linkers(item, depth + 1, max_depth)
103 else: 135 else:
104 yield item 136 yield item
105 137