diff 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
line wrap: on
line diff
--- a/piecrust/data/linker.py	Sat Jan 03 20:51:34 2015 -0800
+++ b/piecrust/data/linker.py	Sat Jan 03 20:52:19 2015 -0800
@@ -1,6 +1,105 @@
+import logging
+import collections
+from piecrust.data.base import PaginationData
+from piecrust.sources.base import IListableSource, build_pages
+
+
+logger = logging.getLogger(__name__)
+
+
+class LinkedPageData(PaginationData):
+    debug_render = ['name', 'is_dir', 'is_self']
+
+    def __init__(self, name, page, is_self=False):
+        super(LinkedPageData, self).__init__(page)
+        self.name = name
+        self.is_self = is_self
+
+    @property
+    def is_dir(self):
+        return False
 
 
 class Linker(object):
-    def __init__(self, page):
-        self.page = page
+    debug_render_doc = """Provides access to sibling and children pages."""
+
+    def __init__(self, source, *, name=None, dir_path=None, page_path=None):
+        self.source = source
+        self._name = name
+        self._dir_path = dir_path
+        self._root_page_path = page_path
+        self._cache = None
+        self._is_listable = None
+
+    def __iter__(self):
+        self._load()
+        return iter(self._cache.values())
+
+    def __getattr__(self, name):
+        self._load()
+        try:
+            return self._cache[name]
+        except KeyError:
+            raise AttributeError()
+
+    @property
+    def name(self):
+        if not self._name:
+            self._load()
+        return self._name
+
+    @property
+    def is_dir(self):
+        return True
+
+    @property
+    def is_self(self):
+        return False
+
+    def _load(self):
+        if self._cache is not None:
+            return
 
+        self._is_listable = isinstance(self.source, IListableSource)
+        if self._is_listable and self._root_page_path is not None:
+            if self._name is None:
+                self._name = self.source.getBasename(self._root_page_path)
+            if self._dir_path is None:
+                self._dir_path = self.source.getDirpath(self._root_page_path)
+
+        self._cache = collections.OrderedDict()
+        if not self._is_listable or self._dir_path is None:
+            return
+
+        items = self.source.listPath(self._dir_path)
+        with self.source.app.env.page_repository.startBatchGet():
+            for is_dir, name, data in items:
+                if is_dir:
+                    self._cache[name] = Linker(self.source,
+                                               name=name, dir_path=data)
+                else:
+                    page = data.buildPage()
+                    is_root_page = (self._root_page_path == data.rel_path)
+                    self._cache[name] = LinkedPageData(name, page,
+                                                       is_root_page)
+
+
+class RecursiveLinker(Linker):
+    def __init__(self, source, page_path):
+        super(RecursiveLinker, self).__init__(source, page_path=page_path)
+
+    def __iter__(self):
+        self._load()
+        if not self._is_listable:
+            return
+        yield from walk_linkers(self)
+
+
+def walk_linkers(linker):
+    linker._load()
+    for item in linker._cache.values():
+        if item.is_dir:
+            yield from walk_linkers(item)
+        else:
+            yield item
+