# Copyright 2018 The Abseil Authors.
#
# 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.

"""This module provides argparse integration with absl.flags.

``argparse_flags.ArgumentParser`` is a drop-in replacement for
:class:`argparse.ArgumentParser`. It takes care of collecting and defining absl
flags in :mod:`argparse`.

Here is a simple example::

    # Assume the following absl.flags is defined in another module:
    #
    #     from absl import flags
    #     flags.DEFINE_string('echo', None, 'The echo message.')
    #
    parser = argparse_flags.ArgumentParser(
        description='A demo of absl.flags and argparse integration.')
    parser.add_argument('--header', help='Header message to print.')

    # The parser will also accept the absl flag `--echo`.
    # The `header` value is available as `args.header` just like a regular
    # argparse flag. The absl flag `--echo` continues to be available via
    # `absl.flags.FLAGS` if you want to access it.
    args = parser.parse_args()

    # Example usages:
    # ./program --echo='A message.' --header='A header'
    # ./program --header 'A header' --echo 'A message.'


Here is another example demonstrates subparsers::

    parser = argparse_flags.ArgumentParser(description='A subcommands demo.')
    parser.add_argument('--header', help='The header message to print.')

    subparsers = parser.add_subparsers(help='The command to execute.')

    roll_dice_parser = subparsers.add_parser(
        'roll_dice', help='Roll a dice.',
        # By default, absl flags can also be specified after the sub-command.
        # To only allow them before sub-command, pass
        # `inherited_absl_flags=None`.
        inherited_absl_flags=None)
    roll_dice_parser.add_argument('--num_faces', type=int, default=6)
    roll_dice_parser.set_defaults(command=roll_dice)

    shuffle_parser = subparsers.add_parser('shuffle', help='Shuffle inputs.')
    shuffle_parser.add_argument(
        'inputs', metavar='I', nargs='+', help='Inputs to shuffle.')
    shuffle_parser.set_defaults(command=shuffle)

    args = parser.parse_args(argv[1:])
    args.command(args)

    # Example usages:
    # ./program --echo='A message.' roll_dice --num_faces=6
    # ./program shuffle --echo='A message.' 1 2 3 4


There are several differences between :mod:`absl.flags` and
:mod:`~absl.flags.argparse_flags`:

1. Flags defined with absl.flags are parsed differently when using the
   argparse parser. Notably:

   1) absl.flags allows both single-dash and double-dash for any flag, and
      doesn't distinguish them; argparse_flags only allows double-dash for
      flag's regular name, and single-dash for flag's ``short_name``.
   2) Boolean flags in absl.flags can be specified with ``--bool``,
      ``--nobool``, as well as ``--bool=true/false`` (though not recommended);
      in argparse_flags, it only allows ``--bool``, ``--nobool``.

2. Help related flag differences:

   1) absl.flags does not define help flags, absl.app does that; argparse_flags
      defines help flags unless passed with ``add_help=False``.
   2) absl.app supports ``--helpxml``; argparse_flags does not.
   3) argparse_flags supports ``-h``; absl.app does not.
"""

import argparse
import sys

from absl import flags


_BUILT_IN_FLAGS = frozenset({
    'help',
    'helpshort',
    'helpfull',
    'helpxml',
    'flagfile',
    'undefok',
})


