Mercurial > piecrust2
comparison piecrust/sources/default.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 | dd25bd3ce1f9 |
comparison
equal
deleted
inserted
replaced
241:85a6c7ba5e3b | 242:f130365568ff |
---|---|
1 import os | |
2 import os.path | |
3 import logging | |
4 from piecrust.sources.base import ( | |
5 PageFactory, PageSource, InvalidFileSystemEndpointError, | |
6 MODE_CREATING) | |
7 from piecrust.sources.interfaces import IListableSource, IPreparingSource | |
8 from piecrust.sources.mixins import SimplePaginationSourceMixin | |
9 | |
10 | |
11 logger = logging.getLogger(__name__) | |
12 | |
13 | |
14 def filter_page_dirname(d): | |
15 return not (d.startswith('.') or d.endswith('-assets')) | |
16 | |
17 | |
18 def filter_page_filename(f): | |
19 return (f[0] != '.' and # .DS_store and other crap | |
20 f[-1] != '~' and # Vim temp files and what-not | |
21 f not in ['Thumbs.db']) # Windows bullshit | |
22 | |
23 | |
24 class DefaultPageSource(PageSource, IListableSource, IPreparingSource, | |
25 SimplePaginationSourceMixin): | |
26 SOURCE_NAME = 'default' | |
27 | |
28 def __init__(self, app, name, config): | |
29 super(DefaultPageSource, self).__init__(app, name, config) | |
30 self.fs_endpoint = config.get('fs_endpoint', name) | |
31 self.fs_endpoint_path = os.path.join(self.root_dir, self.fs_endpoint) | |
32 self.supported_extensions = list( | |
33 app.config.get('site/auto_formats').keys()) | |
34 self.default_auto_format = app.config.get('site/default_auto_format') | |
35 | |
36 def buildPageFactories(self): | |
37 logger.debug("Scanning for pages in: %s" % self.fs_endpoint_path) | |
38 if not os.path.isdir(self.fs_endpoint_path): | |
39 if self.ignore_missing_dir: | |
40 return | |
41 raise InvalidFileSystemEndpointError(self.name, | |
42 self.fs_endpoint_path) | |
43 | |
44 for dirpath, dirnames, filenames in os.walk(self.fs_endpoint_path): | |
45 rel_dirpath = os.path.relpath(dirpath, self.fs_endpoint_path) | |
46 dirnames[:] = list(filter(filter_page_dirname, dirnames)) | |
47 for f in filter(filter_page_filename, filenames): | |
48 fac_path = f | |
49 if rel_dirpath != '.': | |
50 fac_path = os.path.join(rel_dirpath, f) | |
51 slug = self._makeSlug(fac_path) | |
52 metadata = {'slug': slug} | |
53 fac_path = fac_path.replace('\\', '/') | |
54 self._populateMetadata(fac_path, metadata) | |
55 yield PageFactory(self, fac_path, metadata) | |
56 | |
57 def resolveRef(self, ref_path): | |
58 return os.path.normpath( | |
59 os.path.join(self.fs_endpoint_path, ref_path.lstrip("\\/"))) | |
60 | |
61 def findPagePath(self, metadata, mode): | |
62 uri_path = metadata.get('slug', '') | |
63 if not uri_path: | |
64 uri_path = '_index' | |
65 path = os.path.join(self.fs_endpoint_path, uri_path) | |
66 _, ext = os.path.splitext(path) | |
67 | |
68 if mode == MODE_CREATING: | |
69 if ext == '': | |
70 path = '%s.%s' % (path, self.default_auto_format) | |
71 rel_path = os.path.relpath(path, self.fs_endpoint_path) | |
72 rel_path = rel_path.replace('\\', '/') | |
73 self._populateMetadata(rel_path, metadata, mode) | |
74 return rel_path, metadata | |
75 | |
76 if ext == '': | |
77 paths_to_check = [ | |
78 '%s.%s' % (path, e) | |
79 for e in self.supported_extensions] | |
80 else: | |
81 paths_to_check = [path] | |
82 for path in paths_to_check: | |
83 if os.path.isfile(path): | |
84 rel_path = os.path.relpath(path, self.fs_endpoint_path) | |
85 rel_path = rel_path.replace('\\', '/') | |
86 self._populateMetadata(rel_path, metadata, mode) | |
87 return rel_path, metadata | |
88 | |
89 return None, None | |
90 | |
91 def listPath(self, rel_path): | |
92 rel_path = rel_path.lstrip('\\/') | |
93 path = os.path.join(self.fs_endpoint_path, rel_path) | |
94 names = sorted(os.listdir(path)) | |
95 items = [] | |
96 for name in names: | |
97 if os.path.isdir(os.path.join(path, name)): | |
98 if filter_page_dirname(name): | |
99 rel_subdir = os.path.join(rel_path, name) | |
100 items.append((True, name, rel_subdir)) | |
101 else: | |
102 if filter_page_filename(name): | |
103 slug = self._makeSlug(os.path.join(rel_path, name)) | |
104 metadata = {'slug': slug} | |
105 | |
106 fac_path = name | |
107 if rel_path != '.': | |
108 fac_path = os.path.join(rel_path, name) | |
109 fac_path = fac_path.replace('\\', '/') | |
110 | |
111 self._populateMetadata(fac_path, metadata) | |
112 fac = PageFactory(self, fac_path, metadata) | |
113 | |
114 name, _ = os.path.splitext(name) | |
115 items.append((False, name, fac)) | |
116 return items | |
117 | |
118 def getDirpath(self, rel_path): | |
119 return os.path.dirname(rel_path) | |
120 | |
121 def getBasename(self, rel_path): | |
122 filename = os.path.basename(rel_path) | |
123 name, _ = os.path.splitext(filename) | |
124 return name | |
125 | |
126 def setupPrepareParser(self, parser, app): | |
127 parser.add_argument('uri', help='The URI for the new page.') | |
128 | |
129 def buildMetadata(self, args): | |
130 return {'slug': args.uri} | |
131 | |
132 def _makeSlug(self, rel_path): | |
133 slug, ext = os.path.splitext(rel_path) | |
134 slug = slug.replace('\\', '/') | |
135 if ext.lstrip('.') not in self.supported_extensions: | |
136 slug += ext | |
137 if slug.startswith('./'): | |
138 slug = slug[2:] | |
139 if slug == '_index': | |
140 slug = '' | |
141 return slug | |
142 | |
143 def _populateMetadata(self, rel_path, metadata, mode=None): | |
144 pass | |
145 |