aboutsummaryrefslogtreecommitdiff
path: root/catapult/telemetry/telemetry/internal/util/command_line.py
diff options
context:
space:
mode:
Diffstat (limited to 'catapult/telemetry/telemetry/internal/util/command_line.py')
-rw-r--r--catapult/telemetry/telemetry/internal/util/command_line.py121
1 files changed, 121 insertions, 0 deletions
diff --git a/catapult/telemetry/telemetry/internal/util/command_line.py b/catapult/telemetry/telemetry/internal/util/command_line.py
new file mode 100644
index 00000000..2a0d6038
--- /dev/null
+++ b/catapult/telemetry/telemetry/internal/util/command_line.py
@@ -0,0 +1,121 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# 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.internal.util import camel_case
+
+
+class ArgumentHandlerMixIn(object):
+ """A structured way to handle command-line arguments.
+
+ 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."""
+
+ @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 = ''
+
+ @classmethod
+ def CreateParser(cls):
+ return optparse.OptionParser('%%prog %s %s' % (cls.Name(), cls.usage),
+ description=cls.Description())
+
+ @classmethod
+ def AddCommandLineArgs(cls, parser, environment):
+ # pylint: disable=arguments-differ
+ pass
+
+ @classmethod
+ def ProcessCommandLineArgs(cls, parser, args, environment):
+ # pylint: disable=arguments-differ
+ pass
+
+ 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, None)
+ options, args = parser.parse_args(args=args)
+ options.positional_args = args
+ cls.ProcessCommandLineArgs(parser, options, None)
+ 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)