Source code

Revision control

Copy as Markdown

Other Tools

#!/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
"""
import os
import sys
from optparse import OptionParser
from .logger import Logger
from .manifestparser import ManifestParser, convert
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
self.logger = Logger()
def parser(self):
return OptionParser(
usage=self.usage, description=self.__doc__, add_help_option=False
)
class CopyCLI(CLICommand):
"""
To copy tests and manifests from a source
"""
usage = "%prog [options] copy manifest directory -tag1 -tag2 --key1=value1 --key2=value2 ..."
def __call__(self, global_options, args):
# parse the arguments
try:
kwargs, tags, args = parse_args(args)
except ParserError as e:
self._parser.error(str(e))
# make sure we have some manifests, otherwise it will
# be quite boring
if not len(args) == 2:
self.logger.error("missing arguments: manifest directory")
HelpCLI(self._parser)(global_options, ["copy"])
return 1
# 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)
return 0
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, global_options, args):
parser = self.parser()
options, args = parser.parse_args(args)
# need some directories
if not len(args):
self.logger.error("missing arguments: directory ...")
parser.print_usage()
return 1
# 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)
return 0
class HelpCLI(CLICommand):
"""
get help on a command
"""
usage = "%prog [options] help [command]"
def __call__(self, global_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 as e:
self._parser.error(str(e))
# make sure we have some manifests, otherwise it will
# be quite boring
if not len(args) == 2:
self.logger.error("missing arguments: manifest directory")
HelpCLI(self._parser)(options, ["update"])
return 1
# 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)
return 0
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 as e:
self._parser.error(str(e))
# make sure we have some manifests, otherwise it will
# be quite boring
if not args:
self.logger.error("missing arguments: manifest ...")
HelpCLI(self._parser)(options, ["write"])
return 1
# 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)
return 0
# command -> class mapping
commands = {
"copy": CopyCLI,
"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()
global_options, args = parser.parse_args(args)
if not args:
HelpCLI(parser)(global_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)
)
return 1
handler = commands[command](parser)
return handler(global_options, args[1:])
if __name__ == "__main__":
sys.exit(main())