Mercurial > piecrust2
comparison piecrust/data/base.py @ 3:f485ba500df3
Gigantic change to basically make PieCrust 2 vaguely functional.
- Serving works, with debug window.
- Baking works, multi-threading, with dependency handling.
- Various things not implemented yet.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Sun, 10 Aug 2014 23:43:16 -0700 |
parents | |
children | 474c9882decf |
comparison
equal
deleted
inserted
replaced
2:40fa08b261b9 | 3:f485ba500df3 |
---|---|
1 import time | |
2 import logging | |
3 from piecrust.data.assetor import Assetor | |
4 | |
5 | |
6 logger = logging.getLogger(__name__) | |
7 | |
8 | |
9 class LazyPageConfigData(object): | |
10 """ An object that represents the configuration header of a page, | |
11 but also allows for additional data. It's meant to be exposed | |
12 to the templating system. | |
13 """ | |
14 def __init__(self, page): | |
15 self._page = page | |
16 self._values = None | |
17 self._loaders = None | |
18 | |
19 @property | |
20 def page(self): | |
21 return self._page | |
22 | |
23 def __getitem__(self, name): | |
24 self._load() | |
25 | |
26 if self._loaders: | |
27 loader = self._loaders.get(name) | |
28 if loader is not None: | |
29 try: | |
30 self._values[name] = loader(self, name) | |
31 except Exception as ex: | |
32 logger.error("Error while loading attribute '%s' for: %s" | |
33 % (name, self._page.path)) | |
34 logger.exception(ex) | |
35 raise Exception("Internal Error: %s" % ex) | |
36 | |
37 # We need to double-check `_loaders` here because | |
38 # the loader could have removed all loaders, which | |
39 # would set this back to `None`. | |
40 if self._loaders is not None: | |
41 del self._loaders[name] | |
42 if len(self._loaders) == 0: | |
43 self._loaders = None | |
44 | |
45 return self._values[name] | |
46 | |
47 def setValue(self, name, value): | |
48 self._values[name] = value | |
49 | |
50 def mapLoader(self, attr_name, loader): | |
51 if loader is None: | |
52 if self._loaders is None or attr_name not in self._loaders: | |
53 return | |
54 del self._loaders[attr_name] | |
55 if len(self._loaders) == 0: | |
56 self._loaders = None | |
57 return | |
58 | |
59 if self._loaders is None: | |
60 self._loaders = {} | |
61 if attr_name in self._loaders: | |
62 raise Exception("A loader has already been mapped for: %s" % | |
63 attr_name) | |
64 self._loaders[attr_name] = loader | |
65 | |
66 def _load(self): | |
67 if self._values is not None: | |
68 return | |
69 self._values = dict(self._page.config.get()) | |
70 try: | |
71 self._loadCustom() | |
72 except Exception as ex: | |
73 logger.error("Error while loading data for: %s" % self._page.path) | |
74 logger.exception(ex) | |
75 raise Exception("Internal Error: %s" % ex) | |
76 | |
77 def _loadCustom(self): | |
78 pass | |
79 | |
80 | |
81 def build_uri(page): | |
82 route = page.app.getRoute(page.source.name, page.source_metadata) | |
83 if route is None: | |
84 raise Exception("Can't get route for page: %s" % page.path) | |
85 return route.getUri(page.source_metadata) | |
86 | |
87 | |
88 def load_rendered_segment(data, name): | |
89 from piecrust.rendering import PageRenderingContext, render_page_segments | |
90 | |
91 uri = build_uri(data.page) | |
92 try: | |
93 ctx = PageRenderingContext(data.page, uri) | |
94 segs = render_page_segments(ctx) | |
95 except Exception as e: | |
96 logger.exception("Error rendering segments for '%s': %s" % (uri, e)) | |
97 raise | |
98 | |
99 for k, v in segs.iteritems(): | |
100 data.mapLoader(k, None) | |
101 data.setValue(k, v) | |
102 | |
103 if 'content.abstract' in segs: | |
104 data.setValue('content', segs['content.abstract']) | |
105 data.setValue('has_more', True) | |
106 if name == 'content': | |
107 return segs['content.abstract'] | |
108 | |
109 return segs[name] | |
110 | |
111 | |
112 class PaginationData(LazyPageConfigData): | |
113 def __init__(self, page): | |
114 super(PaginationData, self).__init__(page) | |
115 | |
116 def _loadCustom(self): | |
117 page_url = build_uri(self.page) | |
118 self.setValue('url', page_url) | |
119 self.setValue('slug', page_url) | |
120 self.setValue('timestamp', | |
121 time.mktime(self.page.datetime.timetuple())) | |
122 date_format = self.page.app.config.get('site/date_format') | |
123 if date_format: | |
124 self.setValue('date', self.page.datetime.strftime(date_format)) | |
125 | |
126 assetor = Assetor(self.page, page_url) | |
127 self.setValue('assets', assetor) | |
128 | |
129 segment_names = self.page.config.get('segments') | |
130 for name in segment_names: | |
131 self.mapLoader(name, load_rendered_segment) | |
132 |