Mercurial > piecrust2
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 |