Mercurial > piecrust2
changeset 12:30a42341cfa8
Define page slugs properly, avoid recursions with debug data.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Mon, 18 Aug 2014 16:49:54 -0700 |
parents | 617191dec18e |
children | a8f9c78a6608 |
files | piecrust/data/base.py piecrust/data/builder.py piecrust/environment.py piecrust/rendering.py piecrust/uriutil.py |
diffstat | 5 files changed, 98 insertions(+), 25 deletions(-) [+] |
line wrap: on
line diff
--- a/piecrust/data/base.py Mon Aug 18 16:47:44 2014 -0700 +++ b/piecrust/data/base.py Mon Aug 18 16:49:54 2014 -0700 @@ -1,12 +1,16 @@ import time import logging from piecrust.data.assetor import Assetor +from piecrust.uriutil import get_slug logger = logging.getLogger(__name__) class IPaginationSource(object): + """ Defines the interface for a source that can be used as the data + for an iterator or a pagination. + """ def getItemsPerPage(self): raise NotImplementedError() @@ -28,6 +32,9 @@ but also allows for additional data. It's meant to be exposed to the templating system. """ + debug_render = [] + debug_render_dynamic = ['_debugRenderKeys'] + def __init__(self, page): self._page = page self._values = None @@ -37,7 +44,16 @@ def page(self): return self._page + def __getattr__(self, name): + try: + return self.getValue(name) + except KeyError: + raise AttributeError + def __getitem__(self, name): + return self.getValue(name) + + def getValue(self, name): self._load() if self._loaders: @@ -46,10 +62,8 @@ 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) + raise Exception("Error while loading attribute '%s' for: %s" + % (name, self._page.rel_path)) from ex # We need to double-check `_loaders` here because # the loader could have removed all loaders, which @@ -87,13 +101,18 @@ 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) + raise Exception("Error while loading data for: %s" % self._page.rel_path) from ex def _loadCustom(self): pass + def _debugRenderKeys(self): + self._load() + keys = set(self._values.keys()) + if self._loaders: + keys |= set(self._loaders.keys()) + return list(keys) + class PaginationData(LazyPageConfigData): def __init__(self, page): @@ -109,7 +128,7 @@ def _loadCustom(self): page_url = self._get_uri() self.setValue('url', page_url) - self.setValue('slug', page_url) + self.setValue('slug', get_slug(self._page.app, page_url)) self.setValue('timestamp', time.mktime(self.page.datetime.timetuple())) date_format = self.page.app.config.get('site/date_format') @@ -124,16 +143,29 @@ self.mapLoader(name, self._load_rendered_segment) def _load_rendered_segment(self, data, name): - from piecrust.rendering import PageRenderingContext, render_page_segments + do_render = True + eis = self._page.app.env.exec_info_stack + if eis is not None and eis.hasPage(self._page): + # This is the pagination data for the page that is currently + # being rendered! Inception! But this is possible... so just + # prevent infinite recursion. + do_render = False assert self is data - uri = self._get_uri() - try: - ctx = PageRenderingContext(self._page, uri) - segs = render_page_segments(ctx) - except Exception as e: - logger.exception("Error rendering segments for '%s': %s" % (uri, e)) - raise + + if do_render: + uri = self._get_uri() + try: + from piecrust.rendering import (PageRenderingContext, + render_page_segments) + ctx = PageRenderingContext(self._page, uri) + segs = render_page_segments(ctx) + except Exception as e: + raise Exception("Error rendering segments for '%s'" % uri) from e + else: + segs = {} + for name in self.page.config.get('segments'): + segs[name] = "<unavailable: current page>" for k, v in segs.items(): self.mapLoader(k, None)
--- a/piecrust/data/builder.py Mon Aug 18 16:47:44 2014 -0700 +++ b/piecrust/data/builder.py Mon Aug 18 16:49:54 2014 -0700 @@ -5,6 +5,7 @@ from piecrust.data.debug import build_debug_info from piecrust.data.linker import Linker from piecrust.data.paginator import Paginator +from piecrust.uriutil import get_slug logger = logging.getLogger(__name__) @@ -18,18 +19,23 @@ self.pagination_source = None self.pagination_filter = None + @property + def slug(self): + return get_slug(self.page.app, self.uri) + def build_page_data(ctx): page = ctx.page app = page.app + pc_data = PieCrustData() pgn_source = ctx.pagination_source or get_default_pagination_source(page) paginator = Paginator(page, pgn_source, ctx.uri, ctx.page_num, ctx.pagination_filter) assetor = Assetor(page, ctx.uri) linker = Linker(page) data = { - 'piecrust': build_piecrust_data(), + 'piecrust': pc_data, 'page': dict(page.config.get()), 'assets': assetor, 'pagination': paginator, @@ -38,6 +44,7 @@ } page_data = data['page'] page_data['url'] = ctx.uri + page_data['slug'] = ctx.slug page_data['timestamp'] = time.mktime(page.datetime.timetuple()) date_format = app.config.get('site/date_format') if date_format: @@ -52,7 +59,7 @@ # displayed in the debugger window. if (app.debug and app.config.get('site/enable_debug_info') and not app.config.get('baker/is_baking')): - data['piecrust']['debug_info'] = build_debug_info(page, data) + pc_data._enableDebugInfo(page, data) return data @@ -73,14 +80,31 @@ from piecrust import APP_VERSION as VERSION -def build_piecrust_data(): - data = { - 'version': VERSION, - 'url': 'http://bolt80.com/piecrust/', - 'branding': 'Baked with <em><a href="%s">PieCrust</a> %s</em>.' % ( +class PieCrustData(object): + debug_render = ['version', 'url', 'branding', 'debug_info'] + debug_render_invoke = ['version', 'url', 'branding', 'debug_info'] + debug_render_redirect = {'debug_info': '_debugRenderDebugInfo'} + + def __init__(self): + self.version = VERSION + self.url = 'http://bolt80.com/piecrust/' + self.branding = 'Baked with <em><a href="%s">PieCrust</a> %s</em>.' % ( 'http://bolt80.com/piecrust/', VERSION) - } - return data + self._page = None + self._data = None + + @property + def debug_info(self): + if self._page is not None and self._data is not None: + return build_debug_info(self._page, self._data) + return None + + def _enableDebugInfo(self, page, data): + self._page = page + self._data = data + + def _debugRenderDebugInfo(self): + return "The very thing you're looking at!" def build_site_data(page):
--- a/piecrust/environment.py Mon Aug 18 16:47:44 2014 -0700 +++ b/piecrust/environment.py Mon Aug 18 16:49:54 2014 -0700 @@ -53,6 +53,12 @@ def is_main_page(self): return len(self._page_stack) == 1 + def hasPage(self, page): + for ei in self._page_stack: + if ei.page == page: + return True + return False + def pushPage(self, page, phase, render_ctx): self._page_stack.append(ExecutionInfo(page, phase, render_ctx))
--- a/piecrust/rendering.py Mon Aug 18 16:47:44 2014 -0700 +++ b/piecrust/rendering.py Mon Aug 18 16:49:54 2014 -0700 @@ -4,6 +4,7 @@ from piecrust.data.builder import (DataBuildingContext, build_page_data, build_layout_data) from piecrust.environment import PHASE_PAGE_FORMATTING, PHASE_PAGE_RENDERING +from piecrust.uriutil import get_slug logger = logging.getLogger(__name__) @@ -49,6 +50,10 @@ return self.page.app @property + def slug(self): + return get_slug(self.page.app, self.uri) + + @property def source_metadata(self): return self.page.source_metadata
--- a/piecrust/uriutil.py Mon Aug 18 16:47:44 2014 -0700 +++ b/piecrust/uriutil.py Mon Aug 18 16:49:54 2014 -0700 @@ -72,3 +72,9 @@ pattern = re.compile("|".join(list(reps.keys()))) return pattern.sub(lambda m: reps[re.escape(m.group(0))], text) + +def get_slug(app, uri): + site_root = app.config.get('site/root') + uri = uri[len(site_root):] + return uri.lstrip('/') +