diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/piecrust/sources/default.py	Wed Feb 18 18:35:03 2015 -0800
@@ -0,0 +1,145 @@
+import os
+import os.path
+import logging
+from piecrust.sources.base import (
+        PageFactory, PageSource, InvalidFileSystemEndpointError,
+        MODE_CREATING)
+from piecrust.sources.interfaces import IListableSource, IPreparingSource
+from piecrust.sources.mixins import SimplePaginationSourceMixin
+
+
+logger = logging.getLogger(__name__)
+
+
+def filter_page_dirname(d):
+    return not (d.startswith('.') or d.endswith('-assets'))
+
+
+def filter_page_filename(f):
+    return (f[0] != '.' and   # .DS_store and other crap
+            f[-1] != '~' and  # Vim temp files and what-not
+            f not in ['Thumbs.db'])  # Windows bullshit
+
+
+class DefaultPageSource(PageSource, IListableSource, IPreparingSource,
+                        SimplePaginationSourceMixin):
+    SOURCE_NAME = 'default'
+
+    def __init__(self, app, name, config):
+        super(DefaultPageSource, self).__init__(app, name, config)
+        self.fs_endpoint = config.get('fs_endpoint', name)
+        self.fs_endpoint_path = os.path.join(self.root_dir, self.fs_endpoint)
+        self.supported_extensions = list(
+                app.config.get('site/auto_formats').keys())
+        self.default_auto_format = app.config.get('site/default_auto_format')
+
+    def buildPageFactories(self):
+        logger.debug("Scanning for pages in: %s" % self.fs_endpoint_path)
+        if not os.path.isdir(self.fs_endpoint_path):
+            if self.ignore_missing_dir:
+                return
+            raise InvalidFileSystemEndpointError(self.name,
+                                                 self.fs_endpoint_path)
+
+        for dirpath, dirnames, filenames in os.walk(self.fs_endpoint_path):
+            rel_dirpath = os.path.relpath(dirpath, self.fs_endpoint_path)
+            dirnames[:] = list(filter(filter_page_dirname, dirnames))
+            for f in filter(filter_page_filename, filenames):
+                fac_path = f
+                if rel_dirpath != '.':
+                    fac_path = os.path.join(rel_dirpath, f)
+                slug = self._makeSlug(fac_path)
+                metadata = {'slug': slug}
+                fac_path = fac_path.replace('\\', '/')
+                self._populateMetadata(fac_path, metadata)
+                yield PageFactory(self, fac_path, metadata)
+
+    def resolveRef(self, ref_path):
+        return os.path.normpath(
+                os.path.join(self.fs_endpoint_path, ref_path.lstrip("\\/")))
+
+    def findPagePath(self, metadata, mode):
+        uri_path = metadata.get('slug', '')
+        if not uri_path:
+            uri_path = '_index'
+        path = os.path.join(self.fs_endpoint_path, uri_path)
+        _, ext = os.path.splitext(path)
+
+        if mode == MODE_CREATING:
+            if ext == '':
+                path = '%s.%s' % (path, self.default_auto_format)
+            rel_path = os.path.relpath(path, self.fs_endpoint_path)
+            rel_path = rel_path.replace('\\', '/')
+            self._populateMetadata(rel_path, metadata, mode)
+            return rel_path, metadata
+
+        if ext == '':
+            paths_to_check = [
+                    '%s.%s' % (path, e)
+                    for e in self.supported_extensions]
+        else:
+            paths_to_check = [path]
+        for path in paths_to_check:
+            if os.path.isfile(path):
+                rel_path = os.path.relpath(path, self.fs_endpoint_path)
+                rel_path = rel_path.replace('\\', '/')
+                self._populateMetadata(rel_path, metadata, mode)
+                return rel_path, metadata
+
+        return None, None
+
+    def listPath(self, rel_path):
+        rel_path = rel_path.lstrip('\\/')
+        path = os.path.join(self.fs_endpoint_path, rel_path)
+        names = sorted(os.listdir(path))
+        items = []
+        for name in names:
+            if os.path.isdir(os.path.join(path, name)):
+                if filter_page_dirname(name):
+                    rel_subdir = os.path.join(rel_path, name)
+                    items.append((True, name, rel_subdir))
+            else:
+                if filter_page_filename(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 setupPrepareParser(self, parser, app):
+        parser.add_argument('uri', help='The URI for the new page.')
+
+    def buildMetadata(self, args):
+        return {'slug': args.uri}
+
+    def _makeSlug(self, rel_path):
+        slug, ext = os.path.splitext(rel_path)
+        slug = slug.replace('\\', '/')
+        if ext.lstrip('.') not in self.supported_extensions:
+            slug += ext
+        if slug.startswith('./'):
+            slug = slug[2:]
+        if slug == '_index':
+            slug = ''
+        return slug
+
+    def _populateMetadata(self, rel_path, metadata, mode=None):
+        pass
+