comparison piecrust/pipelines/page.py @ 877:d6d35b2efd04

bake: Rename "pass" to "step" and make the page pipeline use different steps. That pipeline is now first loading all pages, and then rendering full pages unless they trigger a sub-render.
author Ludovic Chabant <ludovic@chabant.com>
date Thu, 15 Jun 2017 22:16:23 -0700
parents 504ddb370df8
children b4e10471e970
comparison
equal deleted inserted replaced
876:d1095774bfcf 877:d6d35b2efd04
1 import logging 1 import logging
2 from piecrust.pipelines.base import ContentPipeline 2 from piecrust.pipelines.base import ContentPipeline
3 from piecrust.pipelines._pagebaker import PageBaker 3 from piecrust.pipelines._pagebaker import PageBaker
4 from piecrust.pipelines._pagerecords import PagePipelineRecordEntry 4 from piecrust.pipelines._pagerecords import PagePipelineRecordEntry
5 from piecrust.rendering import (
6 RenderingContext, render_page_segments)
7 from piecrust.sources.base import AbortedSourceUseError 5 from piecrust.sources.base import AbortedSourceUseError
8 6
9 7
10 logger = logging.getLogger(__name__) 8 logger = logging.getLogger(__name__)
11 9
33 existing.errors += record_entry.errors 31 existing.errors += record_entry.errors
34 existing.flags |= record_entry.flags 32 existing.flags |= record_entry.flags
35 existing.subs = record_entry.subs 33 existing.subs = record_entry.subs
36 34
37 def run(self, job, ctx, result): 35 def run(self, job, ctx, result):
38 pass_name = job.data.get('pass', 0) 36 step_num = job.step_num
39 if pass_name == 0: 37 if step_num == 0:
40 self._renderSegmentsOrPostpone(job.content_item, ctx, result) 38 self._loadPage(job.content_item, ctx, result)
41 elif pass_name == 1: 39 elif step_num == 1:
42 self._fullRender(job.content_item, ctx, result) 40 self._renderOrPostpone(job.content_item, ctx, result)
41 elif step_num == 2:
42 self._renderAlways(job.content_item, ctx, result)
43 43
44 def getDeletions(self, ctx): 44 def getDeletions(self, ctx):
45 for prev, cur in ctx.record_history.diffs: 45 for prev, cur in ctx.record_history.diffs:
46 if prev and not cur: 46 if prev and not cur:
47 for sub in prev.subs: 47 for sub in prev.subs:
57 pass 57 pass
58 58
59 def shutdown(self): 59 def shutdown(self):
60 self._pagebaker.stopWriterQueue() 60 self._pagebaker.stopWriterQueue()
61 61
62 def _renderSegmentsOrPostpone(self, content_item, ctx, result): 62 def _loadPage(self, content_item, ctx, result):
63 logger.debug("Loading page: %s" % content_item.spec)
64 page = self.app.getPage(self.source, content_item)
65 record_entry = result.record_entry
66 record_entry.config = page.config.getAll()
67 record_entry.timestamp = page.datetime.timestamp()
68 result.next_step_job = self.createJob(content_item)
69
70 def _renderOrPostpone(self, content_item, ctx, result):
63 # Here our job is to render the page's segments so that they're 71 # Here our job is to render the page's segments so that they're
64 # cached in memory and on disk... unless we detect that the page 72 # cached in memory and on disk... unless we detect that the page
65 # is using some other sources, in which case we abort and we'll try 73 # is using some other sources, in which case we abort and we'll try
66 # again on the second pass. 74 # again on the second pass.
67 logger.debug("Rendering segments for: %s" % content_item.spec) 75 logger.debug("Conditional render for: %s" % content_item.spec)
68 record_entry = result.record_entry
69 stats = self.app.env.stats
70
71 page = self.app.getPage(self.source, content_item) 76 page = self.app.getPage(self.source, content_item)
72 record_entry.config = page.config.getAll() 77 prev_entry = ctx.previous_entry
73 record_entry.timestamp = page.datetime.timestamp() 78 cur_entry = result.record_entry
74
75 rdrctx = RenderingContext(page)
76 self.app.env.abort_source_use = True 79 self.app.env.abort_source_use = True
77 try: 80 try:
78 render_page_segments(rdrctx) 81 self._pagebaker.bake(page, prev_entry, cur_entry)
79 except AbortedSourceUseError: 82 except AbortedSourceUseError:
80 logger.debug("Page was aborted for using source: %s" % 83 logger.debug("Page was aborted for using source: %s" %
81 content_item.spec) 84 content_item.spec)
82 stats.stepCounter("SourceUseAbortions") 85 self.app.env.stats.stepCounter("SourceUseAbortions")
86 result.next_step_job = self.createJob(content_item)
83 finally: 87 finally:
84 self.app.env.abort_source_use = False 88 self.app.env.abort_source_use = False
85 89
86 result.next_pass_job = self.createJob(content_item) 90 def _renderAlways(self, content_item, ctx, result):
87 result.next_pass_job.data.update({
88 'pass': 1,
89 'record_entry': record_entry
90 })
91
92 def _fullRender(self, content_item, ctx, result):
93 logger.debug("Full render for: %s" % content_item.spec) 91 logger.debug("Full render for: %s" % content_item.spec)
94 page = self.app.getPage(self.source, content_item) 92 page = self.app.getPage(self.source, content_item)
95 prev_entry = ctx.previous_entry 93 prev_entry = ctx.previous_entry
96 cur_entry = result.record_entry 94 cur_entry = result.record_entry
97 self._pagebaker.bake(page, prev_entry, cur_entry) 95 self._pagebaker.bake(page, prev_entry, cur_entry)