Mercurial > piecrust2
comparison piecrust/rendering.py @ 719:a066f4ac9094
rendering: Use `fastpickle` serialization before JSON.
This is because JSON loses information about stuff like tuples.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Sat, 28 May 2016 15:43:24 -0700 |
parents | a14371c5cda7 |
children | 606f6d57b5df |
comparison
equal
deleted
inserted
replaced
718:d4408fbbbc7d | 719:a066f4ac9094 |
---|---|
5 from werkzeug.utils import cached_property | 5 from werkzeug.utils import cached_property |
6 from piecrust.data.builder import ( | 6 from piecrust.data.builder import ( |
7 DataBuildingContext, build_page_data, build_layout_data) | 7 DataBuildingContext, build_page_data, build_layout_data) |
8 from piecrust.data.filters import ( | 8 from piecrust.data.filters import ( |
9 PaginationFilter, SettingFilterClause, page_value_accessor) | 9 PaginationFilter, SettingFilterClause, page_value_accessor) |
10 from piecrust.fastpickle import _pickle_object, _unpickle_object | |
10 from piecrust.sources.base import PageSource | 11 from piecrust.sources.base import PageSource |
11 from piecrust.templating.base import TemplateNotFoundError, TemplatingError | 12 from piecrust.templating.base import TemplateNotFoundError, TemplatingError |
12 | 13 |
13 | 14 |
14 logger = logging.getLogger(__name__) | 15 logger = logging.getLogger(__name__) |
89 | 90 |
90 def getCustomInfo(self, key, default=None, create_if_missing=False): | 91 def getCustomInfo(self, key, default=None, create_if_missing=False): |
91 if create_if_missing: | 92 if create_if_missing: |
92 return self._custom_info.setdefault(key, default) | 93 return self._custom_info.setdefault(key, default) |
93 return self._custom_info.get(key, default) | 94 return self._custom_info.get(key, default) |
94 | |
95 | |
96 def _toJson(self): | |
97 data = { | |
98 'used_source_names': list(self.used_source_names), | |
99 'used_pagination': self.used_pagination, | |
100 'pagination_has_more': self.pagination_has_more, | |
101 'used_assets': self.used_assets, | |
102 'custom_info': self._custom_info} | |
103 return data | |
104 | |
105 @staticmethod | |
106 def _fromJson(data): | |
107 assert data is not None | |
108 rpi = RenderPassInfo() | |
109 rpi.used_source_names = set(data['used_source_names']) | |
110 rpi.used_pagination = data['used_pagination'] | |
111 rpi.pagination_has_more = data['pagination_has_more'] | |
112 rpi.used_assets = data['used_assets'] | |
113 rpi._custom_info = data['custom_info'] | |
114 return rpi | |
115 | 95 |
116 | 96 |
117 class PageRenderingContext(object): | 97 class PageRenderingContext(object): |
118 def __init__(self, qualified_page, page_num=1, | 98 def __init__(self, qualified_page, page_num=1, |
119 force_render=False, is_from_request=False): | 99 force_render=False, is_from_request=False): |
216 'pass_info': None} | 196 'pass_info': None} |
217 | 197 |
218 rp = RenderedPage(page, ctx.uri, ctx.page_num) | 198 rp = RenderedPage(page, ctx.uri, ctx.page_num) |
219 rp.data = page_data | 199 rp.data = page_data |
220 rp.content = layout_result['content'] | 200 rp.content = layout_result['content'] |
221 rp.render_info[PASS_FORMATTING] = RenderPassInfo._fromJson( | 201 rp.render_info[PASS_FORMATTING] = _unpickle_object( |
222 render_result['pass_info']) | 202 render_result['pass_info']) |
223 if layout_result['pass_info'] is not None: | 203 if layout_result['pass_info'] is not None: |
224 rp.render_info[PASS_RENDERING] = RenderPassInfo._fromJson( | 204 rp.render_info[PASS_RENDERING] = _unpickle_object( |
225 layout_result['pass_info']) | 205 layout_result['pass_info']) |
226 return rp | 206 return rp |
227 except Exception as ex: | 207 except Exception as ex: |
228 if ctx.app.debug: | 208 if ctx.app.debug: |
229 raise | 209 raise |
230 logger.exception(ex) | 210 logger.exception(ex) |
258 ctx.setCurrentPass(PASS_NONE) | 238 ctx.setCurrentPass(PASS_NONE) |
259 eis.popPage() | 239 eis.popPage() |
260 | 240 |
261 rs = RenderedSegments( | 241 rs = RenderedSegments( |
262 render_result['segments'], | 242 render_result['segments'], |
263 RenderPassInfo._fromJson(render_result['pass_info'])) | 243 _unpickle_object(render_result['pass_info'])) |
264 return rs | 244 return rs |
265 | 245 |
266 | 246 |
267 def _build_render_data(ctx): | 247 def _build_render_data(ctx): |
268 with ctx.app.env.timerScope("PageDataBuild"): | 248 with ctx.app.env.timerScope("PageDataBuild"): |
317 formatted_segments['content.abstract'] = content_abstract | 297 formatted_segments['content.abstract'] = content_abstract |
318 | 298 |
319 pass_info = cpi.render_ctx.render_passes[PASS_FORMATTING] | 299 pass_info = cpi.render_ctx.render_passes[PASS_FORMATTING] |
320 res = { | 300 res = { |
321 'segments': formatted_segments, | 301 'segments': formatted_segments, |
322 'pass_info': pass_info._toJson()} | 302 'pass_info': _pickle_object(pass_info)} |
323 return res | 303 return res |
324 | 304 |
325 | 305 |
326 def _do_render_layout(layout_name, page, layout_data): | 306 def _do_render_layout(layout_name, page, layout_data): |
327 cpi = page.app.env.exec_info_stack.current_page_info | 307 cpi = page.app.env.exec_info_stack.current_page_info |
349 msg = "Can't find template for page: %s\n" % page.path | 329 msg = "Can't find template for page: %s\n" % page.path |
350 msg += "Looked for: %s" % ', '.join(full_names) | 330 msg += "Looked for: %s" % ', '.join(full_names) |
351 raise Exception(msg) from ex | 331 raise Exception(msg) from ex |
352 | 332 |
353 pass_info = cpi.render_ctx.render_passes[PASS_RENDERING] | 333 pass_info = cpi.render_ctx.render_passes[PASS_RENDERING] |
354 res = {'content': output, 'pass_info': pass_info._toJson()} | 334 res = {'content': output, 'pass_info': _pickle_object(pass_info)} |
355 return res | 335 return res |
356 | 336 |
357 | 337 |
358 def get_template_engine(app, engine_name): | 338 def get_template_engine(app, engine_name): |
359 if engine_name == 'html': | 339 if engine_name == 'html': |