Mercurial > piecrust2
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__() |