Mercurial > piecrust2
diff piecrust/sources/mixins.py @ 242:f130365568ff
internal: Code reorganization to put less stuff in `sources.base`.
Interfaces that sources can implement are in `sources.interfaces`. The default
page source is in `sources.default`. The `SimplePageSource` is gone since most
subclasses only wanted to do *some* stuff the same, but *lots* of stuff
slightly different. I may have to revisit the code to extract exactly the code
that's in common.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Wed, 18 Feb 2015 18:35:03 -0800 |
parents | |
children | 07b4b8484c0a |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piecrust/sources/mixins.py Wed Feb 18 18:35:03 2015 -0800 @@ -0,0 +1,139 @@ +import os +import os.path +import logging +from piecrust.data.base import PaginationData +from piecrust.data.filters import PaginationFilter +from piecrust.sources.base import PageFactory +from piecrust.sources.interfaces import IPaginationSource, IListableSource + + +logger = logging.getLogger(__name__) + + +class SourceFactoryIterator(object): + def __init__(self, source): + self.source = source + + # This is to permit recursive traversal of the + # iterator chain. It acts as the end. + self.it = None + + def __iter__(self): + return self.source.getPages() + + +class DateSortIterator(object): + def __init__(self, it, reverse=True): + self.it = it + self.reverse = reverse + + def __iter__(self): + return iter(sorted(self.it, + key=lambda x: x.datetime, reverse=self.reverse)) + + +class PaginationDataBuilderIterator(object): + def __init__(self, it): + self.it = it + + def __iter__(self): + for page in self.it: + if page is None: + yield None + else: + yield PaginationData(page) + + +def page_setting_accessor(item, name): + return item.config.get(name) + + +class SimplePaginationSourceMixin(IPaginationSource): + """ Implements the `IPaginationSource` interface in a standard way that + should fit most page sources. + """ + def getItemsPerPage(self): + return self.config['items_per_page'] + + def getSourceIterator(self): + return SourceFactoryIterator(self) + + def getSorterIterator(self, it): + return DateSortIterator(it) + + def getTailIterator(self, it): + return PaginationDataBuilderIterator(it) + + def getPaginationFilter(self, page): + conf = (page.config.get('items_filters') or + page.app.config.get('site/items_filters')) + if conf == 'none' or conf == 'nil' or conf == '': + conf = None + if conf is not None: + f = PaginationFilter() + f.addClausesFromConfig(conf) + return f + return None + + def getSettingAccessor(self): + return page_setting_accessor + + +class SimpleListableSourceMixin(IListableSource): + """ Implements the `IListableSource` interface for sources that map to + simple file-system structures. + """ + def listPath(self, rel_path): + rel_path = rel_path.lstrip('\\/') + path = self._getFullPath(rel_path) + names = self._sortFilenames(os.listdir(path)) + + items = [] + for name in names: + if os.path.isdir(os.path.join(path, name)): + if self._filterPageDirname(name): + rel_subdir = os.path.join(rel_path, name) + items.append((True, name, rel_subdir)) + else: + if self._filterPageFilename(name): + slug = self._makeSlug(os.path.join(rel_path, name)) + metadata = {'slug': slug} + + fac_path = name + if rel_path != '.': + fac_path = os.path.join(rel_path, name) + fac_path = fac_path.replace('\\', '/') + + self._populateMetadata(fac_path, metadata) + fac = PageFactory(self, fac_path, metadata) + + name, _ = os.path.splitext(name) + items.append((False, name, fac)) + return items + + def getDirpath(self, rel_path): + return os.path.dirname(rel_path) + + def getBasename(self, rel_path): + filename = os.path.basename(rel_path) + name, _ = os.path.splitext(filename) + return name + + def _getFullPath(self, rel_path): + return os.path.join(self.fs_endpoint_path, rel_path) + + def _sortFilenames(self, names): + return sorted(names) + + def _filterPageDirname(self, name): + return True + + def _filterPageFilename(self, name): + return True + + def _makeSlug(self, rel_path): + return rel_path.replace('\\', '/') + + def _populateMetadata(self, rel_path, metadata, mode=None): + pass +