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