changeset 709:4285b2c9b872

themes: Add support for loading from a library of themes.
author Ludovic Chabant <ludovic@chabant.com>
date Thu, 19 May 2016 22:11:27 -0700
parents d3a5a086e5cd
children e85f29b28b84
files piecrust/app.py piecrust/themes/__init__.py piecrust/themes/base.py
diffstat 2 files changed, 68 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/piecrust/app.py	Thu May 19 22:05:10 2016 -0700
+++ b/piecrust/app.py	Thu May 19 22:11:27 2016 -0700
@@ -103,11 +103,23 @@
 
     @cached_property
     def theme_dir(self):
+        # No theme if the curent site is already a theme.
         if self.theme_site:
             return None
+
+        # See if there's a theme we absolutely want.
         td = self._get_dir(THEME_DIR)
         if td is not None:
             return td
+
+        # Try to load a theme specified in the configuration.
+        from piecrust.themes.base import ThemeLoader
+        loader = ThemeLoader(self.root_dir)
+        theme_dir = loader.getThemeDir()
+        if theme_dir is not None:
+            return theme_dir
+
+        # Nothing... use the default theme.
         return os.path.join(RESOURCES_DIR, 'theme')
 
     @cached_property
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/piecrust/themes/base.py	Thu May 19 22:11:27 2016 -0700
@@ -0,0 +1,56 @@
+import sys
+import os.path
+import yaml
+from piecrust import CONFIG_PATH, THEME_DIR, THEMES_DIR
+
+
+class Theme(object):
+    def getPath(self):
+        mod_name = type(self).__module__
+        mod_file = sys.modules[mod_name].__file__
+        return os.path.dirname(mod_file)
+
+
+class ThemeNotFoundError(Exception):
+    pass
+
+
+class ThemeLoader(object):
+    def __init__(self, root_dir):
+        self.root_dir = root_dir
+
+    def getThemeDir(self):
+        # Pre-load the config quickly to see if we're loading a specific
+        # theme from somehwere.
+        # TODO: make configs and themes load together to speed this up.
+        config_path = os.path.join(self.root_dir, CONFIG_PATH)
+        with open(config_path, 'r', encoding='utf8') as fp:
+            config = yaml.load(fp.read())
+        site_config = config.get('site', {})
+        theme = site_config.get('theme', None)
+        if theme is None:
+            return None
+
+        # Get the list of directories in which themes are installed.
+        dirs = []
+        themes_dirs = site_config.get('themes_dirs', [])
+        if isinstance(themes_dirs, str):
+            dirs.append(os.path.join(self.root_dir, themes_dirs))
+        else:
+            dirs += [os.path.join(self.root_dir, p) for p in themes_dirs]
+
+        # Add the default `themes` directory.
+        default_themes_dir = os.path.join(self.root_dir, THEMES_DIR)
+        if os.path.isdir(default_themes_dir):
+            dirs.append(default_themes_dir)
+
+        # Try to find the theme the user wants.
+        for d in dirs:
+            theme_dir = os.path.join(d, theme)
+            if os.path.isdir(theme_dir):
+                return theme_dir
+
+        raise ThemeNotFoundError(
+                "Can't find theme '%s'. Looked in: %s",
+                (theme, ', '.join(dirs)))
+