# HG changeset patch # User Ludovic Chabant # Date 1431243448 25200 # Node ID 4c9eab0e283b2ffa9f746dca44ba378663e36be8 # Parent f33712c4cfabe68fd3e84ff1c5dc626cea48a979 data: Fix problems with using non-existing metadata on a linked page. The page data wrapper now has supports for loader to raise a custom exception to declare that they can't return a value after all (this is especially useful for the wildcard loader). The returned value, if any, is also now cached properly. diff -r f33712c4cfab -r 4c9eab0e283b piecrust/data/base.py --- a/piecrust/data/base.py Sun May 10 00:34:21 2015 -0700 +++ b/piecrust/data/base.py Sun May 10 00:37:28 2015 -0700 @@ -8,6 +8,13 @@ logger = logging.getLogger(__name__) +class LazyPageConfigLoaderHasNoValue(Exception): + """ An exception that can be returned when a loader for `LazyPageConfig` + can't return any value. + """ + pass + + 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 @@ -28,26 +35,34 @@ def get(self, name): try: return self._getValue(name) - except KeyError: + except LazyPageConfigLoaderHasNoValue: return None def __getattr__(self, name): try: return self._getValue(name) - except KeyError: + except LazyPageConfigLoaderHasNoValue: raise AttributeError def __getitem__(self, name): - return self._getValue(name) + try: + return self._getValue(name) + except LazyPageConfigLoaderHasNoValue: + raise KeyError def _getValue(self, name): self._load() + if name in self._values: + return self._values[name] + if self._loaders: loader = self._loaders.get(name) if loader is not None: try: self._values[name] = loader(self, name) + except LazyPageConfigLoaderHasNoValue: + raise except Exception as ex: raise Exception( "Error while loading attribute '%s' for: %s" % @@ -61,16 +76,20 @@ if len(self._loaders) == 0: self._loaders = None - elif name not in self._values: + else: loader = self._loaders.get('*') if loader is not None: try: self._values[name] = loader(self, name) + except LazyPageConfigLoaderHasNoValue: + raise except Exception as ex: raise Exception( - "Error while loading attirbute '%s' for: %s" % + "Error while loading attribute '%s' for: %s" % (name, self._page.rel_path)) from ex + # We always keep the wildcard loader in the loaders list. + assert name in self._values return self._values[name] def _setValue(self, name, value): diff -r f33712c4cfab -r 4c9eab0e283b piecrust/data/linker.py --- a/piecrust/data/linker.py Sun May 10 00:34:21 2015 -0700 +++ b/piecrust/data/linker.py Sun May 10 00:37:28 2015 -0700 @@ -1,8 +1,7 @@ import logging import collections -from piecrust.data.base import PaginationData +from piecrust.data.base import PaginationData, LazyPageConfigLoaderHasNoValue from piecrust.data.iterators import PageIterator -from piecrust.sources.base import build_pages from piecrust.sources.interfaces import IPaginationSource, IListableSource @@ -53,8 +52,10 @@ self.mapLoader('*', self._linkerChildLoader) - def _linkerChildLoader(self, name): - return getattr(self.children, name) + def _linkerChildLoader(self, data, name): + if self.children and hasattr(self.children, name): + return getattr(self.children, name) + raise LazyPageConfigLoaderHasNoValue class LinkedPageDataBuilderIterator(object):