in src/python/pants/option/parser.py [0:0]
def parse_args(self, parse_args_request):
"""Set values for this parser's options on the namespace object.
:param Parser.ParseArgsRequest parse_args_request: parameters for parsing this parser's
arguments.
:returns: The `parse_args_request.namespace` object that the option values are being registered
on.
:raises: :class:`ParseError` if any flags weren't recognized.
"""
flag_value_map = parse_args_request.flag_value_map
namespace = parse_args_request.namespace
get_all_scoped_flag_names = parse_args_request.get_all_scoped_flag_names
levenshtein_max_distance = parse_args_request.levenshtein_max_distance
mutex_map = defaultdict(list)
for args, kwargs in self._unnormalized_option_registrations_iter():
self._validate(args, kwargs)
dest = self.parse_dest(*args, **kwargs)
# Compute the values provided on the command line for this option. Note that there may be
# multiple values, for any combination of the following reasons:
# - The user used the same flag multiple times.
# - The user specified a boolean flag (--foo) and its inverse (--no-foo).
# - The option has multiple names, and the user used more than one of them.
#
# We also check if the option is deprecated, but we only do so if the option is explicitly
# specified as a command-line flag, so we don't spam users with deprecated option values
# specified in config, which isn't something they control.
implicit_value = kwargs.get('implicit_value')
if implicit_value is None and kwargs.get('type') == bool:
implicit_value = True # Allows --foo to mean --foo=true.
flag_vals = []
def add_flag_val(v):
if v is None:
if implicit_value is None:
raise ParseError('Missing value for command line flag {} in {}'.format(
arg, self._scope_str()))
else:
flag_vals.append(implicit_value)
else:
flag_vals.append(v)
for arg in args:
# If the user specified --no-foo on the cmd line, treat it as if the user specified
# --foo, but with the inverse value.
if kwargs.get('type') == bool:
inverse_arg = self._inverse_arg(arg)
if inverse_arg in flag_value_map:
flag_value_map[arg] = [self._invert(v) for v in flag_value_map[inverse_arg]]
implicit_value = self._invert(implicit_value)
del flag_value_map[inverse_arg]
if arg in flag_value_map:
for v in flag_value_map[arg]:
add_flag_val(v)
del flag_value_map[arg]
# Get the value for this option, falling back to defaults as needed.
try:
val = self._compute_value(dest, kwargs, flag_vals)
except ParseError as e:
# Reraise a new exception with context on the option being processed at the time of error.
# Note that other exception types can be raised here that are caught by ParseError (e.g.
# BooleanConversionError), hence we reference the original exception type as type(e).
raise type(e)(
'Error computing value for {} in {} (may also be from PANTS_* environment variables).'
'\nCaused by:\n{}'.format(', '.join(args), self._scope_str(), traceback.format_exc())
)
# If the option is explicitly given, check deprecation and mutual exclusion.
if val.rank > RankedValue.HARDCODED:
self._check_deprecated(dest, kwargs)
mutex_dest = kwargs.get('mutually_exclusive_group')
if mutex_dest:
mutex_map[mutex_dest].append(dest)
dest = mutex_dest
else:
mutex_map[dest].append(dest)
if len(mutex_map[dest]) > 1:
raise self.MutuallyExclusiveOptionError(
"Can only provide one of the mutually exclusive options {}".format(mutex_map[dest]))
setattr(namespace, dest, val)
# See if there are any unconsumed flags remaining, and if so, raise a ParseError.
if flag_value_map:
self._raise_error_for_invalid_flag_names(
flag_value_map,
all_scoped_flag_names=list(get_all_scoped_flag_names()),
levenshtein_max_distance=levenshtein_max_distance)
return namespace