Mercurial > piecrust2
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piecrust/data/base.py Sun Aug 10 23:43:16 2014 -0700 @@ -0,0 +1,132 @@ +import time +import logging +from piecrust.data.assetor import Assetor + + +logger = logging.getLogger(__name__) + + +class LazyPageConfigData(object): + """ An object that represents the configuration header of a page, + but also allows for additional data. It's meant to be exposed + to the templating system. + """ + def __init__(self, page): + self._page = page + self._values = None + self._loaders = None + + @property + def page(self): + return self._page + + def __getitem__(self, name): + self._load() + + if self._loaders: + loader = self._loaders.get(name) + if loader is not None: + try: + self._values[name] = loader(self, name) + except Exception as ex: + logger.error("Error while loading attribute '%s' for: %s" + % (name, self._page.path)) + logger.exception(ex) + raise Exception("Internal Error: %s" % ex) + + # We need to double-check `_loaders` here because + # the loader could have removed all loaders, which + # would set this back to `None`. + if self._loaders is not None: + del self._loaders[name] + if len(self._loaders) == 0: + self._loaders = None + + return self._values[name] + + def setValue(self, name, value): + self._values[name] = value + + def mapLoader(self, attr_name, loader): + if loader is None: + if self._loaders is None or attr_name not in self._loaders: + return + del self._loaders[attr_name] + if len(self._loaders) == 0: + self._loaders = None + return + + if self._loaders is None: + self._loaders = {} + if attr_name in self._loaders: + raise Exception("A loader has already been mapped for: %s" % + attr_name) + self._loaders[attr_name] = loader + + def _load(self): + if self._values is not None: + return + self._values = dict(self._page.config.get()) + try: + self._loadCustom() + except Exception as ex: + logger.error("Error while loading data for: %s" % self._page.path) + logger.exception(ex) + raise Exception("Internal Error: %s" % ex) + + def _loadCustom(self): + pass + + +def build_uri(page): + route = page.app.getRoute(page.source.name, page.source_metadata) + if route is None: + raise Exception("Can't get route for page: %s" % page.path) + return route.getUri(page.source_metadata) + + +def load_rendered_segment(data, name): + from piecrust.rendering import PageRenderingContext, render_page_segments + + uri = build_uri(data.page) + try: + ctx = PageRenderingContext(data.page, uri) + segs = render_page_segments(ctx) + except Exception as e: + logger.exception("Error rendering segments for '%s': %s" % (uri, e)) + raise + + for k, v in segs.iteritems(): + data.mapLoader(k, None) + data.setValue(k, v) + + if 'content.abstract' in segs: + data.setValue('content', segs['content.abstract']) + data.setValue('has_more', True) + if name == 'content': + return segs['content.abstract'] + + return segs[name] + + +class PaginationData(LazyPageConfigData): + def __init__(self, page): + super(PaginationData, self).__init__(page) + + def _loadCustom(self): + page_url = build_uri(self.page) + self.setValue('url', page_url) + self.setValue('slug', page_url) + self.setValue('timestamp', + time.mktime(self.page.datetime.timetuple())) + date_format = self.page.app.config.get('site/date_format') + if date_format: + self.setValue('date', self.page.datetime.strftime(date_format)) + + assetor = Assetor(self.page, page_url) + self.setValue('assets', assetor) + + segment_names = self.page.config.get('segments') + for name in segment_names: + self.mapLoader(name, load_rendered_segment) +