Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / tools / telemetry / telemetry / core / command_line.py
index cee8833..450cd0d 100644 (file)
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import argparse
 import optparse
 
+from telemetry.core import camel_case
 
-class Command(object):
-  @property
-  def name(self):
-    return self.__class__.__name__.lower()
 
-  @property
-  def description(self):
-    return self.__doc__
+class ArgumentHandlerMixIn(object):
+  """A structured way to handle command-line arguments.
 
-  def AddCommandLineOptions(self, parser):
-    pass
+  In AddCommandLineArgs, add command-line arguments.
+  In ProcessCommandLineArgs, validate them and store them in a private class
+  variable. This way, each class encapsulates its own arguments, without needing
+  to pass an arguments object around everywhere.
+  """
 
+  @classmethod
+  def AddCommandLineArgs(cls, parser):
+    """Override to accept custom command-line arguments."""
 
-class ArgparseCommand(Command):
-  def ProcessCommandLine(self, parser, args):
-    pass
+  @classmethod
+  def ProcessCommandLineArgs(cls, parser, args):
+    """Override to process command-line arguments.
+
+    We pass in parser so we can call parser.error()."""
+
+
+class Command(ArgumentHandlerMixIn):
+  """An abstraction for things that run from the command-line."""
+
+  @classmethod
+  def Name(cls):
+    return camel_case.ToUnderscore(cls.__name__)
+
+  @classmethod
+  def Description(cls):
+    if cls.__doc__:
+      return cls.__doc__.splitlines()[0]
+    else:
+      return ''
 
   def Run(self, args):
     raise NotImplementedError()
 
+  @classmethod
+  def main(cls, args=None):
+    """Main method to run this command as a standalone script."""
+    parser = argparse.ArgumentParser()
+    cls.AddCommandLineArgs(parser)
+    args = parser.parse_args(args=args)
+    cls.ProcessCommandLineArgs(parser, args)
+    return min(cls().Run(args), 255)
+
 
 # TODO: Convert everything to argparse.
 class OptparseCommand(Command):
   usage = ''
 
-  def CreateParser(self):
-    return optparse.OptionParser('%%prog %s %s' % (self.name, self.usage))
-
-  def ProcessCommandLine(self, parser, options, args):
-    pass
+  @classmethod
+  def CreateParser(cls):
+    return optparse.OptionParser('%%prog %s %s' % (cls.Name(), cls.usage),
+                                 description=cls.Description())
 
-  def Run(self, options, args):
+  def Run(self, args):
     raise NotImplementedError()
+
+  @classmethod
+  def main(cls, args=None):
+    """Main method to run this command as a standalone script."""
+    parser = cls.CreateParser()
+    cls.AddCommandLineArgs(parser)
+    options, args = parser.parse_args(args=args)
+    options.positional_args = args
+    cls.ProcessCommandLineArgs(parser, options)
+    return min(cls().Run(options), 255)
+
+
+class SubcommandCommand(Command):
+  """Combines Commands into one big command with sub-commands.
+
+  E.g. "svn checkout", "svn update", and "svn commit" are separate sub-commands.
+
+  Example usage:
+    class MyCommand(command_line.SubcommandCommand):
+      commands = (Help, List, Run)
+
+    if __name__ == '__main__':
+      sys.exit(MyCommand.main())
+  """
+
+  commands = ()
+
+  @classmethod
+  def AddCommandLineArgs(cls, parser):
+    subparsers = parser.add_subparsers()
+
+    for command in cls.commands:
+      subparser = subparsers.add_parser(
+          command.Name(), help=command.Description())
+      subparser.set_defaults(command=command)
+      command.AddCommandLineArgs(subparser)
+
+  @classmethod
+  def ProcessCommandLineArgs(cls, parser, args):
+    args.command.ProcessCommandLineArgs(parser, args)
+
+  def Run(self, args):
+    return args.command().Run(args)