blob: af21ae3e3de2d4306d4eafb5d57610fa53432ca9 [file] [log] [blame]
# Copyright 2016 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 os.path
import sys
_SRC_DIR = os.path.abspath(os.path.join(
os.path.dirname(__file__), '..', '..', '..'))
sys.path.append(os.path.join(_SRC_DIR, 'build', 'android'))
from pylib import constants
class Options(object):
"""Global options repository.
ParseArgs must be called before use. See _ARGS for common members, these will
be available as instance attributes (eg, OPTIONS.clear_cache).
"""
# Tuples of (argument name, default value, help string).
_ARGS = [ ('chrome_package_name', 'chrome',
'build/android/pylib/constants package description'),
('devtools_hostname', 'localhost',
'hostname for devtools websocket connection'),
('devtools_port', 9222,
'port for devtools websocket connection'),
('local_build_dir', None,
'Build directory for local binary files such as chrome'),
('local_noisy', False,
'Enable local chrome console output'),
('local_profile_dir', None,
'profile directory to use for local runs'),
('no_sandbox', False,
'pass --no-sandbox to browser (local run only; see also '
'https://chromium.googlesource.com/chromium/src/+/master/'
'docs/linux_suid_sandbox_development.md)'),
('devices_file', _SRC_DIR + '/third_party/WebKit/Source/devtools'
'/front_end/emulated_devices/module.json', 'File containing a'
' list of emulated devices characteristics.')
]
def __init__(self):
self._arg_set = set()
self._parsed_args = None
def AddGlobalArgument(self, arg_name, default, help_str):
"""Add a global argument.
Args:
arg_name: the name of the argument. This will be used as an optional --
argument.
default: the default value for the argument. The type of this default will
be used as the type of the argument.
help_str: the argument help string.
"""
self._ARGS.append((arg_name, default, help_str))
def ParseArgs(self, arg_list, description=None, extra=None):
"""Parse command line arguments.
Args:
arg_list: command line argument list.
description: description to use in argument parser.
extra: additional required arguments to add. These will be exposed as
instance attributes. This is either a list of extra arguments, or a
single string or tuple. If a tuple, the first item is the argument and
the second a default, otherwise the argument is required. Arguments are
used as in argparse, ie those beginning with -- are named, and those
without a dash are positional. Don't use a single dash.
"""
parser = self._MakeParser(description, extra)
self._parsed_args = parser.parse_args(arg_list)
def ExtractArgs(self, arg_list):
"""Extract arguments from arg_str.
Args:
arg_list: command line argument list. It will be changed so that arguments
used by this options instance are removed.
"""
parser = self._MakeParser()
(self._parsed_args, unused) = parser.parse_known_args(arg_list)
del arg_list[:]
arg_list.extend(unused)
def GetParentParser(self, group_name='Global'):
"""Returns a parser suitable for passing in as a parent to argparse.
Args:
group_name: A group name for the parser (see argparse's
add_argument_group).
Returns:
An argparse parser instance.
"""
return self._MakeParser(group=group_name)
def SetParsedArgs(self, parsed_args):
"""Set parsed args. Used with GetParentParser.
Args:
parsed_args: the result of argparse.parse_args or similar.
"""
self._parsed_args = parsed_args
def _MakeParser(self, description=None, extra=None, group=None):
self._arg_set = set()
add_help = True if group is None else False
parser = argparse.ArgumentParser(
description=description, add_help=add_help)
container = parser if group is None else parser.add_argument_group(group)
for arg, default, help_str in self._ARGS:
# All global options are named.
arg = '--' + arg
self._AddArg(container, arg, default, help_str=help_str)
if extra is not None:
if type(extra) is not list:
extra = [extra]
for arg in extra:
if type(arg) is tuple:
argname, default = arg
self._AddArg(container, argname, default)
else:
self._AddArg(container, arg, None, required=True)
return parser
def _AddArg(self, container, arg, default, required=False, help_str=None):
assert not arg.startswith('-') or arg.startswith('--'), \
"Single dash arguments aren't supported: %s" % arg
arg_name = arg
if arg.startswith('--'):
arg_name = arg[2:]
assert arg_name not in self._arg_set, \
'%s extra arg is a duplicate' % arg_name
self._arg_set.add(arg_name)
kwargs = {}
if required and arg.startswith('--'):
kwargs['required'] = required
if help_str is not None:
kwargs['help'] = help_str
if default is not None:
if type(default) is bool:
# If the default of a switch is true, setting the flag stores false.
if default:
kwargs['action'] = 'store_false'
else:
kwargs['action'] = 'store_true'
else:
kwargs['default'] = default
kwargs['type'] = type(default)
container.add_argument(arg, **kwargs)
def __getattr__(self, name):
if name in self._arg_set:
assert self._parsed_args, 'Option requested before ParseArgs called'
return getattr(self._parsed_args, name)
raise AttributeError(name)
def ChromePackage(self):
return constants.PACKAGE_INFO[self.chrome_package_name]
def LocalBinary(self, binary_name):
"""Get local binary path from its name."""
assert self.local_build_dir, '--local_build_dir needs to be set.'
path = os.path.join(self.local_build_dir, binary_name)
assert os.path.isfile(path), \
'Missing binary file {} (wrong --local_build_dir?).'.format(path)
return path
OPTIONS = Options()