class ArgumentParser(argparse.ArgumentParser):
  """Custom ArgumentParser class to support special absl flags."""

  def __init__(self, **kwargs):
    """Initializes ArgumentParser.

    Args:
      **kwargs: same as argparse.ArgumentParser, except:
          1. It also accepts `inherited_absl_flags`: the absl flags to inherit.
             The default is the global absl.flags.FLAGS instance. Pass None to
             ignore absl flags.
          2. The `prefix_chars` argument must be the default value '-'.

    Raises:
      ValueError: Raised when prefix_chars is not '-'.
    """
    prefix_chars = kwargs.get('prefix_chars', '-')
    if prefix_chars != '-':
      raise ValueError(
          'argparse_flags.ArgumentParser only supports "-" as the prefix '
          'character, found "{}".'.format(prefix_chars))

    # Remove inherited_absl_flags before calling super.
    self._inherited_absl_flags = kwargs.pop('inherited_absl_flags', flags.FLAGS)
    # Now call super to initialize argparse.ArgumentParser before calling
    # add_argument in _define_absl_flags.
    super(ArgumentParser, self).__init__(**kwargs)

    if self.add_help:
      # -h and --help are defined in super.
      # Also add the --helpshort and --helpfull flags.
      self.add_argument(
          # Action 'help' defines a similar flag to -h/--help.
          '--helpshort', action='help',
          default=argparse.SUPPRESS, help=argparse.SUPPRESS)
      self.add_argument(
          '--helpfull', action=_HelpFullAction,
          default=argparse.SUPPRESS, help='show full help message and exit')

    if self._inherited_absl_flags:
      self.add_argument(
          '--undefok', default=argparse.SUPPRESS, help=argparse.SUPPRESS)
      self._define_absl_flags(self._inherited_absl_flags)

  def parse_known_args(self, args=None, namespace=None):
    if args is None:
      args = sys.argv[1:]
    if self._inherited_absl_flags:
      # Handle --flagfile.
      # Explicitly specify force_gnu=True, since argparse behaves like
      # gnu_getopt: flags can be specified after positional arguments.
      args = self._inherited_absl_flags.read_flags_from_files(
          args, force_gnu=True)

    undefok_missing = object()
    undefok = getattr(namespace, 'undefok', undefok_missing)

    namespace, args = super(ArgumentParser, self).parse_known_args(
        args, namespace)

    # For Python <= 2.7.8: https://bugs.python.org/issue9351, a bug where
    # sub-parsers don't preserve existing namespace attributes.
    # Restore the undefok attribute if a sub-parser dropped it.
    if undefok is not undefok_missing:
      namespace.undefok = undefok

    if self._inherited_absl_flags:
      # Handle --undefok. At this point, `args` only contains unknown flags,
      # so it won't strip defined flags that are also specified with --undefok.
      # For Python <= 2.7.8: https://bugs.python.org/issue9351, a bug where
      # sub-parsers don't preserve existing namespace attributes. The undefok
      # attribute might not exist because a subparser dropped it.
      if hasattr(namespace, 'undefok'):
        args = _strip_undefok_args(namespace.undefok, args)
        # absl flags are not exposed in the Namespace object. See Namespace:
        # https://docs.python.org/3/library/argparse.html#argparse.Namespace.
        del namespace.undefok
      self._inherited_absl_flags.mark_as_parsed()
      try:
        self._inherited_absl_flags.validate_all_flags()
      except flags.IllegalFlagValueError as e:
        self.error(str(e))

    return namespace, args

  def _define_absl_flags(self, absl_flags):
    """Defines flags from absl_flags."""
    key_flags = set(absl_flags.get_key_flags_for_module(sys.argv[0]))
    for name in absl_flags:
      if name in _BUILT_IN_FLAGS:
        # Do not inherit built-in flags.
        continue
      flag_instance = absl_flags[name]
      # Each flags with short_name appears in FLAGS twice, so only define
      # when the dictionary key is equal to the regular name.
      if name == flag_instance.name:
        # Suppress the flag in the help short message if it's not a main
        # module's key flag.
        suppress = flag_instance not in key_flags
        self._define_absl_flag(flag_instance, suppress)

  def _define_absl_flag(self, flag_instance, suppress):
    """Defines a flag from the flag_instance."""
    flag_name = flag_instance.name
    short_name = flag_instance.short_name
    argument_names = ['--' + flag_name]
    if short_name:
      argument_names.insert(0, '-' + short_name)
    if suppress:
      helptext = argparse.SUPPRESS
    else:
      # argparse help string uses %-formatting. Escape the literal %'s.
      helptext = flag_instance.help.replace('%', '%%')
    if flag_instance.boolean:
      # Only add the `no` form to the long name.
      argument_names.append('--no' + flag_name)
      self.add_argument(
          *argument_names, action=_BooleanFlagAction, help=helptext,
          metavar=flag_instance.name.upper(),
          flag_instance=flag_instance)
    else:
      self.add_argument(
          *argument_names, action=_FlagAction, help=helptext,
          metavar=flag_instance.name.upper(),
          flag_instance=flag_instance)


class _FlagAction(argparse.Action):
  """Action class for Abseil non-boolean flags."""

  def __init__(
      self,
      option_strings,
      dest,
      help,  # pylint: disable=redefined-builtin
      metavar,
      flag_instance,
      default=argparse.SUPPRESS):
    """Initializes _FlagAction.

    Args:
      option_strings: See argparse.Action.
      dest: Ignored. The flag is always defined with dest=argparse.SUPPRESS.
      help: See argparse.Action.
      metavar: See argparse.Action.
      flag_instance: absl.flags.Flag, the absl flag instance.
      default: Ignored. The flag always uses dest=argparse.SUPPRESS so it
          doesn't affect the parsing result.
    """
    del dest
    self._flag_instance = flag_instance
    super(_FlagAction, self).__init__(
        option_strings=option_strings,
        dest=argparse.SUPPRESS,
        help=help,
        metavar=metavar)

  def __call__(self, parser, namespace, values, option_string=None):
    """See https://docs.python.org/3/library/argparse.html#action-classes."""
    self._flag_instance.parse(values)
    self._flag_instance.using_default_value = False


