From d23abb794d2594adde158f2242c0a5cb0fea5e31 Mon Sep 17 00:00:00 2001 From: Nikos Skalkotos <skalkoto@grnet.gr> Date: Thu, 18 Dec 2014 18:20:39 +0200 Subject: [PATCH] Add a result() method in the output interface By default the output goes to sys.stdout. This is used in snf-mkimage to output the plankton answer when registering an image to a synnefo deployment. This resolves #21 --- image_creator/dialog_main.py | 3 ++- image_creator/dialog_menu.py | 2 +- image_creator/dialog_util.py | 4 ++-- image_creator/main.py | 11 +++++------ image_creator/output/__init__.py | 4 ++++ image_creator/output/cli.py | 24 +++++++++++++++--------- image_creator/output/composite.py | 16 ++++++++++------ image_creator/output/dialog.py | 18 ++++++++++++++++++ 8 files changed, 57 insertions(+), 25 deletions(-) diff --git a/image_creator/dialog_main.py b/image_creator/dialog_main.py index dadf4c0..614ad0b 100644 --- a/image_creator/dialog_main.py +++ b/image_creator/dialog_main.py @@ -201,7 +201,8 @@ def dialog_main(media, logfile, tmpdir, snapshot): tmplog = None if logfile else tempfile.NamedTemporaryFile(prefix='fatal-', delete=False) try: - log = SimpleOutput(False, logfile if logfile else tmplog) + stream = logfile if logfile else tmplog + log = SimpleOutput(colored=False, stderr=stream, stdout=stream) while 1: try: out = CompositeOutput([log]) diff --git a/image_creator/dialog_menu.py b/image_creator/dialog_menu.py index 0fd555f..0f1f274 100644 --- a/image_creator/dialog_menu.py +++ b/image_creator/dialog_menu.py @@ -932,7 +932,7 @@ def show_log(session): """Show the current execution log""" d = session['dialog'] - log = session['image'].out[0].stream + log = session['image'].out[0].stderr log.file.flush() diff --git a/image_creator/dialog_util.py b/image_creator/dialog_util.py index 6e1e959..675322b 100644 --- a/image_creator/dialog_util.py +++ b/image_creator/dialog_util.py @@ -214,13 +214,13 @@ def extract_image(session): image.dump(path) # Extract metadata file - out.info("Extracting metadata file ...") + out.info("Extracting metadata file ...", False) with open('%s.meta' % path, 'w') as f: f.write(extract_metadata_string(session)) out.success('done') # Extract md5sum file - out.info("Extracting md5sum file ...") + out.info("Extracting md5sum file ...", False) md5str = "%s %s\n" % (session['checksum'], name) with open('%s.md5sum' % path, 'w') as f: f.write(md5str) diff --git a/image_creator/main.py b/image_creator/main.py index ec18bd4..e1c2fec 100644 --- a/image_creator/main.py +++ b/image_creator/main.py @@ -214,10 +214,10 @@ def image_creator(): "be set") if options.silent: - out = SilentOutput() + out = SilentOutput(colored=sys.stderr.isatty()) else: - out = OutputWthProgress(True) if sys.stderr.isatty() else \ - SimpleOutput(False) + out = OutputWthProgress() if sys.stderr.isatty() else \ + SimpleOutput(colored=False) title = 'snf-image-creator %s' % version out.info(title) @@ -430,7 +430,7 @@ def image_creator(): out.info("Sharing metadata file ...", False) kamaki.share("%s.meta" % options.upload) out.success('done') - + out.result(json.dumps(result, indent=4)) out.info() except ClientError as e: raise FatalError("Service client: %d %s" % (e.status, e.message)) @@ -449,8 +449,7 @@ def main(): try: sys.exit(image_creator()) except FatalError as e: - colored = sys.stderr.isatty() - SimpleOutput(colored).error(e) + SimpleOutput(colored=sys.stderr.isatty()).error(e) sys.exit(1) if __name__ == '__main__': diff --git a/image_creator/output/__init__.py b/image_creator/output/__init__.py index 8ca8963..4ace944 100644 --- a/image_creator/output/__init__.py +++ b/image_creator/output/__init__.py @@ -40,6 +40,10 @@ class Output(object): """Print normal program output""" pass + def result(self, msg='', new_line=True): + """Print a result""" + pass + def cleanup(self): """Cleanup this output class""" pass diff --git a/image_creator/output/cli.py b/image_creator/output/cli.py index f22f1a1..a1bd78f 100644 --- a/image_creator/output/cli.py +++ b/image_creator/output/cli.py @@ -33,14 +33,20 @@ def write(msg, new_line, decorate, stream): class SilentOutput(Output): """Silent Output class. Only Errors are printed""" - def __init__(self, colored=True, stream=None): - self.colored = colored - self.stream = sys.stderr if stream is None else stream + def __init__(self, **kwargs): + """Initialize a SilentOutput instance""" + self.colored = kwargs['colored'] if 'colored' in kwargs else True + self.stdout = kwargs['stdout'] if 'stdout' in kwargs else sys.stdout + self.stderr = kwargs['stderr'] if 'stderr' in kwargs else sys.stderr + + def result(self, msg, new_line=True): + """Print a result""" + write(msg, new_line, lambda x: x, self.stdout) def error(self, msg, new_line=True): """Print an error""" color = red if self.colored else lambda x: x - write("Error: %s" % msg, new_line, color, self.stream) + write("Error: %s" % msg, new_line, color, self.stderr) class SimpleOutput(SilentOutput): @@ -51,21 +57,21 @@ class SimpleOutput(SilentOutput): def warn(self, msg, new_line=True): """Print a warning""" color = yellow if self.colored else lambda x: x - write("Warning: %s" % msg, new_line, color, self.stream) + write("Warning: %s" % msg, new_line, color, self.stderr) def success(self, msg, new_line=True): """Print msg after an action is completed""" color = green if self.colored else lambda x: x - write(msg, new_line, color, self.stream) + write(msg, new_line, color, self.stderr) def info(self, msg='', new_line=True): """Print msg as normal program output""" - write(msg, new_line, lambda x: x, self.stream) + write(msg, new_line, lambda x: x, self.stderr) def clear(self): """Clear the screen""" - if self.stream.isatty(): - self.stream.write('\033[H\033[2J') + if self.stderr.isatty(): + self.stderr.write('\033[H\033[2J') class OutputWthProgress(SimpleOutput): diff --git a/image_creator/output/composite.py b/image_creator/output/composite.py index fbcb76d..fe1185c 100644 --- a/image_creator/output/composite.py +++ b/image_creator/output/composite.py @@ -56,6 +56,11 @@ class CompositeOutput(Output, list): for out in self: out.info(msg, new_line) + def result(self, msg='', new_line=True): + """Call the output method of each of the output instances""" + for out in self: + out.result(msg, new_line) + def cleanup(self): """Call the cleanup method of each of the output instances""" for out in self: @@ -66,28 +71,27 @@ class CompositeOutput(Output, list): for out in self: out.clear() - class _Progress(object): + class _Progress(list): """Class used to composite different Progress objects""" def __init__(self, size, title, bar_type='default'): """Create a progress on each of the added output instances""" - self._progresses = [] for out in self.parent: - self._progresses.append(out.Progress(size, title, bar_type)) + self.append(out.Progress(size, title, bar_type)) def goto(self, dest): """Call the goto method of each of the progress instances""" - for progress in self._progresses: + for progress in self: progress.goto(dest) def next(self): """Call the next method of each of the progress instances""" - for progress in self._progresses: + for progress in self: progress.next() def success(self, result): """Call the success method of each of the progress instances""" - for progress in self._progresses: + for progress in self: progress.success(result) # vim: set sta sts=4 shiftwidth=4 sw=4 et ai : diff --git a/image_creator/output/dialog.py b/image_creator/output/dialog.py index 8fb93cc..c7fbc64 100644 --- a/image_creator/output/dialog.py +++ b/image_creator/output/dialog.py @@ -48,6 +48,10 @@ class GaugeOutput(Output): self.d.gauge_update(self.percent, self.msg, update_text=True) time.sleep(0.4) + def result(self, msg='', new_line=True): + """Print a result""" + self.info(msg, new_line) + def success(self, result, new_line=True): """Print result after a successful action""" self.percent = 100 @@ -61,6 +65,12 @@ class GaugeOutput(Output): update_text=True) time.sleep(0.4) + def error(self, msg, new_line=True): + """Print an error""" + self.d.gauge_update(self.percent, "%s Error: %s" % (self.msg, msg), + update_text=True) + time.sleep(0.4) + def cleanup(self): """Cleanup the GaugeOutput instance""" self.d.gauge_stop() @@ -120,6 +130,10 @@ class InfoBoxOutput(Output): self.d.infobox(display, title=self.title, height=self.height, width=self.width) + def result(self, msg='', new_line=True): + """Print a result""" + self.info(msg, new_line) + def success(self, result, new_line=True): """Print result after an action is completed successfully""" self.info(result, new_line) @@ -128,6 +142,10 @@ class InfoBoxOutput(Output): """Print a warning message""" self.info("Warning: %s" % msg, new_line) + def error(self, msg, new_line=True): + """Print an error message""" + self.info("Error: %s" % msg, new_line) + def finalize(self): """Finalize the output. After this is called, the InfoboxOutput instance should be destroyed -- GitLab