comparison piecrust/sources/blogarchives.py @ 857:d231a10d18f9

refactor: Make the data providers and blog archives source functional. Also, because of a behaviour change in Jinja, the blog archives sources is now offering monthly archives by itself.
author Ludovic Chabant <ludovic@chabant.com>
date Thu, 08 Jun 2017 08:49:33 -0700
parents 9bb22bbe093c
children 504ddb370df8
comparison
equal deleted inserted replaced
856:9bb22bbe093c 857:d231a10d18f9
1 import time
1 import logging 2 import logging
2 import datetime 3 import datetime
4 import collections
3 from piecrust.data.filters import PaginationFilter, IFilterClause 5 from piecrust.data.filters import PaginationFilter, IFilterClause
4 from piecrust.dataproviders.pageiterator import ( 6 from piecrust.dataproviders.pageiterator import (
5 PageIterator, HardCodedFilterIterator, DateSortIterator) 7 PageIterator, HardCodedFilterIterator, DateSortIterator)
6 from piecrust.page import Page 8 from piecrust.page import Page
7 from piecrust.pipelines._pagebaker import PageBaker 9 from piecrust.pipelines._pagebaker import PageBaker
9 from piecrust.pipelines.base import ( 11 from piecrust.pipelines.base import (
10 ContentPipeline, get_record_name_for_source) 12 ContentPipeline, get_record_name_for_source)
11 from piecrust.routing import RouteParameter 13 from piecrust.routing import RouteParameter
12 from piecrust.sources.base import ContentItem 14 from piecrust.sources.base import ContentItem
13 from piecrust.sources.generator import GeneratorSourceBase 15 from piecrust.sources.generator import GeneratorSourceBase
16 from piecrust.sources.list import ListSource
14 17
15 18
16 logger = logging.getLogger(__name__) 19 logger = logging.getLogger(__name__)
17 20
18 21
65 it = PageIterator(self.inner_source) 68 it = PageIterator(self.inner_source)
66 it._simpleNonSortedWrap(HardCodedFilterIterator, flt2) 69 it._simpleNonSortedWrap(HardCodedFilterIterator, flt2)
67 it._wrapAsSort(DateSortIterator, reverse=False) 70 it._wrapAsSort(DateSortIterator, reverse=False)
68 ctx.custom_data['archives'] = it 71 ctx.custom_data['archives'] = it
69 72
70 def _bakeDirtyYears(self, ctx, all_years, dirty_years): 73 ctx.custom_data['monthly_archives'] = _MonthlyArchiveData(
71 route = self.app.getGeneratorRoute(self.name) 74 self.inner_source, year)
72 if route is None:
73 raise Exception(
74 "No routes have been defined for generator: %s" %
75 self.name)
76
77 logger.debug("Using archive page: %s" % self.page_ref)
78 fac = self.page_ref.getFactory()
79
80 for y in dirty_years:
81 extra_route_metadata = {'year': y}
82
83 logger.debug("Queuing: %s [%s]" % (fac.ref_spec, y))
84 ctx.queueBakeJob(fac, route, extra_route_metadata, str(y))
85 ctx.runJobQueue()
86 75
87 76
88 class IsFromYearFilterClause(IFilterClause): 77 class IsFromYearFilterClause(IFilterClause):
89 def __init__(self, year): 78 def __init__(self, year):
90 self.year = year 79 self.year = year
91 80
92 def pageMatches(self, fil, page): 81 def pageMatches(self, fil, page):
93 return (page.datetime.year == self.year) 82 return (page.datetime.year == self.year)
94 83
95 84
96 def _date_sorter(it): 85 class _MonthlyArchiveData(collections.abc.Mapping):
97 return sorted(it, key=lambda x: x.datetime) 86 def __init__(self, inner_source, year):
87 self._inner_source = inner_source
88 self._year = year
89 self._months = None
90
91 def __iter__(self):
92 self._load()
93 return iter(self._months)
94
95 def __len__(self):
96 self._load()
97 return len(self._months)
98
99 def __getitem__(self, i):
100 self._load()
101 return self._months[i]
102
103 def _load(self):
104 if self._months is not None:
105 return
106
107 month_index = {}
108 src = self._inner_source
109 app = src.app
110 for item in self._inner_source.getAllContents():
111 page = app.getPage(src, item)
112
113 if page.datetime.year != self._year:
114 continue
115
116 month = page.datetime.month
117
118 posts_this_month = month_index.get(month)
119 if posts_this_month is None:
120 posts_this_month = []
121 month_index[month] = posts_this_month
122 posts_this_month.append(page.content_item)
123
124 self._months = []
125 for m, ptm in month_index.items():
126 timestamp = time.mktime((self._year, m, 1, 0, 0, 0, 0, 0, -1))
127
128 it = PageIterator(ListSource(self._inner_source, ptm))
129 it._wrapAsSort(DateSortIterator, reverse=False)
130
131 self._months.append({
132 'timestamp': timestamp,
133 'posts': it
134 })
98 135
99 136
100 class BlogArchivesPipelineRecordEntry(PagePipelineRecordEntry): 137 class BlogArchivesPipelineRecordEntry(PagePipelineRecordEntry):
101 def __init__(self): 138 def __init__(self):
102 super().__init__() 139 super().__init__()