Mercurial > piecrust2
comparison piecrust/publishing/base.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 |
comparison
equal
deleted
inserted
replaced
620:c2708f20a87b | 621:8f9c0bdb3724 |
---|---|
1 import os.path | |
2 import shlex | |
3 import logging | |
4 import threading | |
5 import subprocess | |
6 | |
7 | |
8 logger = logging.getLogger(__name__) | |
1 | 9 |
2 | 10 |
3 class PublishingContext(object): | 11 class PublishingContext(object): |
4 def __init__(self): | 12 def __init__(self): |
5 self.custom_logging_file = None | 13 self.bake_out_dir = None |
14 self.preview = False | |
6 | 15 |
7 | 16 |
8 class Publisher(object): | 17 class Publisher(object): |
9 def __init__(self, app, target): | 18 def __init__(self, app, target): |
10 self.app = app | 19 self.app = app |
11 self.target = target | 20 self.target = target |
12 self.is_using_custom_logging = False | 21 self.parsed_url = None |
13 self.log_file_path = None | 22 self.log_file_path = None |
23 | |
24 @property | |
25 def has_url_config(self): | |
26 return self.parsed_url is not None | |
27 | |
28 @property | |
29 def url_config(self): | |
30 if self.parsed_url is not None: | |
31 return self.getConfig() | |
32 raise Exception("This publisher has a full configuration.") | |
14 | 33 |
15 def getConfig(self): | 34 def getConfig(self): |
16 return self.app.config.get('publish/%s' % self.target) | 35 return self.app.config.get('publish/%s' % self.target) |
17 | 36 |
18 def getConfigValue(self, name): | 37 def getConfigValue(self, name): |
38 if self.has_url_config: | |
39 raise Exception("This publisher only has a URL configuration.") | |
19 return self.app.config.get('publish/%s/%s' % (self.target, name)) | 40 return self.app.config.get('publish/%s/%s' % (self.target, name)) |
20 | 41 |
21 def run(self, ctx): | 42 def run(self, ctx): |
22 raise NotImplementedError() | 43 raise NotImplementedError() |
23 | 44 |
45 | |
46 class ShellCommandPublisherBase(Publisher): | |
47 def __init__(self, app, target): | |
48 super(ShellCommandPublisherBase, self).__init__(app, target) | |
49 self.expand_user_args = True | |
50 | |
51 def run(self, ctx): | |
52 args = self._getCommandArgs(ctx) | |
53 if self.expand_user_args: | |
54 args = [os.path.expanduser(i) for i in args] | |
55 | |
56 if ctx.preview: | |
57 preview_args = ' '.join([shlex.quote(i) for i in args]) | |
58 logger.info( | |
59 "Would run shell command: %s" % preview_args) | |
60 return True | |
61 | |
62 logger.debug( | |
63 "Running shell command: %s" % args) | |
64 | |
65 proc = subprocess.Popen( | |
66 args, cwd=self.app.root_dir, bufsize=0, | |
67 stdout=subprocess.PIPE) | |
68 | |
69 logger.debug("Running publishing monitor for PID %d" % proc.pid) | |
70 thread = _PublishThread(proc) | |
71 thread.start() | |
72 proc.wait() | |
73 thread.join() | |
74 | |
75 if proc.returncode != 0: | |
76 logger.error( | |
77 "Publish process returned code %d" % proc.returncode) | |
78 else: | |
79 logger.debug("Publish process returned successfully.") | |
80 | |
81 return proc.returncode == 0 | |
82 | |
83 def _getCommandArgs(self, ctx): | |
84 raise NotImplementedError() | |
85 | |
86 | |
87 class _PublishThread(threading.Thread): | |
88 def __init__(self, proc): | |
89 super(_PublishThread, self).__init__( | |
90 name='publish_monitor', daemon=True) | |
91 self.proc = proc | |
92 self.root_logger = logging.getLogger() | |
93 | |
94 def run(self): | |
95 for line in iter(self.proc.stdout.readline, b''): | |
96 line_str = line.decode('utf8') | |
97 logger.info(line_str.rstrip('\r\n')) | |
98 for h in self.root_logger.handlers: | |
99 h.flush() | |
100 | |
101 self.proc.communicate() | |
102 logger.debug("Publish monitor exiting.") | |
103 |