Mercurial > piecrust2
view piecrust/publishing/shell.py @ 1188:a7c43131d871
bake: Fix file write flushing problem with Python 3.8+
Writing the cache files fails in Python 3.8 because it looks like flushing
behaviour has changed. We need to explicitly flush. And even then, in very
rare occurrences, it looks like it can still run into racing conditions,
so we do a very hacky and ugly "retry" loop when fetching cached data :(
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Tue, 15 Jun 2021 22:36:23 -0700 |
parents | 8ca228956cc6 |
children |
line wrap: on
line source
import os.path import shlex import logging import threading import subprocess from piecrust.publishing.base import Publisher logger = logging.getLogger(__name__) class ShellCommandPublisherBase(Publisher): def __init__(self, app, target, config): super(ShellCommandPublisherBase, self).__init__(app, target, config) self.expand_user_args = True def run(self, ctx): args = self._getCommandArgs(ctx) if self.expand_user_args: args = [os.path.expanduser(i) for i in args] if ctx.preview: preview_args = ' '.join([shlex.quote(i) for i in args]) logger.info( "Would run shell command: %s" % preview_args) return True logger.debug( "Running shell command: %s" % args) proc = subprocess.Popen( args, cwd=self.app.root_dir, bufsize=0, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) logger.debug("Running publishing monitor for PID %d" % proc.pid) thread = _PublishThread(proc) thread.start() proc.wait() thread.join() if proc.returncode != 0: logger.error( "Publish process returned code %d" % proc.returncode) else: logger.debug("Publish process returned successfully.") return proc.returncode == 0 def _getCommandArgs(self, ctx): raise NotImplementedError() class _PublishThread(threading.Thread): def __init__(self, proc): super(_PublishThread, self).__init__( name='publish_monitor', daemon=True) self.proc = proc self.root_logger = logging.getLogger() def run(self): for line in iter(self.proc.stdout.readline, b''): line_str = line.decode('utf8') logger.info(line_str.rstrip('\r\n')) for h in self.root_logger.handlers: h.flush() self.proc.communicate() logger.debug("Publish monitor exiting.") class ShellCommandPublisher(ShellCommandPublisherBase): PUBLISHER_NAME = 'shell' def _getCommandArgs(self, ctx): target_cmd = self.config.get('command') if not target_cmd: raise Exception("No command specified for publish target: %s" % self.target) args = shlex.split(target_cmd) return args