| #!/usr/bin/env python |
| # This Source Code Form is subject to the terms of the Mozilla Public |
| # License, v. 2.0. If a copy of the MPL was not distributed with this file, |
| # You can obtain one at http://mozilla.org/MPL/2.0/. |
| |
| """ |
| Mozilla universal manifest parser |
| """ |
| |
| from optparse import OptionParser |
| import os |
| import sys |
| |
| from .manifestparser import ( |
| convert, |
| ManifestParser, |
| ) |
| |
| |
| class ParserError(Exception): |
| """error for exceptions while parsing the command line""" |
| |
| def parse_args(_args): |
| """ |
| parse and return: |
| --keys=value (or --key value) |
| -tags |
| args |
| """ |
| |
| # return values |
| _dict = {} |
| tags = [] |
| args = [] |
| |
| # parse the arguments |
| key = None |
| for arg in _args: |
| if arg.startswith('---'): |
| raise ParserError("arguments should start with '-' or '--' only") |
| elif arg.startswith('--'): |
| if key: |
| raise ParserError("Key %s still open" % key) |
| key = arg[2:] |
| if '=' in key: |
| key, value = key.split('=', 1) |
| _dict[key] = value |
| key = None |
| continue |
| elif arg.startswith('-'): |
| if key: |
| raise ParserError("Key %s still open" % key) |
| tags.append(arg[1:]) |
| continue |
| else: |
| if key: |
| _dict[key] = arg |
| continue |
| args.append(arg) |
| |
| # return values |
| return (_dict, tags, args) |
| |
| class CLICommand(object): |
| usage = '%prog [options] command' |
| def __init__(self, parser): |
| self._parser = parser # master parser |
| def parser(self): |
| return OptionParser(usage=self.usage, description=self.__doc__, |
| add_help_option=False) |
| |
| class Copy(CLICommand): |
| usage = '%prog [options] copy manifest directory -tag1 -tag2 --key1=value1 --key2=value2 ...' |
| def __call__(self, options, args): |
| # parse the arguments |
| try: |
| kwargs, tags, args = parse_args(args) |
| except ParserError, e: |
| self._parser.error(e.message) |
| |
| # make sure we have some manifests, otherwise it will |
| # be quite boring |
| if not len(args) == 2: |
| HelpCLI(self._parser)(options, ['copy']) |
| return |
| |
| # read the manifests |
| # TODO: should probably ensure these exist here |
| manifests = ManifestParser() |
| manifests.read(args[0]) |
| |
| # print the resultant query |
| manifests.copy(args[1], None, *tags, **kwargs) |
| |
| |
| class CreateCLI(CLICommand): |
| """ |
| create a manifest from a list of directories |
| """ |
| usage = '%prog [options] create directory <directory> <...>' |
| |
| def parser(self): |
| parser = CLICommand.parser(self) |
| parser.add_option('-p', '--pattern', dest='pattern', |
| help="glob pattern for files") |
| parser.add_option('-i', '--ignore', dest='ignore', |
| default=[], action='append', |
| help='directories to ignore') |
| parser.add_option('-w', '--in-place', dest='in_place', |
| help='Write .ini files in place; filename to write to') |
| return parser |
| |
| def __call__(self, _options, args): |
| parser = self.parser() |
| options, args = parser.parse_args(args) |
| |
| # need some directories |
| if not len(args): |
| parser.print_usage() |
| return |
| |
| # add the directories to the manifest |
| for arg in args: |
| assert os.path.exists(arg) |
| assert os.path.isdir(arg) |
| manifest = convert(args, pattern=options.pattern, ignore=options.ignore, |
| write=options.in_place) |
| if manifest: |
| print manifest |
| |
| |
| class WriteCLI(CLICommand): |
| """ |
| write a manifest based on a query |
| """ |
| usage = '%prog [options] write manifest <manifest> -tag1 -tag2 --key1=value1 --key2=value2 ...' |
| def __call__(self, options, args): |
| |
| # parse the arguments |
| try: |
| kwargs, tags, args = parse_args(args) |
| except ParserError, e: |
| self._parser.error(e.message) |
| |
| # make sure we have some manifests, otherwise it will |
| # be quite boring |
| if not args: |
| HelpCLI(self._parser)(options, ['write']) |
| return |
| |
| # read the manifests |
| # TODO: should probably ensure these exist here |
| manifests = ManifestParser() |
| manifests.read(*args) |
| |
| # print the resultant query |
| manifests.write(global_tags=tags, global_kwargs=kwargs) |
| |
| |
| |
| class HelpCLI(CLICommand): |
| """ |
| get help on a command |
| """ |
| usage = '%prog [options] help [command]' |
| |
| def __call__(self, options, args): |
| if len(args) == 1 and args[0] in commands: |
| commands[args[0]](self._parser).parser().print_help() |
| else: |
| self._parser.print_help() |
| print '\nCommands:' |
| for command in sorted(commands): |
| print ' %s : %s' % (command, commands[command].__doc__.strip()) |
| |
| class UpdateCLI(CLICommand): |
| """ |
| update the tests as listed in a manifest from a directory |
| """ |
| usage = '%prog [options] update manifest directory -tag1 -tag2 --key1=value1 --key2=value2 ...' |
| |
| def __call__(self, options, args): |
| # parse the arguments |
| try: |
| kwargs, tags, args = parse_args(args) |
| except ParserError, e: |
| self._parser.error(e.message) |
| |
| # make sure we have some manifests, otherwise it will |
| # be quite boring |
| if not len(args) == 2: |
| HelpCLI(self._parser)(options, ['update']) |
| return |
| |
| # read the manifests |
| # TODO: should probably ensure these exist here |
| manifests = ManifestParser() |
| manifests.read(args[0]) |
| |
| # print the resultant query |
| manifests.update(args[1], None, *tags, **kwargs) |
| |
| |
| # command -> class mapping |
| commands = { 'create': CreateCLI, |
| 'help': HelpCLI, |
| 'update': UpdateCLI, |
| 'write': WriteCLI } |
| |
| def main(args=sys.argv[1:]): |
| """console_script entry point""" |
| |
| # set up an option parser |
| usage = '%prog [options] [command] ...' |
| description = "%s. Use `help` to display commands" % __doc__.strip() |
| parser = OptionParser(usage=usage, description=description) |
| parser.add_option('-s', '--strict', dest='strict', |
| action='store_true', default=False, |
| help='adhere strictly to errors') |
| parser.disable_interspersed_args() |
| |
| options, args = parser.parse_args(args) |
| |
| if not args: |
| HelpCLI(parser)(options, args) |
| parser.exit() |
| |
| # get the command |
| command = args[0] |
| if command not in commands: |
| parser.error("Command must be one of %s (you gave '%s')" % (', '.join(sorted(commands.keys())), command)) |
| |
| handler = commands[command](parser) |
| handler(options, args[1:]) |
| |
| if __name__ == '__main__': |
| main() |