2018-07-04 15:39:44 +01:00
|
|
|
# Copyright 2013-2018 ARM Limited
|
2017-02-21 13:37:11 +00:00
|
|
|
#
|
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
# you may not use this file except in compliance with the License.
|
|
|
|
# You may obtain a copy of the License at
|
|
|
|
#
|
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
#
|
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
# See the License for the specific language governing permissions and
|
|
|
|
# limitations under the License.
|
|
|
|
#
|
2017-03-06 11:10:25 +00:00
|
|
|
|
|
|
|
|
2017-02-21 13:37:11 +00:00
|
|
|
import sys
|
|
|
|
import argparse
|
2019-06-19 17:06:49 +01:00
|
|
|
import locale
|
2017-02-21 13:37:11 +00:00
|
|
|
import logging
|
2017-03-06 11:10:25 +00:00
|
|
|
import os
|
|
|
|
import warnings
|
2017-02-21 13:37:11 +00:00
|
|
|
|
2018-06-14 17:31:07 +01:00
|
|
|
import devlib
|
2019-02-20 11:53:09 +00:00
|
|
|
try:
|
|
|
|
from devlib.utils.version import version as installed_devlib_version
|
|
|
|
except ImportError:
|
|
|
|
installed_devlib_version = None
|
2018-06-14 17:31:07 +01:00
|
|
|
|
2017-03-06 11:10:25 +00:00
|
|
|
from wa.framework import pluginloader
|
|
|
|
from wa.framework.command import init_argument_parser
|
2017-02-21 13:37:11 +00:00
|
|
|
from wa.framework.configuration import settings
|
2017-03-06 11:10:25 +00:00
|
|
|
from wa.framework.configuration.execution import ConfigManager
|
2018-03-12 10:22:23 +00:00
|
|
|
from wa.framework.host import init_user_directory, init_config
|
2019-02-20 11:53:09 +00:00
|
|
|
from wa.framework.exception import ConfigError, HostError
|
|
|
|
from wa.framework.version import (get_wa_version_with_commit, format_version,
|
|
|
|
required_devlib_version)
|
2017-03-06 11:10:25 +00:00
|
|
|
from wa.utils import log
|
2017-02-21 13:37:11 +00:00
|
|
|
from wa.utils.doc import format_body
|
|
|
|
|
|
|
|
warnings.filterwarnings(action='ignore', category=UserWarning, module='zope')
|
|
|
|
|
2017-12-06 14:49:30 +00:00
|
|
|
# Disable this to avoid false positive from dynamically-created attributes.
|
|
|
|
# pylint: disable=no-member
|
2017-02-21 13:37:11 +00:00
|
|
|
|
2017-03-06 11:10:25 +00:00
|
|
|
logger = logging.getLogger('command_line')
|
2017-02-21 13:37:11 +00:00
|
|
|
|
|
|
|
|
|
|
|
def load_commands(subparsers):
|
|
|
|
commands = {}
|
|
|
|
for command in pluginloader.list_commands():
|
2017-12-04 17:24:12 +00:00
|
|
|
commands[command.name] = pluginloader.get_command(command.name,
|
2017-03-06 11:10:25 +00:00
|
|
|
subparsers=subparsers)
|
2017-02-21 13:37:11 +00:00
|
|
|
return commands
|
|
|
|
|
|
|
|
|
framework/entrypoint: fix joined options parsing.
In order to properly enable verbose logging for plugin enumeration,
verbosity option must be extracted before commands are processed, and
therefore before all valid arguments are known.
ArgumentParser.parse_known_args() is used for this, which will collect
all unexpected arguments into an "extras" list, rather than raising an
error. This, however, has an outstanding bug, where if say option '-v'
is known and '-f is unknown, args '-v -f' will be parsed correctly (with
'-f' being collected into extras), but '-vf' will not, resulting in an
error.
To get around this, pre-process sys.argv to detect joined options and
manually split them into separate args.
2017-11-07 17:17:05 +00:00
|
|
|
# ArgumentParser.parse_known_args() does not correctly deal with concatenated
|
|
|
|
# single character options. See https://bugs.python.org/issue16142 for the
|
|
|
|
# description of the issue (with a fix attached since 2013!). To get around
|
|
|
|
# this problem, this will pre-process sys.argv to detect such joined options
|
|
|
|
# and split them.
|
|
|
|
def split_joined_options(argv):
|
|
|
|
output = []
|
|
|
|
for part in argv:
|
|
|
|
if len(part) > 1 and part[0] == '-' and part[1] != '-':
|
|
|
|
for c in part[1:]:
|
|
|
|
output.append('-' + c)
|
|
|
|
else:
|
|
|
|
output.append(part)
|
|
|
|
return output
|
|
|
|
|
|
|
|
|
2019-02-20 11:53:09 +00:00
|
|
|
# Instead of presenting an obscure error due to a version mismatch explicitly warn the user.
|
|
|
|
def check_devlib_version():
|
2019-12-18 10:02:52 +00:00
|
|
|
if not installed_devlib_version or installed_devlib_version[:-1] <= required_devlib_version[:-1]:
|
|
|
|
# Check the 'dev' field separately to account for comparing with release versions.
|
|
|
|
if installed_devlib_version.dev and installed_devlib_version.dev < required_devlib_version.dev:
|
|
|
|
msg = 'WA requires Devlib version >={}. Please update the currently installed version {}'
|
|
|
|
raise HostError(msg.format(format_version(required_devlib_version), devlib.__version__))
|
2019-02-20 11:53:09 +00:00
|
|
|
|
|
|
|
|
2019-06-19 17:06:49 +01:00
|
|
|
# If the default encoding is not UTF-8 warn the user as this may cause compatibility issues
|
|
|
|
# when parsing files.
|
|
|
|
def check_system_encoding():
|
|
|
|
system_encoding = locale.getpreferredencoding()
|
|
|
|
msg = 'System Encoding: {}'.format(system_encoding)
|
|
|
|
if 'UTF-8' not in system_encoding:
|
|
|
|
logger.warning(msg)
|
|
|
|
logger.warning('To prevent encoding issues please use a locale setting which supports UTF-8')
|
|
|
|
else:
|
|
|
|
logger.debug(msg)
|
|
|
|
|
|
|
|
|
2017-02-21 13:37:11 +00:00
|
|
|
def main():
|
2017-03-06 11:10:25 +00:00
|
|
|
if not os.path.exists(settings.user_directory):
|
|
|
|
init_user_directory()
|
2018-03-12 10:22:23 +00:00
|
|
|
if not os.path.exists(os.path.join(settings.user_directory, 'config.yaml')):
|
|
|
|
init_config()
|
2017-03-06 11:10:25 +00:00
|
|
|
|
2017-02-21 13:37:11 +00:00
|
|
|
try:
|
2017-03-06 11:10:25 +00:00
|
|
|
|
|
|
|
description = ("Execute automated workloads on a remote device and process "
|
|
|
|
"the resulting output.\n\nUse \"wa <subcommand> -h\" to see "
|
|
|
|
"help for individual subcommands.")
|
|
|
|
parser = argparse.ArgumentParser(description=format_body(description, 80),
|
|
|
|
prog='wa',
|
|
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
|
|
)
|
|
|
|
init_argument_parser(parser)
|
|
|
|
|
|
|
|
# load_commands will trigger plugin enumeration, and we want logging
|
|
|
|
# to be enabled for that, which requires the verbosity setting; however
|
2018-04-30 11:30:40 +01:00
|
|
|
# full argument parsing cannot be completed until the commands are loaded; so
|
|
|
|
# parse just the base args for now so we can get verbosity.
|
framework/entrypoint: fix joined options parsing.
In order to properly enable verbose logging for plugin enumeration,
verbosity option must be extracted before commands are processed, and
therefore before all valid arguments are known.
ArgumentParser.parse_known_args() is used for this, which will collect
all unexpected arguments into an "extras" list, rather than raising an
error. This, however, has an outstanding bug, where if say option '-v'
is known and '-f is unknown, args '-v -f' will be parsed correctly (with
'-f' being collected into extras), but '-vf' will not, resulting in an
error.
To get around this, pre-process sys.argv to detect joined options and
manually split them into separate args.
2017-11-07 17:17:05 +00:00
|
|
|
argv = split_joined_options(sys.argv[1:])
|
2017-12-01 15:04:44 +00:00
|
|
|
|
|
|
|
# 'Parse_known_args' automatically displays the default help and exits
|
2018-06-07 10:47:59 +01:00
|
|
|
# if '-h' or '--help' is detected, we want our custom help messages so
|
|
|
|
# ensure these are never passed as parameters.
|
2017-12-01 15:04:44 +00:00
|
|
|
filtered_argv = list(argv)
|
|
|
|
if '-h' in filtered_argv:
|
|
|
|
filtered_argv.remove('-h')
|
2018-06-07 10:47:59 +01:00
|
|
|
elif '--help' in filtered_argv:
|
|
|
|
filtered_argv.remove('--help')
|
2017-12-01 15:04:44 +00:00
|
|
|
|
|
|
|
args, _ = parser.parse_known_args(filtered_argv)
|
2017-03-06 11:10:25 +00:00
|
|
|
settings.set("verbosity", args.verbose)
|
|
|
|
log.init(settings.verbosity)
|
2018-05-09 15:35:56 +01:00
|
|
|
logger.debug('Version: {}'.format(get_wa_version_with_commit()))
|
2018-06-14 17:31:07 +01:00
|
|
|
logger.debug('devlib version: {}'.format(devlib.__full_version__))
|
2018-04-30 11:58:37 +01:00
|
|
|
logger.debug('Command Line: {}'.format(' '.join(sys.argv)))
|
2019-02-20 11:53:09 +00:00
|
|
|
check_devlib_version()
|
2019-06-19 17:06:49 +01:00
|
|
|
check_system_encoding()
|
2017-03-06 11:10:25 +00:00
|
|
|
|
|
|
|
# each command will add its own subparser
|
2018-06-13 08:54:50 +01:00
|
|
|
subparsers = parser.add_subparsers(dest='command')
|
|
|
|
subparsers.required = True
|
|
|
|
commands = load_commands(subparsers)
|
framework/entrypoint: fix joined options parsing.
In order to properly enable verbose logging for plugin enumeration,
verbosity option must be extracted before commands are processed, and
therefore before all valid arguments are known.
ArgumentParser.parse_known_args() is used for this, which will collect
all unexpected arguments into an "extras" list, rather than raising an
error. This, however, has an outstanding bug, where if say option '-v'
is known and '-f is unknown, args '-v -f' will be parsed correctly (with
'-f' being collected into extras), but '-vf' will not, resulting in an
error.
To get around this, pre-process sys.argv to detect joined options and
manually split them into separate args.
2017-11-07 17:17:05 +00:00
|
|
|
args = parser.parse_args(argv)
|
2017-03-06 11:10:25 +00:00
|
|
|
|
|
|
|
config = ConfigManager()
|
|
|
|
config.load_config_file(settings.user_config_file)
|
|
|
|
for config_file in args.config:
|
|
|
|
if not os.path.exists(config_file):
|
|
|
|
raise ConfigError("Config file {} not found".format(config_file))
|
|
|
|
config.load_config_file(config_file)
|
|
|
|
|
2017-02-21 13:37:11 +00:00
|
|
|
command = commands[args.command]
|
2017-03-06 11:10:25 +00:00
|
|
|
sys.exit(command.execute(config, args))
|
|
|
|
|
2018-02-28 15:18:58 +00:00
|
|
|
except KeyboardInterrupt as e:
|
|
|
|
log.log_error(e, logger)
|
2017-03-06 11:10:25 +00:00
|
|
|
sys.exit(3)
|
2017-02-21 13:37:11 +00:00
|
|
|
except Exception as e: # pylint: disable=broad-except
|
2018-02-28 15:18:58 +00:00
|
|
|
log.log_error(e, logger)
|
2017-03-06 11:10:25 +00:00
|
|
|
sys.exit(2)
|