diff options
Diffstat (limited to 'catapult/telemetry/telemetry/internal/util/command_line.py')
-rw-r--r-- | catapult/telemetry/telemetry/internal/util/command_line.py | 121 |
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) |