annotate piecrust/data/linker.py @ 298:b7ab1b503510

data: Fix incorrect next/previous page URLs in pagination data. Consolidate splitting an URL between its first URL and its sub page number. Be careful about the index page's URL not losing its slash.
author Ludovic Chabant <ludovic@chabant.com>
date Wed, 11 Mar 2015 23:46:42 -0700
parents 311447fe3dd0
children 2408eb6f4da8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
172
4fc1d306046b linker: Actually implement the `Linker` class, and use it in the page data.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
1 import logging
4fc1d306046b linker: Actually implement the `Linker` class, and use it in the page data.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
2 import collections
242
f130365568ff internal: Code reorganization to put less stuff in `sources.base`.
Ludovic Chabant <ludovic@chabant.com>
parents: 237
diff changeset
3 from piecrust.data.base import PaginationData
212
701591ebfcba data: Improve the Linker and RecursiveLinker features. Add tests.
Ludovic Chabant <ludovic@chabant.com>
parents: 172
diff changeset
4 from piecrust.data.iterators import PageIterator
242
f130365568ff internal: Code reorganization to put less stuff in `sources.base`.
Ludovic Chabant <ludovic@chabant.com>
parents: 237
diff changeset
5 from piecrust.sources.base import build_pages
f130365568ff internal: Code reorganization to put less stuff in `sources.base`.
Ludovic Chabant <ludovic@chabant.com>
parents: 237
diff changeset
6 from piecrust.sources.interfaces import IPaginationSource, IListableSource
172
4fc1d306046b linker: Actually implement the `Linker` class, and use it in the page data.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
7
4fc1d306046b linker: Actually implement the `Linker` class, and use it in the page data.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
8
4fc1d306046b linker: Actually implement the `Linker` class, and use it in the page data.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
9 logger = logging.getLogger(__name__)
4fc1d306046b linker: Actually implement the `Linker` class, and use it in the page data.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
10
4fc1d306046b linker: Actually implement the `Linker` class, and use it in the page data.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
11
247
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
12 class PageLinkerData(object):
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
13 """ Entry template data to get access to related pages from a given
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
14 root page.
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
15 """
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
16 def __init__(self, source, page_path):
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
17 self._linker = Linker(source, page_path)
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
18
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
19 @property
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
20 def siblings(self):
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
21 return self._linker
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
22
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
23 @property
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
24 def children(self):
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
25 self._linker._load()
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
26 if self._linker._self_item is None:
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
27 return None
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
28 return self._linker._self_item.config.get('__linker_child')
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
29
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
30 @property
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
31 def root(self):
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
32 return self._linker.root
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
33
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
34 def forpath(self, rel_path):
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
35 return self._linker.forpath(rel_path)
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
36
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
37
172
4fc1d306046b linker: Actually implement the `Linker` class, and use it in the page data.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
38 class LinkedPageData(PaginationData):
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
39 """ Class whose instances get returned when iterating on a `Linker`
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
40 or `RecursiveLinker`. It's just like what gets usually returned by
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
41 `Paginator` and other page iterators, but with a few additional data
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
42 like hierarchical data.
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
43 """
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
44 debug_render = ['is_dir', 'is_self'] + PaginationData.debug_render
172
4fc1d306046b linker: Actually implement the `Linker` class, and use it in the page data.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
45
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
46 def __init__(self, page):
172
4fc1d306046b linker: Actually implement the `Linker` class, and use it in the page data.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
47 super(LinkedPageData, self).__init__(page)
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
48 self.name = page.config.get('__linker_name')
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
49 self.is_self = page.config.get('__linker_is_self')
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
50 self.children = page.config.get('__linker_child')
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
51 self.is_dir = (self.children is not None)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
52 self.is_page = True
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
53
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
54 self.mapLoader('*', self._linkerChildLoader)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
55
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
56 def _linkerChildLoader(self, name):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
57 return getattr(self.children, name)
172
4fc1d306046b linker: Actually implement the `Linker` class, and use it in the page data.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
58
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
59
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
60 class LinkedPageDataBuilderIterator(object):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
61 """ Iterator that builds `LinkedPageData` out of pages.
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
62 """
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
63 def __init__(self, it):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
64 self.it = it
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
65
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
66 def __iter__(self):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
67 for item in self.it:
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
68 yield LinkedPageData(item)
3
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
69
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
70
227
d6d0e4976beb data: Make the `Linekr` use the new `getSettingAccessor` API.
Ludovic Chabant <ludovic@chabant.com>
parents: 212
diff changeset
71 class LinkerSource(IPaginationSource):
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
72 """ Source iterator that returns pages given by `Linker`.
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
73 """
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
74 def __init__(self, pages, orig_source):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
75 self._pages = list(pages)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
76 self._orig_source = None
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
77 if isinstance(orig_source, IPaginationSource):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
78 self._orig_source = orig_source
227
d6d0e4976beb data: Make the `Linekr` use the new `getSettingAccessor` API.
Ludovic Chabant <ludovic@chabant.com>
parents: 212
diff changeset
79
d6d0e4976beb data: Make the `Linekr` use the new `getSettingAccessor` API.
Ludovic Chabant <ludovic@chabant.com>
parents: 212
diff changeset
80 def getItemsPerPage(self):
d6d0e4976beb data: Make the `Linekr` use the new `getSettingAccessor` API.
Ludovic Chabant <ludovic@chabant.com>
parents: 212
diff changeset
81 raise NotImplementedError()
d6d0e4976beb data: Make the `Linekr` use the new `getSettingAccessor` API.
Ludovic Chabant <ludovic@chabant.com>
parents: 212
diff changeset
82
d6d0e4976beb data: Make the `Linekr` use the new `getSettingAccessor` API.
Ludovic Chabant <ludovic@chabant.com>
parents: 212
diff changeset
83 def getSourceIterator(self):
d6d0e4976beb data: Make the `Linekr` use the new `getSettingAccessor` API.
Ludovic Chabant <ludovic@chabant.com>
parents: 212
diff changeset
84 return self._pages
d6d0e4976beb data: Make the `Linekr` use the new `getSettingAccessor` API.
Ludovic Chabant <ludovic@chabant.com>
parents: 212
diff changeset
85
d6d0e4976beb data: Make the `Linekr` use the new `getSettingAccessor` API.
Ludovic Chabant <ludovic@chabant.com>
parents: 212
diff changeset
86 def getSorterIterator(self, it):
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
87 # We don't want to sort the pages -- we expect the original source
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
88 # to return hierarchical items in the order it wants already.
227
d6d0e4976beb data: Make the `Linekr` use the new `getSettingAccessor` API.
Ludovic Chabant <ludovic@chabant.com>
parents: 212
diff changeset
89 return None
d6d0e4976beb data: Make the `Linekr` use the new `getSettingAccessor` API.
Ludovic Chabant <ludovic@chabant.com>
parents: 212
diff changeset
90
d6d0e4976beb data: Make the `Linekr` use the new `getSettingAccessor` API.
Ludovic Chabant <ludovic@chabant.com>
parents: 212
diff changeset
91 def getTailIterator(self, it):
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
92 return LinkedPageDataBuilderIterator(it)
227
d6d0e4976beb data: Make the `Linekr` use the new `getSettingAccessor` API.
Ludovic Chabant <ludovic@chabant.com>
parents: 212
diff changeset
93
d6d0e4976beb data: Make the `Linekr` use the new `getSettingAccessor` API.
Ludovic Chabant <ludovic@chabant.com>
parents: 212
diff changeset
94 def getPaginationFilter(self, page):
d6d0e4976beb data: Make the `Linekr` use the new `getSettingAccessor` API.
Ludovic Chabant <ludovic@chabant.com>
parents: 212
diff changeset
95 return None
d6d0e4976beb data: Make the `Linekr` use the new `getSettingAccessor` API.
Ludovic Chabant <ludovic@chabant.com>
parents: 212
diff changeset
96
d6d0e4976beb data: Make the `Linekr` use the new `getSettingAccessor` API.
Ludovic Chabant <ludovic@chabant.com>
parents: 212
diff changeset
97 def getSettingAccessor(self):
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
98 if self._orig_source:
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
99 return self._orig_source.getSettingAccessor()
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
100 return None
212
701591ebfcba data: Improve the Linker and RecursiveLinker features. Add tests.
Ludovic Chabant <ludovic@chabant.com>
parents: 172
diff changeset
101
701591ebfcba data: Improve the Linker and RecursiveLinker features. Add tests.
Ludovic Chabant <ludovic@chabant.com>
parents: 172
diff changeset
102
3
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
103 class Linker(object):
172
4fc1d306046b linker: Actually implement the `Linker` class, and use it in the page data.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
104 debug_render_doc = """Provides access to sibling and children pages."""
4fc1d306046b linker: Actually implement the `Linker` class, and use it in the page data.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
105
247
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
106 def __init__(self, source, root_page_path, *, name=None, dir_path=None):
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
107 self._source = source
247
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
108 self._root_page_path = root_page_path
172
4fc1d306046b linker: Actually implement the `Linker` class, and use it in the page data.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
109 self._name = name
4fc1d306046b linker: Actually implement the `Linker` class, and use it in the page data.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
110 self._dir_path = dir_path
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
111 self._items = None
247
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
112 self._self_item = None
172
4fc1d306046b linker: Actually implement the `Linker` class, and use it in the page data.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
113
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
114 self.is_dir = True
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
115 self.is_page = False
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
116 self.is_self = False
172
4fc1d306046b linker: Actually implement the `Linker` class, and use it in the page data.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
117
4fc1d306046b linker: Actually implement the `Linker` class, and use it in the page data.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
118 def __iter__(self):
227
d6d0e4976beb data: Make the `Linekr` use the new `getSettingAccessor` API.
Ludovic Chabant <ludovic@chabant.com>
parents: 212
diff changeset
119 return iter(self.pages)
212
701591ebfcba data: Improve the Linker and RecursiveLinker features. Add tests.
Ludovic Chabant <ludovic@chabant.com>
parents: 172
diff changeset
120
227
d6d0e4976beb data: Make the `Linekr` use the new `getSettingAccessor` API.
Ludovic Chabant <ludovic@chabant.com>
parents: 212
diff changeset
121 def __getattr__(self, name):
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
122 self._load()
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
123 try:
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
124 item = self._items[name]
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
125 except KeyError:
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
126 raise AttributeError()
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
127
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
128 if isinstance(item, Linker):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
129 return item
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
130
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
131 return LinkedPageData(item)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
132
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
133 @property
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
134 def name(self):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
135 if self._name is None:
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
136 self._load()
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
137 return self._name
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
138
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
139 @property
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
140 def children(self):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
141 return self._iterItems(0)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
142
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
143 @property
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
144 def pages(self):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
145 return self._iterItems(0, filter_page_items)
227
d6d0e4976beb data: Make the `Linekr` use the new `getSettingAccessor` API.
Ludovic Chabant <ludovic@chabant.com>
parents: 212
diff changeset
146
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
147 @property
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
148 def directories(self):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
149 return self._iterItems(0, filter_directory_items)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
150
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
151 @property
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
152 def all(self):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
153 return self._iterItems()
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
154
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
155 @property
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
156 def allpages(self):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
157 return self._iterItems(-1, filter_page_items)
227
d6d0e4976beb data: Make the `Linekr` use the new `getSettingAccessor` API.
Ludovic Chabant <ludovic@chabant.com>
parents: 212
diff changeset
158
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
159 @property
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
160 def alldirectories(self):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
161 return self._iterItems(-1, filter_directory_items)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
162
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
163 @property
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
164 def root(self):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
165 return self.forpath('/')
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
166
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
167 def forpath(self, rel_path):
247
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
168 return Linker(self._source, self._root_page_path,
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
169 name='.', dir_path=rel_path)
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
170
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
171 def _iterItems(self, max_depth=-1, filter_func=None):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
172 items = walk_linkers(self, max_depth=max_depth,
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
173 filter_func=filter_func)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
174 src = LinkerSource(items, self._source)
227
d6d0e4976beb data: Make the `Linekr` use the new `getSettingAccessor` API.
Ludovic Chabant <ludovic@chabant.com>
parents: 212
diff changeset
175 return PageIterator(src)
212
701591ebfcba data: Improve the Linker and RecursiveLinker features. Add tests.
Ludovic Chabant <ludovic@chabant.com>
parents: 172
diff changeset
176
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
177 def _load(self):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
178 if self._items is not None:
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
179 return
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
180
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
181 is_listable = isinstance(self._source, IListableSource)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
182 if not is_listable:
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
183 raise Exception("Source '%s' can't be listed." % self._source.name)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
184
247
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
185 if self._name is None:
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
186 self._name = self._source.getBasename(self._root_page_path)
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
187 if self._dir_path is None:
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
188 self._dir_path = self._source.getDirpath(self._root_page_path)
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
189
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
190 if self._dir_path is None:
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
191 raise Exception("This linker has no directory to start from.")
212
701591ebfcba data: Improve the Linker and RecursiveLinker features. Add tests.
Ludovic Chabant <ludovic@chabant.com>
parents: 172
diff changeset
192
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
193 items = list(self._source.listPath(self._dir_path))
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
194 self._items = collections.OrderedDict()
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
195 with self._source.app.env.page_repository.startBatchGet():
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
196 for is_dir, name, data in items:
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
197 # If `is_dir` is true, `data` will be the directory's source
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
198 # path. If not, it will be a page factory.
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
199 if is_dir:
247
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
200 item = Linker(self._source, self._root_page_path,
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
201 name=name, dir_path=data)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
202 else:
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
203 item = data.buildPage()
247
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
204 is_self = (item.rel_path == self._root_page_path)
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
205 item.config.set('__linker_name', name)
247
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
206 item.config.set('__linker_is_self', is_self)
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
207 if is_self:
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
208 self._self_item = item
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
209
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
210 existing = self._items.get(name)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
211 if existing is None:
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
212 self._items[name] = item
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
213 elif is_dir:
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
214 # The current item is a directory. The existing item
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
215 # should be a page.
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
216 existing.config.set('__linker_child', item)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
217 else:
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
218 # The current item is a page. The existing item should
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
219 # be a directory.
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
220 item.config.set('__linker_child', existing)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
221 self._items[name] = item
172
4fc1d306046b linker: Actually implement the `Linker` class, and use it in the page data.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
222
4fc1d306046b linker: Actually implement the `Linker` class, and use it in the page data.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
223
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
224 def filter_page_items(item):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
225 return not isinstance(item, Linker)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
226
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
227
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
228 def filter_directory_items(item):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
229 return isinstance(item, linker)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
230
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
231
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
232 def walk_linkers(linker, depth=0, max_depth=-1, filter_func=None):
172
4fc1d306046b linker: Actually implement the `Linker` class, and use it in the page data.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
233 linker._load()
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
234 for item in linker._items.values():
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
235 if not filter_func or filter_func(item):
172
4fc1d306046b linker: Actually implement the `Linker` class, and use it in the page data.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
236 yield item
4fc1d306046b linker: Actually implement the `Linker` class, and use it in the page data.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
237
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
238 if (isinstance(item, Linker) and
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
239 (max_depth < 0 or depth + 1 <= max_depth)):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
240 yield from walk_linkers(item, depth + 1, max_depth)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
241