class _BooleanFlagAction(argparse.Action):
  """Action class for Abseil boolean flags."""

  def __init__(
      self,
      option_strings,
      dest,
      help,  # pylint: disable=redefined-builtin
      metavar,
      flag_instance,
      default=argparse.SUPPRESS):
    """Initializes _BooleanFlagAction.

    Args:
      option_strings: See argparse.Action.
      dest: Ignored. The flag is always defined with dest=argparse.SUPPRESS.
      help: See argparse.Action.
      metavar: See argparse.Action.
      flag_instance: absl.flags.Flag, the absl flag instance.
      default: Ignored. The flag always uses dest=argparse.SUPPRESS so it
          doesn't affect the parsing result.
    """
    del dest, default
    self._flag_instance = flag_instance
    flag_names = [self._flag_instance.name]
    if self._flag_instance.short_name:
      flag_names.append(self._flag_instance.short_name)
    self._flag_names = frozenset(flag_names)
    super(_BooleanFlagAction, self).__init__(
        option_strings=option_strings,
        dest=argparse.SUPPRESS,
        nargs=0,  # Does not accept values, only `--bool` or `--nobool`.
        help=help,
        metavar=metavar)

  def __call__(self, parser, namespace, values, option_string=None):
    """See https://docs.python.org/3/library/argparse.html#action-classes."""
    if not isinstance(values, list) or values:
      raise ValueError('values must be an empty list.')
    if option_string.startswith('--'):
      option = option_string[2:]
    else:
      option = option_string[1:]
    if option in self._flag_names:
      self._flag_instance.parse('true')
    else:
      if not option.startswith('no') or option[2:] not in self._flag_names:
        raise ValueError('invalid option_string: ' + option_string)
      self._flag_instance.parse('false')
    self._flag_instance.using_default_value = False


class _HelpFullAction(argparse.Action):
  """Action class for --helpfull flag."""

  def __init__(self, option_strings, dest, default, help):  # pylint: disable=redefined-builtin
    """Initializes _HelpFullAction.

    Args:
      option_strings: See argparse.Action.
      dest: Ignored. The flag is always defined with dest=argparse.SUPPRESS.
      default: Ignored.
      help: See argparse.Action.
    """
    del dest, default
    super(_HelpFullAction, self).__init__(
        option_strings=option_strings,
        dest=argparse.SUPPRESS,
        default=argparse.SUPPRESS,
        nargs=0,
        help=help)

  def __call__(self, parser, namespace, values, option_string=None):
    """See https://docs.python.org/3/library/argparse.html#action-classes."""
    # This only prints flags when help is not argparse.SUPPRESS.
    # It includes user defined argparse flags, as well as main module's
    # key absl flags. Other absl flags use argparse.SUPPRESS, so they aren't
    # printed here.
    parser.print_help()

    absl_flags = parser._inherited_absl_flags  # pylint: disable=protected-access
    if absl_flags:
      modules = sorted(absl_flags.flags_by_module_dict())
      main_module = sys.argv[0]
      if main_module in modules:
        # The main module flags are already printed in parser.print_help().
        modules.remove(main_module)
      print(absl_flags._get_help_for_modules(  # pylint: disable=protected-access
          modules, prefix='', include_special_flags=True))
    parser.exit()


def _strip_undefok_args(undefok, args):
  """Returns a new list of args after removing flags in --undefok."""
  if undefok:
    undefok_names = set(name.strip() for name in undefok.split(','))
    undefok_names |= set('no' + name for name in undefok_names)
    # Remove undefok flags.
    args = [arg for arg in args if not _is_undefok(arg, undefok_names)]
  return args


def _is_undefok(arg, undefok_names):
  """Returns whether we can ignore arg based on a set of undefok flag names."""
  if not arg.startswith('-'):
    return False
  if arg.startswith('--'):
    arg_without_dash = arg[2:]
  else:
    arg_without_dash = arg[1:]
  if '=' in arg_without_dash:
    name, _ = arg_without_dash.split('=', 1)
  else:
    name = arg_without_dash
  if name in undefok_names:
    return True
  return False
