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