cros_bundle_firmware: Use enter/exit instead of del

This change makes use of Python's 'with' construct which is a nicer way to
deal with the finalization problem.

BUG=chromium-os:17298
TEST=run cros_bundle_firmware; check that output is still consistent and
output directory is removed.

Change-Id: I81045a5e52af68f512dbf4a48a6151832e7c47d5
Reviewed-on: http://gerrit.chromium.org/gerrit/5592
Reviewed-by: Che-Liang Chiou <clchiou@chromium.org>
Tested-by: Simon Glass <sjg@chromium.org>
diff --git a/host/cros_bundle_firmware b/host/cros_bundle_firmware
index cce398d..e9b58a0 100755
--- a/host/cros_bundle_firmware
+++ b/host/cros_bundle_firmware
@@ -61,6 +61,49 @@
   tools.CheckTool('dtput', 'dtc')
   tools.CheckTool('dtget', 'dtc')
 
+def _DoBundle(options, output, tools):
+  """The main part of the cros_bundle_firmware code.
+
+  This takes the supplied options and performs the firmware bundling.
+
+  Args:
+    options: Parser options.
+    output: cros_output object to use.
+    tools: Tools object to use.
+  """
+  _CheckTools(tools, options)
+  tools.PrepareOutputDir(options.outdir, options.preserve)
+
+  bundle = Bundle(tools, output)
+  bundle.SetDirs(keydir=options.key)
+  bundle.SetFiles(board=options.board, uboot=options.uboot, bct=options.bct,
+                  bmpblk=options.bmpblk)
+  bundle.SetOptions(small=options.small)
+
+  try:
+    # Set up the fdt and options that we want.
+    bundle.SelectFdt(options.fdt)
+    bundle.SetBootcmd(options.bootcmd, options.bootsecure)
+    bundle.AddConfigList(options.add_config_str)
+    bundle.AddConfigList(options.add_config_int, use_int=True)
+
+    out_fname = bundle.Start(options.hardware_id, options.output)
+
+    # Write it to the board if required.
+    if options.write:
+      flasher = options.uboot_flasher
+      if not flasher:
+        flasher = bundle.uboot_fname
+      write_firmware.DoWriteFirmware(output, tools, bundle.fdt, flasher,
+          bundle.bct_fname, out_fname)
+
+  except (CmdError, ValueError) as err:
+    # For verbosity 4 we want to display all possible information
+    if options.verbosity >= 4:
+      raise
+    else:
+      output.Error(str(err))
+
 def main():
   """Main function for cros_bundle_firmware."""
   parser = optparse.OptionParser()
@@ -113,45 +156,9 @@
       default=False, help='Write firmware to SPI flash with USB A-A cable')
   (options, args) = parser.parse_args(sys.argv)
 
-  output = cros_output.Output(options.verbosity)
-  tools = Tools(output)
-  _CheckTools(tools, options)
-  tools.PrepareOutputDir(options.outdir, options.preserve)
-
-  bundle = Bundle(tools, output)
-  bundle.SetDirs(keydir=options.key)
-  bundle.SetFiles(board=options.board, uboot=options.uboot, bct=options.bct,
-                  bmpblk=options.bmpblk)
-  bundle.SetOptions(small=options.small)
-
-  try:
-    # Set up the fdt and options that we want.
-    bundle.SelectFdt(options.fdt)
-    bundle.SetBootcmd(options.bootcmd, options.bootsecure)
-    bundle.AddConfigList(options.add_config_str)
-    bundle.AddConfigList(options.add_config_int, use_int=True)
-
-    out_fname = bundle.Start(options.hardware_id, options.output)
-
-    # Write it to the board if required.
-    if options.write:
-      flasher = options.uboot_flasher
-      if not flasher:
-        flasher = bundle.uboot_fname
-      write_firmware.DoWriteFirmware(output, tools, bundle.fdt, flasher,
-          bundle.bct_fname, out_fname)
-
-  except (CmdError, ValueError) as err:
-    # For verbosity 4 we want to display all possible information
-    if options.verbosity >= 4:
-      raise
-    else:
-      output.Error(str(err))
-      del tools
-      del output
-      sys.exit(1)
-  del tools
-  del output
+  with cros_output.Output(options.verbosity) as output:
+    with Tools(output) as tools:
+      _DoBundle(options, output, tools)
 
 
 def _Test():
diff --git a/host/lib/cros_output.py b/host/lib/cros_output.py
index d8891bf..b638db7 100644
--- a/host/lib/cros_output.py
+++ b/host/lib/cros_output.py
@@ -45,9 +45,13 @@
     # TODO(sjg): Move this into Chromite libraries when we have them
     self.stdout_is_tty = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()
 
-  def __del__(self):
+  def __enter__(self):
+    return self
+
+  def __exit__(self, type, value, traceback):
     """Clean up and remove any progress message."""
     self.ClearProgress()
+    return False
 
   def UserIsPresent(self):
     """This returns True if it is likely that a user is present.
diff --git a/host/lib/tools.py b/host/lib/tools.py
index 586f5a6..8d8bed2 100755
--- a/host/lib/tools.py
+++ b/host/lib/tools.py
@@ -78,8 +78,12 @@
     self.outdir = None          # We have no output directory yet
     self._delete_tempdir = None # And no temporary directory to delete
 
-  def __del__(self):
-      self.FinalizeOutputDir()
+  def __enter__(self):
+    return self
+
+  def __exit__(self, type, value, traceback):
+    self.FinalizeOutputDir()
+    return False
 
   def _SetRoot(self, root_dir):
     """Sets the root directory for the build envionrment.