Mercurial > piecrust2
diff piecrust/publishing/publisher.py @ 621:8f9c0bdb3724
publish: Polish/refactor the publishing workflows.
* Add a `--preview` option.
* The `--list` option gives a nicer output, and prints warnings/errors for
incorrect configuration.
* Moved most of the `shell` code into a base class that's reusable.
* Simplified the code to log publishing to a file.
* Nicer output overall, with times.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Mon, 08 Feb 2016 20:44:26 -0800 |
parents | e2e955a3bb25 |
children | 6abb436fea5b |
line wrap: on
line diff
--- a/piecrust/publishing/publisher.py Sat Feb 06 21:49:50 2016 -0800 +++ b/piecrust/publishing/publisher.py Mon Feb 08 20:44:26 2016 -0800 @@ -1,4 +1,8 @@ +import os.path +import time import logging +import urllib.parse +from piecrust.chefutil import format_timed from piecrust.publishing.base import PublishingContext @@ -17,17 +21,72 @@ def __init__(self, app): self.app = app - def run(self, target, log_file=None): + def run(self, target, preview=False, log_file=None): + start_time = time.perf_counter() + + # Get the configuration for this target. target_cfg = self.app.config.get('publish/%s' % target) if not target_cfg: raise InvalidPublishTargetError( "No such publish target: %s" % target) - target_type = target_cfg.get('type') - if not target_type: - raise InvalidPublishTargetError( - "Publish target '%s' doesn't specify a type." % target) + target_type = None + bake_first = True + parsed_url = None + if isinstance(target_cfg, dict): + target_type = target_cfg.get('type') + if not target_type: + raise InvalidPublishTargetError( + "Publish target '%s' doesn't specify a type." % target) + bake_first = target_cfg.get('bake', True) + elif isinstance(target_cfg, str): + comps = urllib.parse.urlparse(target_cfg) + if not comps.scheme: + raise InvalidPublishTargetError( + "Publish target '%s' has an invalid target URL." % + target) + parsed_url = comps + target_type = find_publisher_name(self.app, comps.scheme) + if target_type is None: + raise InvalidPublishTargetError( + "No such publish target scheme: %s" % comps.scheme) + # Setup logging stuff. + hdlr = None + root_logger = logging.getLogger() + if log_file and not preview: + logger.debug("Adding file handler for: %s" % log_file) + hdlr = logging.FileHandler(log_file, mode='w', encoding='utf8') + root_logger.addHandler(hdlr) + if not preview: + logger.info("Deploying to %s" % target) + else: + logger.info("Previewing deployment to %s" % target) + + # Bake first is necessary. + bake_out_dir = None + if bake_first: + bake_out_dir = os.path.join(self.app.cache_dir, 'pub', target) + if not preview: + bake_start_time = time.perf_counter() + logger.debug("Baking first to: %s" % bake_out_dir) + + from piecrust.baking.baker import Baker + baker = Baker(self.app, bake_out_dir) + rec1 = baker.bake() + + from piecrust.processing.pipeline import ProcessorPipeline + proc = ProcessorPipeline(self.app, bake_out_dir) + rec2 = proc.run() + + if not rec1.success or not rec2.success: + raise Exception( + "Error during baking, aborting publishing.") + logger.info(format_timed(bake_start_time, "Baked website.")) + else: + logger.info("Would bake to: %s" % bake_out_dir) + + # Create the appropriate publisher. pub = None for pub_cls in self.app.plugin_loader.getPublishers(): if pub_cls.PUBLISHER_NAME == target_type: @@ -37,39 +96,47 @@ raise InvalidPublishTargetError( "Publish target '%s' has invalid type: %s" % (target, target_type)) + pub.parsed_url = parsed_url + + # Publish! + logger.debug( + "Running publish target '%s' with publisher: %s" % + (target, pub.PUBLISHER_NAME)) + pub_start_time = time.perf_counter() ctx = PublishingContext() - - hdlr = None - if log_file: - if not pub.is_using_custom_logging: - logger.debug("Adding file handler for: %s" % log_file) - hdlr = logging.FileHandler(log_file, mode='w', encoding='utf8') - logger.addHandler(hdlr) - else: - logger.debug("Creating custom log file: %s" % log_file) - ctx.custom_logging_file = open( - log_file, mode='w', encoding='utf8') - - intro_msg = ("Running publish target '%s' with publisher: %s" % - (target, pub.PUBLISHER_NAME)) - logger.debug(intro_msg) - if ctx.custom_logging_file: - ctx.custom_logging_file.write(intro_msg + "\n") - + ctx.bake_out_dir = bake_out_dir + ctx.preview = preview try: success = pub.run(ctx) except Exception as ex: raise PublishingError( "Error publishing to target: %s" % target) from ex finally: - if ctx.custom_logging_file: - ctx.custom_logging_file.close() if hdlr: - logger.removeHandler(hdlr) + root_logger.removeHandler(hdlr) hdlr.close() if not success: raise PublishingError( "Unknown error publishing to target: %s" % target) + logger.info(format_timed( + pub_start_time, "Ran publisher %s" % pub.PUBLISHER_NAME)) + logger.info(format_timed(start_time, 'Deployed to %s' % target)) + + +def find_publisher_class(app, scheme): + for pub_cls in app.plugin_loader.getPublishers(): + pub_sch = getattr(pub_cls, 'PUBLISHER_SCHEME', None) + if ('bake+%s' % pub_sch) == scheme: + return pub_cls + return None + + +def find_publisher_name(app, scheme): + pub_cls = find_publisher_class(app, scheme) + if pub_cls: + return pub_cls.PUBLISHER_NAME + return None +