diff piecrust/app.py @ 758:6abb436fea5b

publish: Make publisher more powerful and better exposed on the command line. * Make the `chef publish` command have one sub-command per publish target. * Add custom argument parsing per publisher to have strong extra arguments available per publish target. * Make publish targets a first class citizen of the `PieCrust` app class.
author Ludovic Chabant <ludovic@chabant.com>
date Sat, 25 Jun 2016 17:03:29 -0700
parents ab5c6a8ae90a
children fd694f1297c7
line wrap: on
line diff
--- a/piecrust/app.py	Sat Jun 25 17:01:08 2016 -0700
+++ b/piecrust/app.py	Sat Jun 25 17:03:29 2016 -0700
@@ -2,6 +2,7 @@
 import os.path
 import hashlib
 import logging
+import urllib.parse
 from werkzeug.utils import cached_property
 from piecrust import (
         RESOURCES_DIR,
@@ -10,9 +11,9 @@
         CONFIG_PATH, THEME_CONFIG_PATH)
 from piecrust.appconfig import PieCrustConfiguration
 from piecrust.cache import ExtensibleCache, NullExtensibleCache
-from piecrust.plugins.base import PluginLoader
+from piecrust.configuration import ConfigurationError, merge_dicts
 from piecrust.environment import StandardEnvironment
-from piecrust.configuration import ConfigurationError, merge_dicts
+from piecrust.plugins.base import PluginLoader
 from piecrust.routing import Route
 from piecrust.sources.base import REALM_THEME
 
@@ -165,6 +166,36 @@
             gens.append(gen)
         return gens
 
+    @cached_property
+    def publishers(self):
+        defs_by_name = {}
+        defs_by_scheme = {}
+        for cls in self.plugin_loader.getPublishers():
+            defs_by_name[cls.PUBLISHER_NAME] = cls
+            if cls.PUBLISHER_SCHEME:
+                defs_by_scheme[cls.PUBLISHER_SCHEME] = cls
+
+        tgts = []
+        publish_config = self.config.get('publish')
+        if publish_config is None:
+            return tgts
+        for n, t in publish_config.items():
+            pub_type = None
+            is_scheme = False
+            if isinstance(t, dict):
+                pub_type = t.get('type')
+            elif isinstance(t, str):
+                comps = urllib.parse.urlparse(t)
+                pub_type = comps.scheme
+                is_scheme = True
+            cls = (defs_by_scheme.get(pub_type) if is_scheme
+                    else defs_by_name.get(pub_type))
+            if cls is None:
+                raise ConfigurationError("No such publisher: %s" % pub_type)
+            tgt = cls(self, n, t)
+            tgts.append(tgt)
+        return tgts
+
     def getSource(self, source_name):
         for source in self.sources:
             if source.name == source_name:
@@ -195,6 +226,12 @@
                 return route
         return None
 
+    def getPublisher(self, target_name):
+        for pub in self.publishers:
+            if pub.target == target_name:
+                return pub
+        return None
+
     def _get_dir(self, default_rel_dir):
         abs_dir = os.path.join(self.root_dir, default_rel_dir)
         if os.path.isdir(abs_dir):