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 |
