Mercurial > piecrust2
comparison piecrust/data/paginationdata.py @ 874:f4608e2e80ce
data: Optimize page data creation.
`datetime.strftime` was pretty costly so it's no lazily-computed in some
places, and replaced with some better alternative elsewhere.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Thu, 15 Jun 2017 07:31:50 -0700 |
parents | 08e02c2a2a1a |
children | d6d35b2efd04 |
comparison
equal
deleted
inserted
replaced
873:93ea115027fc | 874:f4608e2e80ce |
---|---|
9 class PaginationData(LazyPageConfigData): | 9 class PaginationData(LazyPageConfigData): |
10 def __init__(self, page): | 10 def __init__(self, page): |
11 super().__init__(page) | 11 super().__init__(page) |
12 | 12 |
13 def _load(self): | 13 def _load(self): |
14 from piecrust.data.assetor import Assetor | |
15 from piecrust.uriutil import split_uri | 14 from piecrust.uriutil import split_uri |
16 | 15 |
17 page = self._page | 16 page = self._page |
18 dt = page.datetime | 17 dt = page.datetime |
18 set_val = self._setValue | |
19 | |
19 page_url = page.getUri() | 20 page_url = page.getUri() |
20 _, slug = split_uri(page.app, page_url) | 21 _, slug = split_uri(page.app, page_url) |
21 self._setValue('url', page_url) | 22 set_val('url', page_url) |
22 self._setValue('slug', slug) | 23 set_val('slug', slug) |
23 self._setValue('timestamp', | 24 set_val('timestamp', time.mktime(page.datetime.timetuple())) |
24 time.mktime(page.datetime.timetuple())) | 25 set_val('datetime', { |
25 self._setValue('datetime', { | |
26 'year': dt.year, 'month': dt.month, 'day': dt.day, | 26 'year': dt.year, 'month': dt.month, 'day': dt.day, |
27 'hour': dt.hour, 'minute': dt.minute, 'second': dt.second}) | 27 'hour': dt.hour, 'minute': dt.minute, 'second': dt.second}) |
28 date_format = page.app.config.get('site/date_format') | 28 set_val('mtime', page.content_mtime) |
29 if date_format: | |
30 self._setValue('date', page.datetime.strftime(date_format)) | |
31 self._setValue('mtime', page.content_mtime) | |
32 | 29 |
33 assetor = Assetor(page) | 30 self._mapLoader('date', _load_date) |
34 self._setValue('assets', assetor) | 31 self._mapLoader('assets', _load_assets) |
35 | 32 |
36 segment_names = page.config.get('segments') | 33 segment_names = page.config.get('segments') |
37 for name in segment_names: | 34 for name in segment_names: |
38 self._mapLoader(name, self._load_rendered_segment) | 35 self._mapLoader(name, _load_rendered_segment) |
39 | 36 |
40 def _load_rendered_segment(self, data, name): | |
41 do_render = True | |
42 stack = self._page.app.env.render_ctx_stack | |
43 if stack.hasPage(self._page): | |
44 # This is the pagination data for the page that is currently | |
45 # being rendered! Inception! But this is possible... so just | |
46 # prevent infinite recursion. | |
47 do_render = False | |
48 | 37 |
49 assert self is data | 38 def _load_assets(data, name): |
39 from piecrust.data.assetor import Assetor | |
40 return Assetor(data._page) | |
50 | 41 |
51 if do_render: | |
52 uri = self._page.getUri() | |
53 try: | |
54 from piecrust.rendering import ( | |
55 RenderingContext, render_page_segments) | |
56 ctx = RenderingContext(self._page) | |
57 render_result = render_page_segments(ctx) | |
58 segs = render_result.segments | |
59 except Exception as ex: | |
60 logger.exception(ex) | |
61 raise Exception( | |
62 "Error rendering segments for '%s'" % uri) from ex | |
63 else: | |
64 segs = {} | |
65 for name in self._page.config.get('segments'): | |
66 segs[name] = "<unavailable: current page>" | |
67 | 42 |
68 for k, v in segs.items(): | 43 def _load_date(data, name): |
69 self._unmapLoader(k) | 44 page = data._page |
70 self._setValue(k, v) | 45 date_format = page.app.config.get('site/date_format') |
46 if date_format: | |
47 return page.datetime.strftime(date_format) | |
48 return None | |
71 | 49 |
72 if 'content.abstract' in segs: | |
73 self._setValue('content', segs['content.abstract']) | |
74 self._setValue('has_more', True) | |
75 if name == 'content': | |
76 return segs['content.abstract'] | |
77 | 50 |
78 return segs[name] | 51 def _load_rendered_segment(data, name): |
52 page = data._page | |
79 | 53 |
54 do_render = True | |
55 stack = page.app.env.render_ctx_stack | |
56 if stack.hasPage(page): | |
57 # This is the pagination data for the page that is currently | |
58 # being rendered! Inception! But this is possible... so just | |
59 # prevent infinite recursion. | |
60 do_render = False | |
61 | |
62 if do_render: | |
63 uri = page.getUri() | |
64 try: | |
65 from piecrust.rendering import ( | |
66 RenderingContext, render_page_segments) | |
67 ctx = RenderingContext(page) | |
68 render_result = render_page_segments(ctx) | |
69 segs = render_result.segments | |
70 except Exception as ex: | |
71 logger.exception(ex) | |
72 raise Exception( | |
73 "Error rendering segments for '%s'" % uri) from ex | |
74 else: | |
75 segs = {} | |
76 for name in page.config.get('segments'): | |
77 segs[name] = "<unavailable: current page>" | |
78 | |
79 unmap_loader = data._unmapLoader | |
80 set_val = data._setValue | |
81 | |
82 for k, v in segs.items(): | |
83 unmap_loader(k) | |
84 set_val(k, v) | |
85 | |
86 if 'content.abstract' in segs: | |
87 set_val('content', segs['content.abstract']) | |
88 set_val('has_more', True) | |
89 if name == 'content': | |
90 return segs['content.abstract'] | |
91 | |
92 return segs[name] | |
93 |