Mercurial > piecrust2
comparison piecrust/rendering.py @ 96:0445a2232de7
Improvements and fixes to incremental baking.
* Better handling of the render pass during page rendering.
* Used sources are paired with the pass they were used in.
* Proper use and invalidation of the rendered segments cache based on render
passes.
* The `Assetor` is also better tracking what was used in a page.
* Add flags on a page to get better caching information for the debug window.
* Property invalidation of the previous bake record when needed.
* Better information about why pages are delayed.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Sun, 07 Sep 2014 23:48:57 -0700 |
parents | 2fec3ee1298f |
children | 28444014ce7d |
comparison
equal
deleted
inserted
replaced
95:cb6eadea0845 | 96:0445a2232de7 |
---|---|
1 import re | 1 import re |
2 import os.path | 2 import os.path |
3 import logging | 3 import logging |
4 from piecrust.data.builder import (DataBuildingContext, build_page_data, | 4 from piecrust.data.builder import (DataBuildingContext, build_page_data, |
5 build_layout_data) | 5 build_layout_data) |
6 from piecrust.environment import PHASE_PAGE_FORMATTING, PHASE_PAGE_RENDERING | |
7 from piecrust.sources.base import PageSource | 6 from piecrust.sources.base import PageSource |
8 from piecrust.uriutil import get_slug | 7 from piecrust.uriutil import get_slug |
9 | 8 |
10 | 9 |
11 logger = logging.getLogger(__name__) | 10 logger = logging.getLogger(__name__) |
29 self.execution_info = None | 28 self.execution_info = None |
30 | 29 |
31 @property | 30 @property |
32 def app(self): | 31 def app(self): |
33 return self.page.app | 32 return self.page.app |
33 | |
34 | |
35 PASS_NONE = 0 | |
36 PASS_FORMATTING = 1 | |
37 PASS_RENDERING = 2 | |
34 | 38 |
35 | 39 |
36 class PageRenderingContext(object): | 40 class PageRenderingContext(object): |
37 def __init__(self, page, uri, page_num=1): | 41 def __init__(self, page, uri, page_num=1): |
38 self.page = page | 42 self.page = page |
44 self.use_cache = False | 48 self.use_cache = False |
45 self.used_assets = None | 49 self.used_assets = None |
46 self.used_pagination = None | 50 self.used_pagination = None |
47 self.used_source_names = set() | 51 self.used_source_names = set() |
48 self.used_taxonomy_terms = set() | 52 self.used_taxonomy_terms = set() |
53 self.current_pass = PASS_NONE | |
49 | 54 |
50 @property | 55 @property |
51 def app(self): | 56 def app(self): |
52 return self.page.app | 57 return self.page.app |
53 | 58 |
64 | 69 |
65 def setPagination(self, paginator): | 70 def setPagination(self, paginator): |
66 if self.used_pagination is not None: | 71 if self.used_pagination is not None: |
67 raise Exception("Pagination has already been used.") | 72 raise Exception("Pagination has already been used.") |
68 self.used_pagination = paginator | 73 self.used_pagination = paginator |
74 self.addUsedSource(paginator._source) | |
69 | 75 |
70 def addUsedSource(self, source): | 76 def addUsedSource(self, source): |
71 if isinstance(source, PageSource): | 77 if isinstance(source, PageSource): |
72 self.used_source_names.add(source.name) | 78 self.used_source_names.add((source.name, self.current_pass)) |
73 | 79 |
74 | 80 |
75 def render_page(ctx): | 81 def render_page(ctx): |
76 eis = ctx.app.env.exec_info_stack | 82 eis = ctx.app.env.exec_info_stack |
77 eis.pushPage(ctx.page, PHASE_PAGE_RENDERING, ctx) | 83 eis.pushPage(ctx.page, ctx) |
78 try: | 84 try: |
79 page = ctx.page | 85 page = ctx.page |
80 | 86 |
81 # Build the data for both segment and layout rendering. | 87 # Build the data for both segment and layout rendering. |
82 data_ctx = DataBuildingContext(page, ctx.uri, ctx.page_num) | 88 data_ctx = DataBuildingContext(page, ctx.uri, ctx.page_num) |
85 page_data = build_page_data(data_ctx) | 91 page_data = build_page_data(data_ctx) |
86 if ctx.custom_data: | 92 if ctx.custom_data: |
87 page_data.update(ctx.custom_data) | 93 page_data.update(ctx.custom_data) |
88 | 94 |
89 # Render content segments. | 95 # Render content segments. |
96 ctx.current_pass = PASS_FORMATTING | |
90 repo = ctx.app.env.rendered_segments_repository | 97 repo = ctx.app.env.rendered_segments_repository |
91 if repo: | 98 if repo: |
92 cache_key = '%s:%s' % (ctx.uri, ctx.page_num) | 99 cache_key = '%s:%s' % (ctx.uri, ctx.page_num) |
93 page_time = page.path_mtime | 100 page_time = page.path_mtime |
94 contents = repo.get(cache_key, | 101 contents = repo.get(cache_key, |
96 fs_cache_time=page_time) | 103 fs_cache_time=page_time) |
97 else: | 104 else: |
98 contents = _do_render_page_segments(page, page_data) | 105 contents = _do_render_page_segments(page, page_data) |
99 | 106 |
100 # Render layout. | 107 # Render layout. |
108 ctx.current_pass = PASS_RENDERING | |
101 layout_name = page.config.get('layout') | 109 layout_name = page.config.get('layout') |
102 if layout_name is None: | 110 if layout_name is None: |
103 layout_name = page.source.config.get('default_layout', 'default') | 111 layout_name = page.source.config.get('default_layout', 'default') |
104 null_names = ['', 'none', 'nil'] | 112 null_names = ['', 'none', 'nil'] |
105 if layout_name not in null_names: | 113 if layout_name not in null_names: |
112 rp.data = page_data | 120 rp.data = page_data |
113 rp.content = output | 121 rp.content = output |
114 rp.execution_info = eis.current_page_info | 122 rp.execution_info = eis.current_page_info |
115 return rp | 123 return rp |
116 finally: | 124 finally: |
125 ctx.current_pass = PASS_NONE | |
117 eis.popPage() | 126 eis.popPage() |
118 | 127 |
119 | 128 |
120 def render_page_segments(ctx): | 129 def render_page_segments(ctx): |
121 repo = ctx.app.env.rendered_segments_repository | 130 repo = ctx.app.env.rendered_segments_repository |
128 return _do_render_page_segments_from_ctx(ctx) | 137 return _do_render_page_segments_from_ctx(ctx) |
129 | 138 |
130 | 139 |
131 def _do_render_page_segments_from_ctx(ctx): | 140 def _do_render_page_segments_from_ctx(ctx): |
132 eis = ctx.app.env.exec_info_stack | 141 eis = ctx.app.env.exec_info_stack |
133 eis.pushPage(ctx.page, PHASE_PAGE_FORMATTING, ctx) | 142 eis.pushPage(ctx.page, ctx) |
143 ctx.current_pass = PASS_FORMATTING | |
134 try: | 144 try: |
135 data_ctx = DataBuildingContext(ctx.page, ctx.uri, ctx.page_num) | 145 data_ctx = DataBuildingContext(ctx.page, ctx.uri, ctx.page_num) |
136 page_data = build_page_data(data_ctx) | 146 page_data = build_page_data(data_ctx) |
137 return _do_render_page_segments(ctx.page, page_data) | 147 return _do_render_page_segments(ctx.page, page_data) |
138 finally: | 148 finally: |
149 ctx.current_pass = PASS_NONE | |
139 eis.popPage() | 150 eis.popPage() |
140 | 151 |
141 | 152 |
142 def _do_render_page_segments(page, page_data): | 153 def _do_render_page_segments(page, page_data): |
143 app = page.app | 154 app = page.app |