comparison 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
comparison
equal deleted inserted replaced
241:85a6c7ba5e3b 242:f130365568ff
1 import os
2 import os.path
3 import logging
4 from piecrust.data.base import PaginationData
5 from piecrust.data.filters import PaginationFilter
6 from piecrust.sources.base import PageFactory
7 from piecrust.sources.interfaces import IPaginationSource, IListableSource
8
9
10 logger = logging.getLogger(__name__)
11
12
13 class SourceFactoryIterator(object):
14 def __init__(self, source):
15 self.source = source
16
17 # This is to permit recursive traversal of the
18 # iterator chain. It acts as the end.
19 self.it = None
20
21 def __iter__(self):
22 return self.source.getPages()
23
24
25 class DateSortIterator(object):
26 def __init__(self, it, reverse=True):
27 self.it = it
28 self.reverse = reverse
29
30 def __iter__(self):
31 return iter(sorted(self.it,
32 key=lambda x: x.datetime, reverse=self.reverse))
33
34
35 class PaginationDataBuilderIterator(object):
36 def __init__(self, it):
37 self.it = it
38
39 def __iter__(self):
40 for page in self.it:
41 if page is None:
42 yield None
43 else:
44 yield PaginationData(page)
45
46
47 def page_setting_accessor(item, name):
48 return item.config.get(name)
49
50
51 class SimplePaginationSourceMixin(IPaginationSource):
52 """ Implements the `IPaginationSource` interface in a standard way that
53 should fit most page sources.
54 """
55 def getItemsPerPage(self):
56 return self.config['items_per_page']
57
58 def getSourceIterator(self):
59 return SourceFactoryIterator(self)
60
61 def getSorterIterator(self, it):
62 return DateSortIterator(it)
63
64 def getTailIterator(self, it):
65 return PaginationDataBuilderIterator(it)
66
67 def getPaginationFilter(self, page):
68 conf = (page.config.get('items_filters') or
69 page.app.config.get('site/items_filters'))
70 if conf == 'none' or conf == 'nil' or conf == '':
71 conf = None
72 if conf is not None:
73 f = PaginationFilter()
74 f.addClausesFromConfig(conf)
75 return f
76 return None
77
78 def getSettingAccessor(self):
79 return page_setting_accessor
80
81
82 class SimpleListableSourceMixin(IListableSource):
83 """ Implements the `IListableSource` interface for sources that map to
84 simple file-system structures.
85 """
86 def listPath(self, rel_path):
87 rel_path = rel_path.lstrip('\\/')
88 path = self._getFullPath(rel_path)
89 names = self._sortFilenames(os.listdir(path))
90
91 items = []
92 for name in names:
93 if os.path.isdir(os.path.join(path, name)):
94 if self._filterPageDirname(name):
95 rel_subdir = os.path.join(rel_path, name)
96 items.append((True, name, rel_subdir))
97 else:
98 if self._filterPageFilename(name):
99 slug = self._makeSlug(os.path.join(rel_path, name))
100 metadata = {'slug': slug}
101
102 fac_path = name
103 if rel_path != '.':
104 fac_path = os.path.join(rel_path, name)
105 fac_path = fac_path.replace('\\', '/')
106
107 self._populateMetadata(fac_path, metadata)
108 fac = PageFactory(self, fac_path, metadata)
109
110 name, _ = os.path.splitext(name)
111 items.append((False, name, fac))
112 return items
113
114 def getDirpath(self, rel_path):
115 return os.path.dirname(rel_path)
116
117 def getBasename(self, rel_path):
118 filename = os.path.basename(rel_path)
119 name, _ = os.path.splitext(filename)
120 return name
121
122 def _getFullPath(self, rel_path):
123 return os.path.join(self.fs_endpoint_path, rel_path)
124
125 def _sortFilenames(self, names):
126 return sorted(names)
127
128 def _filterPageDirname(self, name):
129 return True
130
131 def _filterPageFilename(self, name):
132 return True
133
134 def _makeSlug(self, rel_path):
135 return rel_path.replace('\\', '/')
136
137 def _populateMetadata(self, rel_path, metadata, mode=None):
138 pass
139