Mercurial > piecrust2
comparison piecrust/generation/blogarchives.py @ 724:09115f0900f0
bake: Add blog archives generator.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Sun, 29 May 2016 20:20:19 -0700 |
parents | ab5c6a8ae90a |
children | e35407c60e00 |
comparison
equal
deleted
inserted
replaced
723:606f6d57b5df | 724:09115f0900f0 |
---|---|
1 import logging | |
2 import datetime | |
3 from piecrust.data.filters import PaginationFilter, IFilterClause | |
1 from piecrust.generation.base import PageGenerator | 4 from piecrust.generation.base import PageGenerator |
5 | |
6 | |
7 logger = logging.getLogger(__name__) | |
2 | 8 |
3 | 9 |
4 class BlogArchivesPageGenerator(PageGenerator): | 10 class BlogArchivesPageGenerator(PageGenerator): |
5 GENERATOR_NAME = 'blog_archives' | 11 GENERATOR_NAME = 'blog_archives' |
6 | 12 |
7 def bake(self, ctx): | 13 def __init__(self, app, name, config): |
14 super(BlogArchivesPageGenerator, self).__init__(app, name, config) | |
15 | |
16 def onRouteFunctionUsed(self, route, route_metadata): | |
8 pass | 17 pass |
9 | 18 |
19 def prepareRenderContext(self, ctx): | |
20 ctx.pagination_source = self.source | |
21 | |
22 year = ctx.page.route_metadata.get('year') | |
23 if year is None: | |
24 raise Exception( | |
25 "Can't find the archive year in the route metadata") | |
26 if type(year) is not int: | |
27 raise Exception( | |
28 "The route for generator '%s' should specify an integer " | |
29 "parameter for 'year'." % self.name) | |
30 | |
31 flt = PaginationFilter() | |
32 flt.addClause(IsFromYearFilterClause(year)) | |
33 ctx.pagination_filter = flt | |
34 | |
35 ctx.custom_data['year'] = year | |
36 | |
37 def bake(self, ctx): | |
38 if not self.page_ref.exists: | |
39 logger.debug( | |
40 "No page found at '%s', skipping %s archives." % | |
41 (self.page_ref, self.source_name)) | |
42 return | |
43 | |
44 logger.debug("Baking %s archives...", self.source_name) | |
45 with format_timed_scope(logger, 'gathered archive years', | |
46 level=logging.DEBUG, colored=False): | |
47 all_years, dirty_years = self._buildDirtyYears(ctx) | |
48 | |
49 with format_timed_scope(logger, "baked %d %s archives." % | |
50 (len(dirty_years), self.source_name)): | |
51 self._bakeDirtyYears(ctx, all_years, dirty_years) | |
52 | |
53 def _buildDirtyYears(self, ctx): | |
54 logger.debug("Gathering dirty post years.") | |
55 all_years = set() | |
56 dirty_years = set() | |
57 for _, cur_entry in ctx.getAllPageRecords(): | |
58 if cur_entry.source_name == self.source_name: | |
59 dt = datetime.datetime.fromtimestamp(cur_entry.timestamp) | |
60 all_years.add(dt.year) | |
61 if cur_entry.was_any_sub_baked: | |
62 dirty_years.add(dt.year) | |
63 return all_years, dirty_years | |
64 | |
65 def _bakeDirtyYears(self, ctx, all_years, dirty_years): | |
66 route = self.app.getGeneratorRoute(self.name) | |
67 if route is None: | |
68 raise Exception( | |
69 "No routes have been defined for generator: %s" % | |
70 self.name) | |
71 | |
72 logger.debug("Using archive page: %s" % self.page_ref) | |
73 fac = self.page_ref.getFactory() | |
74 | |
75 for y in dirty_years: | |
76 extra_route_metadata = {'year': y} | |
77 | |
78 logger.debug("Queuing: %s [%s]" % (fac.ref_spec, y)) | |
79 ctx.queueBakeJob(fac, route, extra_route_metadata, str(y)) | |
80 ctx.runJobQueue() | |
81 | |
82 # Create bake entries for the years that were *not* dirty. | |
83 # Otherwise, when checking for deleted pages, we would not find any | |
84 # outputs and would delete those files. | |
85 for prev_entry, cur_entry in ctx.getAllPageRecords(): | |
86 if prev_entry and not cur_entry: | |
87 try: | |
88 y = ctx.getSeedFromRecordExtraKey(prev_entry.extra_key) | |
89 except InvalidRecordExtraKey: | |
90 continue | |
91 if y in all_years: | |
92 logger.debug("Creating unbaked entry for %d archive." % y) | |
93 ctx.collapseRecord(prev_entry) | |
94 else: | |
95 logger.debug("No page references year %d anymore." % y) | |
96 | |
97 | |
98 class IsFromYearFilterClause(IFilterClause): | |
99 def __init__(self, year): | |
100 self.year = year | |
101 | |
102 def pageMatches(self, fil, page): | |
103 return (page.datetime.year == self.year) | |
104 |