annotate piecrust/data/linker.py @ 368:2408eb6f4da8

linker: Don't put linker stuff in the config. Now that we want to deep-copy configuration, we can't put objects in there. We create a wrapper for pages that will store linker-specific objects in a separate attribute.
author Ludovic Chabant <ludovic@chabant.com>
date Sun, 03 May 2015 18:43:28 -0700
parents 311447fe3dd0
children 4c9eab0e283b
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
368
2408eb6f4da8 linker: Don't put linker stuff in the config.
Ludovic Chabant <ludovic@chabant.com>
parents: 250
diff changeset
28 return self._linker._self_item._linker_info.child_linker
247
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)
368
2408eb6f4da8 linker: Don't put linker stuff in the config.
Ludovic Chabant <ludovic@chabant.com>
parents: 250
diff changeset
48 self.name = page._linker_info.name
2408eb6f4da8 linker: Don't put linker stuff in the config.
Ludovic Chabant <ludovic@chabant.com>
parents: 250
diff changeset
49 self.is_self = page._linker_info.is_self
2408eb6f4da8 linker: Don't put linker stuff in the config.
Ludovic Chabant <ludovic@chabant.com>
parents: 250
diff changeset
50 self.children = page._linker_info.child_linker
237
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
368
2408eb6f4da8 linker: Don't put linker stuff in the config.
Ludovic Chabant <ludovic@chabant.com>
parents: 250
diff changeset
103 class _LinkerInfo(object):
2408eb6f4da8 linker: Don't put linker stuff in the config.
Ludovic Chabant <ludovic@chabant.com>
parents: 250
diff changeset
104 def __init__(self):
2408eb6f4da8 linker: Don't put linker stuff in the config.
Ludovic Chabant <ludovic@chabant.com>
parents: 250
diff changeset
105 self.name = None
2408eb6f4da8 linker: Don't put linker stuff in the config.
Ludovic Chabant <ludovic@chabant.com>
parents: 250
diff changeset
106 self.is_self = False
2408eb6f4da8 linker: Don't put linker stuff in the config.
Ludovic Chabant <ludovic@chabant.com>
parents: 250
diff changeset
107 self.child_linker = None
2408eb6f4da8 linker: Don't put linker stuff in the config.
Ludovic Chabant <ludovic@chabant.com>
parents: 250
diff changeset
108
2408eb6f4da8 linker: Don't put linker stuff in the config.
Ludovic Chabant <ludovic@chabant.com>
parents: 250
diff changeset
109
2408eb6f4da8 linker: Don't put linker stuff in the config.
Ludovic Chabant <ludovic@chabant.com>
parents: 250
diff changeset
110 class _LinkedPage(object):
2408eb6f4da8 linker: Don't put linker stuff in the config.
Ludovic Chabant <ludovic@chabant.com>
parents: 250
diff changeset
111 def __init__(self, page):
2408eb6f4da8 linker: Don't put linker stuff in the config.
Ludovic Chabant <ludovic@chabant.com>
parents: 250
diff changeset
112 self._page = page
2408eb6f4da8 linker: Don't put linker stuff in the config.
Ludovic Chabant <ludovic@chabant.com>
parents: 250
diff changeset
113 self._linker_info = _LinkerInfo()
2408eb6f4da8 linker: Don't put linker stuff in the config.
Ludovic Chabant <ludovic@chabant.com>
parents: 250
diff changeset
114
2408eb6f4da8 linker: Don't put linker stuff in the config.
Ludovic Chabant <ludovic@chabant.com>
parents: 250
diff changeset
115 def __getattr__(self, name):
2408eb6f4da8 linker: Don't put linker stuff in the config.
Ludovic Chabant <ludovic@chabant.com>
parents: 250
diff changeset
116 return getattr(self._page, name)
2408eb6f4da8 linker: Don't put linker stuff in the config.
Ludovic Chabant <ludovic@chabant.com>
parents: 250
diff changeset
117
2408eb6f4da8 linker: Don't put linker stuff in the config.
Ludovic Chabant <ludovic@chabant.com>
parents: 250
diff changeset
118
3
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
119 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
120 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
121
247
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
122 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
123 self._source = source
247
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
124 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
125 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
126 self._dir_path = dir_path
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
127 self._items = None
247
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
128 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
129
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
130 self.is_dir = True
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
131 self.is_page = False
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
132 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
133
4fc1d306046b linker: Actually implement the `Linker` class, and use it in the page data.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
134 def __iter__(self):
227
d6d0e4976beb data: Make the `Linekr` use the new `getSettingAccessor` API.
Ludovic Chabant <ludovic@chabant.com>
parents: 212
diff changeset
135 return iter(self.pages)
212
701591ebfcba data: Improve the Linker and RecursiveLinker features. Add tests.
Ludovic Chabant <ludovic@chabant.com>
parents: 172
diff changeset
136
227
d6d0e4976beb data: Make the `Linekr` use the new `getSettingAccessor` API.
Ludovic Chabant <ludovic@chabant.com>
parents: 212
diff changeset
137 def __getattr__(self, name):
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
138 self._load()
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
139 try:
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
140 item = self._items[name]
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
141 except KeyError:
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
142 raise AttributeError()
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
143
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
144 if isinstance(item, Linker):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
145 return item
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
146
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
147 return LinkedPageData(item)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
148
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
149 @property
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
150 def name(self):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
151 if self._name is None:
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
152 self._load()
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
153 return self._name
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 children(self):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
157 return self._iterItems(0)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
158
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 pages(self):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
161 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
162
237
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 directories(self):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
165 return self._iterItems(0, filter_directory_items)
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 @property
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
168 def all(self):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
169 return self._iterItems()
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 @property
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
172 def allpages(self):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
173 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
174
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
175 @property
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
176 def alldirectories(self):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
177 return self._iterItems(-1, filter_directory_items)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
178
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
179 @property
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
180 def root(self):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
181 return self.forpath('/')
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
182
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
183 def forpath(self, rel_path):
247
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
184 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
185 name='.', dir_path=rel_path)
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
186
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
187 def _iterItems(self, max_depth=-1, filter_func=None):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
188 items = walk_linkers(self, max_depth=max_depth,
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
189 filter_func=filter_func)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
190 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
191 return PageIterator(src)
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 def _load(self):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
194 if self._items is not None:
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
195 return
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
196
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
197 is_listable = isinstance(self._source, IListableSource)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
198 if not is_listable:
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
199 raise Exception("Source '%s' can't be listed." % self._source.name)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
200
247
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
201 if self._name is None:
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
202 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
203 if self._dir_path is None:
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
204 self._dir_path = self._source.getDirpath(self._root_page_path)
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
205
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
206 if self._dir_path is None:
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
207 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
208
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
209 items = list(self._source.listPath(self._dir_path))
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
210 self._items = collections.OrderedDict()
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
211 with self._source.app.env.page_repository.startBatchGet():
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
212 for is_dir, name, data in items:
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
213 # 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
214 # path. If not, it will be a page factory.
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
215 if is_dir:
247
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
216 item = Linker(self._source, self._root_page_path,
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
217 name=name, dir_path=data)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
218 else:
368
2408eb6f4da8 linker: Don't put linker stuff in the config.
Ludovic Chabant <ludovic@chabant.com>
parents: 250
diff changeset
219 page = data.buildPage()
2408eb6f4da8 linker: Don't put linker stuff in the config.
Ludovic Chabant <ludovic@chabant.com>
parents: 250
diff changeset
220 is_self = (page.rel_path == self._root_page_path)
2408eb6f4da8 linker: Don't put linker stuff in the config.
Ludovic Chabant <ludovic@chabant.com>
parents: 250
diff changeset
221 item = _LinkedPage(page)
2408eb6f4da8 linker: Don't put linker stuff in the config.
Ludovic Chabant <ludovic@chabant.com>
parents: 250
diff changeset
222 item._linker_info.name = name
2408eb6f4da8 linker: Don't put linker stuff in the config.
Ludovic Chabant <ludovic@chabant.com>
parents: 250
diff changeset
223 item._linker_info.is_self = is_self
247
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
224 if is_self:
d9d5c5de02a8 data: Add a top level wrapper for `Linker`.
Ludovic Chabant <ludovic@chabant.com>
parents: 242
diff changeset
225 self._self_item = item
237
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 existing = self._items.get(name)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
228 if existing is None:
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
229 self._items[name] = item
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
230 elif is_dir:
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
231 # The current item is a directory. The existing item
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
232 # should be a page.
368
2408eb6f4da8 linker: Don't put linker stuff in the config.
Ludovic Chabant <ludovic@chabant.com>
parents: 250
diff changeset
233 existing._linker_info.child_linker = item
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
234 else:
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
235 # The current item is a page. The existing item should
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
236 # be a directory.
368
2408eb6f4da8 linker: Don't put linker stuff in the config.
Ludovic Chabant <ludovic@chabant.com>
parents: 250
diff changeset
237 item._linker_info.child_linker = existing
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
238 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
239
4fc1d306046b linker: Actually implement the `Linker` class, and use it in the page data.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
240
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
241 def filter_page_items(item):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
242 return not isinstance(item, Linker)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
243
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
244
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
245 def filter_directory_items(item):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
246 return isinstance(item, linker)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
247
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
248
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
249 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
250 linker._load()
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
251 for item in linker._items.values():
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
252 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
253 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
254
237
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
255 if (isinstance(item, Linker) and
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
256 (max_depth < 0 or depth + 1 <= max_depth)):
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
257 yield from walk_linkers(item, depth + 1, max_depth)
879fe1457e48 data: `Linker` refactor.
Ludovic Chabant <ludovic@chabant.com>
parents: 227
diff changeset
258