changeset 729:e35407c60e00

templating: Make blog archives generator expose more templating data. In addition to pagination data, also expose a non-paginating iterator that lists all posts in a source by chronological order.
author Ludovic Chabant <ludovic@chabant.com>
date Wed, 01 Jun 2016 22:09:21 -0700
parents e7481bbbb29f
children 8c3c2b949b82
files piecrust/data/iterators.py piecrust/data/pagedata.py piecrust/data/paginationdata.py piecrust/data/provider.py piecrust/generation/blogarchives.py tests/test_data_iterators.py
diffstat 6 files changed, 49 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/piecrust/data/iterators.py	Mon May 30 20:45:27 2016 -0700
+++ b/piecrust/data/iterators.py	Wed Jun 01 22:09:21 2016 -0700
@@ -109,13 +109,27 @@
                 yield page
 
 
+class GenericSortIterator(object):
+    def __init__(self, it, sorter):
+        self.it = it
+        self.sorter = sorter
+        self._sorted_it = None
+
+    def __iter__(self):
+        if self._sorted_it is None:
+            self._sorted_it = self.sorter(self.it)
+        return iter(self._sorted_it)
+
+
 class PageIterator(object):
     debug_render = []
     debug_render_doc_dynamic = ['_debugRenderDoc']
     debug_render_not_empty = True
 
-    def __init__(self, source, current_page=None, pagination_filter=None,
-            offset=0, limit=-1, locked=False):
+    def __init__(self, source, *,
+                 current_page=None,
+                 pagination_filter=None, sorter=None,
+                 offset=0, limit=-1, locked=False):
         self._source = source
         self._current_page = current_page
         self._locked = False
@@ -151,6 +165,10 @@
             self._simpleNonSortedWrap(PaginationFilterIterator,
                                       pagination_filter)
 
+        if sorter is not None:
+            self._simpleNonSortedWrap(GenericSortIterator, sorter)
+            self._has_sorter = True
+
         if offset > 0 or limit > 0:
             self.slice(offset, limit)
 
--- a/piecrust/data/pagedata.py	Mon May 30 20:45:27 2016 -0700
+++ b/piecrust/data/pagedata.py	Wed Jun 01 22:09:21 2016 -0700
@@ -157,10 +157,14 @@
 
     def _load(self):
         page = self._page
+        dt = page.datetime
         for k, v in page.source_metadata.items():
             self._setValue(k, v)
         self._setValue('url', self._ctx.uri)
-        self._setValue('timestamp', time.mktime(page.datetime.timetuple()))
+        self._setValue('timestamp', time.mktime(dt.timetuple()))
+        self._setValue('datetime', {
+            'year': dt.year, 'month': dt.month, 'day': dt.day,
+            'hour': dt.hour, 'minute': dt.minute, 'second': dt.second})
         date_format = page.app.config.get('site/date_format')
         if date_format:
             self._setValue('date', page.datetime.strftime(date_format))
--- a/piecrust/data/paginationdata.py	Mon May 30 20:45:27 2016 -0700
+++ b/piecrust/data/paginationdata.py	Wed Jun 01 22:09:21 2016 -0700
@@ -29,6 +29,7 @@
 
     def _load(self):
         page = self._page
+        dt = page.datetime
         page_url = self._get_uri()
         _, slug = split_uri(page.app, page_url)
         self._setValue('url', page_url)
@@ -36,6 +37,9 @@
         self._setValue(
                 'timestamp',
                 time.mktime(page.datetime.timetuple()))
+        self._setValue('datetime', {
+            'year': dt.year, 'month': dt.month, 'day': dt.day,
+            'hour': dt.hour, 'minute': dt.minute, 'second': dt.second})
         date_format = page.app.config.get('site/date_format')
         if date_format:
             self._setValue('date', page.datetime.strftime(date_format))
--- a/piecrust/data/provider.py	Mon May 30 20:45:27 2016 -0700
+++ b/piecrust/data/provider.py	Wed Jun 01 22:09:21 2016 -0700
@@ -248,5 +248,5 @@
         if self._iterator is not None:
             return
 
-        self._iterator = PageIterator(self._source, self._page)
+        self._iterator = PageIterator(self._source, current_page=self._page)
 
--- a/piecrust/generation/blogarchives.py	Mon May 30 20:45:27 2016 -0700
+++ b/piecrust/generation/blogarchives.py	Wed Jun 01 22:09:21 2016 -0700
@@ -1,6 +1,8 @@
 import logging
 import datetime
+from piecrust.chefutil import format_timed_scope
 from piecrust.data.filters import PaginationFilter, IFilterClause
+from piecrust.data.iterators import PageIterator
 from piecrust.generation.base import PageGenerator
 
 
@@ -34,6 +36,12 @@
 
         ctx.custom_data['year'] = year
 
+        flt2 = PaginationFilter()
+        flt2.addClause(IsFromYearFilterClause(year))
+        it = PageIterator(self.source, pagination_filter=flt2,
+                          sorter=_date_sorter)
+        ctx.custom_data['archives'] = it
+
     def bake(self, ctx):
         if not self.page_ref.exists:
             logger.debug(
@@ -88,11 +96,11 @@
                     y = ctx.getSeedFromRecordExtraKey(prev_entry.extra_key)
                 except InvalidRecordExtraKey:
                     continue
-            if y in all_years:
-                logger.debug("Creating unbaked entry for %d archive." % y)
-                ctx.collapseRecord(prev_entry)
-            else:
-                logger.debug("No page references year %d anymore." % y)
+                if y in all_years:
+                    logger.debug("Creating unbaked entry for %d archive." % y)
+                    ctx.collapseRecord(prev_entry)
+                else:
+                    logger.debug("No page references year %d anymore." % y)
 
 
 class IsFromYearFilterClause(IFilterClause):
@@ -102,3 +110,7 @@
     def pageMatches(self, fil, page):
         return (page.datetime.year == self.year)
 
+
+def _date_sorter(it):
+    return sorted(it, key=lambda x: x.datetime)
+
--- a/tests/test_data_iterators.py	Mon May 30 20:45:27 2016 -0700
+++ b/tests/test_data_iterators.py	Wed Jun 01 22:09:21 2016 -0700
@@ -72,7 +72,8 @@
     page = mock.MagicMock(spec=Page)
     page.config = PageConfiguration()
     page.config.set('threes', {'is_foo': 3})
-    it = PageIterator([TestItem(v) for v in [3, 2, 3, 1, 4, 3]], page)
+    it = PageIterator([TestItem(v) for v in [3, 2, 3, 1, 4, 3]],
+                      current_page=page)
     it.filter('threes')
     assert it.total_count == 3
     assert len(it) == 3