Mercurial > piecrust2
comparison piecrust/page.py @ 49:fce061f8c2ed
Fix cache validation issue with rendered segments, limit disk access.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Fri, 22 Aug 2014 20:26:05 -0700 |
parents | 343d08ef5668 |
children | 563ce5dd02af |
comparison
equal
deleted
inserted
replaced
48:002fa58f54dc | 49:fce061f8c2ed |
---|---|
5 import os.path | 5 import os.path |
6 import hashlib | 6 import hashlib |
7 import logging | 7 import logging |
8 import datetime | 8 import datetime |
9 import dateutil.parser | 9 import dateutil.parser |
10 from werkzeug.utils import cached_property | |
10 from piecrust.configuration import (Configuration, ConfigurationError, | 11 from piecrust.configuration import (Configuration, ConfigurationError, |
11 parse_config_header) | 12 parse_config_header) |
12 from piecrust.environment import PHASE_PAGE_PARSING | 13 from piecrust.environment import PHASE_PAGE_PARSING |
13 | 14 |
14 | 15 |
34 class Page(object): | 35 class Page(object): |
35 def __init__(self, source, source_metadata, rel_path): | 36 def __init__(self, source, source_metadata, rel_path): |
36 self.source = source | 37 self.source = source |
37 self.source_metadata = source_metadata | 38 self.source_metadata = source_metadata |
38 self.rel_path = rel_path | 39 self.rel_path = rel_path |
39 self.path = source.resolveRef(rel_path) | |
40 self._config = None | 40 self._config = None |
41 self._raw_content = None | 41 self._raw_content = None |
42 self._datetime = None | 42 self._datetime = None |
43 | 43 |
44 @property | 44 @property |
46 return self.source.app | 46 return self.source.app |
47 | 47 |
48 @property | 48 @property |
49 def ref_spec(self): | 49 def ref_spec(self): |
50 return '%s:%s' % (self.source.name, self.rel_path) | 50 return '%s:%s' % (self.source.name, self.rel_path) |
51 | |
52 @cached_property | |
53 def path(self): | |
54 return self.source.resolveRef(self.rel_path) | |
55 | |
56 @cached_property | |
57 def path_mtime(self): | |
58 return os.path.getmtime(self.path) | |
51 | 59 |
52 @property | 60 @property |
53 def config(self): | 61 def config(self): |
54 self._load() | 62 self._load() |
55 return self._config | 63 return self._config |
77 page_time = datetime.time(time_dt.hour, time_dt.minute, time_dt.second) | 85 page_time = datetime.time(time_dt.hour, time_dt.minute, time_dt.second) |
78 else: | 86 else: |
79 page_time = datetime.time(0, 0, 0) | 87 page_time = datetime.time(0, 0, 0) |
80 self._datetime = datetime.datetime.combine(page_date, page_time) | 88 self._datetime = datetime.datetime.combine(page_date, page_time) |
81 else: | 89 else: |
82 self._datetime = datetime.datetime.fromtimestamp(os.path.getmtime(self.path)) | 90 self._datetime = datetime.datetime.fromtimestamp(self.path_mtime) |
83 return self._datetime | 91 return self._datetime |
84 | 92 |
85 @datetime.setter | 93 @datetime.setter |
86 def datetime(self, value): | 94 def datetime(self, value): |
87 self._datetime = value | 95 self._datetime = value |
94 return | 102 return |
95 | 103 |
96 eis = self.app.env.exec_info_stack | 104 eis = self.app.env.exec_info_stack |
97 eis.pushPage(self, PHASE_PAGE_PARSING, None) | 105 eis.pushPage(self, PHASE_PAGE_PARSING, None) |
98 try: | 106 try: |
99 config, content = load_page(self.app, self.path) | 107 config, content = load_page(self.app, self.path, self.path_mtime) |
100 self._config = config | 108 self._config = config |
101 self._raw_content = content | 109 self._raw_content = content |
102 finally: | 110 finally: |
103 eis.popPage() | 111 eis.popPage() |
104 | 112 |
152 seg_data.append(p_data) | 160 seg_data.append(p_data) |
153 data[key] = seg_data | 161 data[key] = seg_data |
154 return data | 162 return data |
155 | 163 |
156 | 164 |
157 def load_page(app, path): | 165 def load_page(app, path, path_mtime=None): |
158 try: | 166 try: |
159 return _do_load_page(app, path) | 167 return _do_load_page(app, path, path_mtime) |
160 except Exception as e: | 168 except Exception as e: |
161 logger.exception("Error loading page: %s" % | 169 logger.exception("Error loading page: %s" % |
162 os.path.relpath(path, app.root_dir)) | 170 os.path.relpath(path, app.root_dir)) |
163 _, __, traceback = sys.exc_info() | 171 _, __, traceback = sys.exc_info() |
164 raise PageLoadingError(path, e).with_traceback(traceback) | 172 raise PageLoadingError(path, e).with_traceback(traceback) |
165 | 173 |
166 | 174 |
167 def _do_load_page(app, path): | 175 def _do_load_page(app, path, path_mtime): |
168 exec_info = app.env.exec_info_stack.current_page_info | 176 exec_info = app.env.exec_info_stack.current_page_info |
169 if exec_info is None: | 177 if exec_info is None: |
170 raise Exception("Loading page '%s' but not execution context has " | 178 raise Exception("Loading page '%s' but not execution context has " |
171 "been created for it." % path) | 179 "been created for it." % path) |
172 | 180 |
173 # Check the cache first. | 181 # Check the cache first. |
174 cache = app.cache.getCache('pages') | 182 cache = app.cache.getCache('pages') |
175 cache_path = "%s.json" % hashlib.md5(path.encode('utf8')).hexdigest() | 183 cache_path = "%s.json" % hashlib.md5(path.encode('utf8')).hexdigest() |
176 page_time = os.path.getmtime(path) | 184 page_time = path_mtime or os.path.getmtime(path) |
177 if cache.isValid(cache_path, page_time): | 185 if cache.isValid(cache_path, page_time): |
178 exec_info.was_cache_valid = True | 186 exec_info.was_cache_valid = True |
179 cache_data = json.loads(cache.read(cache_path)) | 187 cache_data = json.loads(cache.read(cache_path)) |
180 config = PageConfiguration(values=cache_data['config'], | 188 config = PageConfiguration(values=cache_data['config'], |
181 validate=False) | 189 validate=False) |