# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Purpose of this module is to hold common script/commandline functionality.

This ranges from optparse, to a basic script wrapper setup (much like
what is used for chromite.bin.*).
"""

from __future__ import print_function

import argparse
import collections
import datetime
import functools
import os
import optparse
import signal
import sys
import urlparse

# TODO(build): sort the cbuildbot.constants/lib.constants issue;
# lib shouldn't have to import from buildbot like this.
from chromite.cbuildbot import constants
from chromite.lib import cros_build_lib
from chromite.lib import cros_logging as logging
from chromite.lib import gs
from chromite.lib import osutils
from chromite.lib import path_util
from chromite.lib import terminal
from chromite.lib import workspace_lib


DEVICE_SCHEME_FILE = 'file'
DEVICE_SCHEME_SSH = 'ssh'
DEVICE_SCHEME_USB = 'usb'


# Command line options to automatically convert from relative or absolute paths
# to locator paths when RunInsideChroot() is used.
_LOCATOR_OVERRIDE_OPTIONS = ('brick', 'blueprint')


class ChrootRequiredError(Exception):
  """Raised when a command must be run in the chroot

  This exception is intended to be caught by code which will restart execution
  in the chroot. Throwing this exception allows contexts to be exited and
  general cleanup to happen before we exec an external binary.

  The command to run inside the chroot, and (optionally) special cros_sdk
  arguments are attached to the exception. Any adjustments to the arguments
  should be done before raising the exception.
  """
  def __init__(self, cmd, chroot_args=None):
    """Constructor for ChrootRequiredError.

    Args:
      cmd: Command line to run inside the chroot as a list of strings.
      chroot_args: Arguments to pass directly to cros_sdk.
    """
    super(ChrootRequiredError, self).__init__(self)
    self.cmd = cmd
    self.chroot_args = chroot_args


class ExecRequiredError(Exception):
  """Raised when a command needs to exec, after cleanup.

  This exception is intended to be caught by code which will exec another
  command. Throwing this exception allows contexts to be exited and general
  cleanup to happen before we exec an external binary.

  The command to run is attached to the exception. Any adjustments to the
  arguments should be done before raising the exception.
  """
  def __init__(self, cmd):
    """Constructor for ExecRequiredError.

    Args:
      cmd: Command line to run inside the chroot as a list of strings.
    """
    super(ExecRequiredError, self).__init__(self)
    self.cmd = cmd


def AbsolutePath(_option, _opt, value):
  """Expand paths and make them absolute."""
  return osutils.ExpandPath(value)


def NormalizeGSPath(value):
  """Normalize GS paths."""
  url = gs.CanonicalizeURL(value, strict=True)
  return '%s%s' % (gs.BASE_GS_URL, os.path.normpath(url[len(gs.BASE_GS_URL):]))


def NormalizeLocalOrGSPath(value):
  """Normalize a local or GS path."""
  ptype = 'gs_path' if gs.PathIsGs(value) else 'path'
  return VALID_TYPES[ptype](value)


def ParseBool(value):
  """Parse bool argument into a bool value.

  For the existing type=bool functionality, the parser uses the built-in bool(x)
  function to determine the value.  This function will only return false if x
  is False or omitted.  Even with this type specified, however, arguments that
  are generated from a command line initially get parsed as a string, and for
  any string value passed in to bool(x), it will always return True.

  Args:
    value: String representing a boolean value.

  Returns:
    True or False.
  """
  return cros_build_lib.BooleanShellValue(value, False)


def ParseDate(value):
  """Parse date argument into a datetime.date object.

  Args:
    value: String representing a single date in "YYYY-MM-DD" format.

  Returns:
    A datetime.date object.
  """
  try:
    return datetime.datetime.strptime(value, '%Y-%m-%d').date()
  except ValueError:
    # Give a helpful error message about the format expected.  Putting this
    # message in the exception is useless because argparse ignores the
    # exception message and just says the value is invalid.
    logging.error('Date is expected to be in format YYYY-MM-DD.')
    raise


def NormalizeUri(value):
  """Normalize a local path or URI."""
  o = urlparse.urlparse(value)
  if o.scheme == 'file':
    # Trim off the file:// prefix.
    return VALID_TYPES['path'](value[7:])
  elif o.scheme not in ('', 'gs'):
    o = list(o)
    o[2] = os.path.normpath(o[2])
    return urlparse.urlunparse(o)
  else:
    return NormalizeLocalOrGSPath(value)


# A Device object holds information parsed from the command line input:
#   scheme: DEVICE_SCHEME_SSH, DEVICE_SCHEME_USB, or DEVICE_SCHEME_FILE.
#   username: String SSH username or None.
#   hostname: String SSH hostname or None.
#   port: Int SSH port or None.
#   path: String USB/file path or None.
#   raw: String raw input from the command line.
# For now this is a superset of all information for USB, SSH, or file devices.
# If functionality diverges based on type, it may be useful to split this into
# separate device classes instead.
Device = cros_build_lib.Collection(
    'Device', scheme=None, username=None, hostname=None, port=None, path=None,
    raw=None)


class DeviceParser(object):
  """Parses devices as an argparse argument type.

  In addition to parsing user input, this class will also ensure that only
  supported device schemes are accepted by the parser. For example,
  `cros deploy` only makes sense with an SSH device, but `cros flash` can use
  SSH, USB, or file device schemes.

  If the device input is malformed or the scheme is wrong, an error message will
  be printed and the program will exit.

  Valid device inputs are:
    - [ssh://][username@]hostname[:port].
    - usb://[path].
    - file://path or /absolute_path.
    - [ssh://]:vm:.

  The last item above is an alias for ssh'ing into a virtual machine on a
  localhost.  It gets translated into 'localhost:9222'.

  Usage:
    parser = argparse.ArgumentParser()

    parser.add_argument(
      'ssh_device',
      type=commandline.DeviceParser(commandline.DEVICE_SCHEME_SSH))

    parser.add_argument(
      'usb_or_file_device',
      type=commandline.DeviceParser([commandline.DEVICE_SCHEME_USB,
                                     commandline.DEVICE_SCHEME_FILE]))
  """

  def __init__(self, schemes):
    """Initializes the parser.

    See the class comments for usage examples.

    Args:
      schemes: A scheme or list of schemes to accept.
    """
    self.schemes = [schemes] if isinstance(schemes, basestring) else schemes
    # Provide __name__ for argparse to print on failure, or else it will use
    # repr() which creates a confusing error message.
    self.__name__ = type(self).__name__

  def __call__(self, value):
    """Parses a device input and enforces constraints.

    DeviceParser is an object so that a set of valid schemes can be specified,
    but argparse expects a parsing function, so we overload __call__() for
    argparse to use.

    Args:
      value: String representing a device target. See class comments for
        valid device input formats.

    Returns:
      A Device object.

    Raises:
      ValueError: |value| is not a valid device specifier or doesn't
        match the supported list of schemes.
    """
    try:
      device = self._ParseDevice(value)
      self._EnforceConstraints(device, value)
      return device
    except ValueError as e:
      # argparse ignores exception messages, so print the message manually.
      logging.error(e)
      raise
    except Exception as e:
      logging.error('Internal error while parsing device input: %s', e)
      raise

  def _EnforceConstraints(self, device, value):
    """Verifies that user-specified constraints are upheld.

    Checks that the parsed device has a scheme that matches what the user
    expects. Additional constraints can be added if needed.

    Args:
      device: Device object.
      value: String representing a device target.

    Raises:
      ValueError: |device| has the wrong scheme.
    """
    if device.scheme not in self.schemes:
      raise ValueError('Unsupported scheme "%s" for device "%s"' %
                       (device.scheme, value))

  def _ParseDevice(self, value):
    """Parse a device argument.

    Args:
      value: String representing a device target.

    Returns:
      A Device object.

    Raises:
      ValueError: |value| is not a valid device specifier.
    """
    # ':vm:' is an alias for ssh'ing into a virtual machihne on localhost;
    # translate it appropriately.
    if value.strip().lower() == ':vm:':
      value = 'localhost:9222'
    elif value.strip().lower() == 'ssh://:vm:':
      value = 'ssh://localhost:9222'
    parsed = urlparse.urlparse(value)
    if not parsed.scheme:
      # Default to a file scheme for absolute paths, SSH scheme otherwise.
      if value and value[0] == '/':
        scheme = DEVICE_SCHEME_FILE
      else:
        # urlparse won't provide hostname/username/port unless a scheme is
        # specified so we need to re-parse.
        parsed = urlparse.urlparse('%s://%s' % (DEVICE_SCHEME_SSH, value))
        scheme = DEVICE_SCHEME_SSH
    else:
      scheme = parsed.scheme.lower()

    if scheme == DEVICE_SCHEME_SSH:
      hostname = parsed.hostname
      port = parsed.port
      if hostname == 'localhost' and not port:
        # Use of localhost as the actual machine is uncommon enough relative to
        # the use of KVM that we require users to specify localhost:22 if they
        # actually want to connect to the localhost.  Otherwise the expectation
        # is that they intend to access the VM but forget or didn't know to use
        # port 9222.
        raise ValueError('To connect to localhost, use ssh://localhost:22 '
                         'explicitly, or use ssh://localhost:9222 for the local'
                         ' VM.')
      if not hostname:
        raise ValueError('Hostname is required for device "%s"' % value)
      return Device(scheme=scheme, username=parsed.username, hostname=hostname,
                    port=port, raw=value)
    elif scheme == DEVICE_SCHEME_USB:
      path = parsed.netloc + parsed.path
      # Change path '' to None for consistency.
      return Device(scheme=scheme, path=path if path else None, raw=value)
    elif scheme == DEVICE_SCHEME_FILE:
      path = parsed.netloc + parsed.path
      if not path:
        raise ValueError('Path is required for "%s"' % value)
      return Device(scheme=scheme, path=path, raw=value)
    else:
      raise ValueError('Unknown device scheme "%s" in "%s"' % (scheme, value))


def NormalizeWorkspacePath(path, default_dir=None, extension=None):
  """Normalize a workspace path.

  Converts |path| into a locator and applies |default_dir| and/or
  |extension| if specified.

  Args:
    path: Relative, absolute, or locator path in the CWD workspace.
    default_dir: If |path| does not contain '/', prepend this
      directory to the result.
    extension: If |path| doesn't end in this extension, append this
      extension to the result.

  Returns:
    Workspace locator corresponding to the modified |path|.

  Raises:
    ValueError: |path| isn't in the workspace.
  """
  if default_dir and '/' not in path:
    path = os.path.join(default_dir, path)

  if extension:
    extension = '.' + extension
    if os.path.splitext(path)[1] != extension:
      path += extension

  if workspace_lib.IsLocator(path):
    return path

  locator = workspace_lib.PathToLocator(path)
  if not locator:
    # argparse ignores exception messages; log it as well so the user sees it.
    error_message = '%s is not in the current workspace.' % path
    logging.error(error_message)
    raise ValueError(error_message)
  return locator


def NormalizeBrickPath(path):
  """Normalize a brick path using some common assumptions.

  Makes the following changes to |path|:
    1. Put non-paths in //bricks (e.g. foo -> //bricks/foo).
    2. Convert to a workspace locator.

  Args:
    path: brick path.

  Returns:
    Locator to the brick.
  """
  return NormalizeWorkspacePath(path, default_dir='//bricks')


def NormalizeBspPath(path):
  """Normalize a BSP path using some common assumptions.

  Makes the following changes to |path|:
    1. Put non-paths in //bsps (e.g. foo -> //bsps/foo).
    2. Convert to a workspace locator.

  Args:
    path: BSP path.

  Returns:
    Locator to the BSP.
  """
  return NormalizeWorkspacePath(path, default_dir='//bsps')


def NormalizeBlueprintPath(path):
  """Normalize a blueprint path using some common assumptions.

  Makes the following changes to |path|:
    1. Put non-paths in //blueprints (e.g. foo -> //blueprints/foo).
    2. Add .json if not already present.
    3. Convert to a workspace locator.

  Args:
    path: blueprint path.

  Returns:
    Locator to the blueprint.
  """
  return NormalizeWorkspacePath(path, default_dir='//blueprints',
                                extension='json')


VALID_TYPES = {
    'bool': ParseBool,
    'date': ParseDate,
    'path': osutils.ExpandPath,
    'gs_path': NormalizeGSPath,
    'local_or_gs_path': NormalizeLocalOrGSPath,
    'path_or_uri': NormalizeUri,
    'blueprint_path': NormalizeBlueprintPath,
    'brick_path': NormalizeBrickPath,
    'bsp_path': NormalizeBspPath,
    'workspace_path': NormalizeWorkspacePath,
}


def OptparseWrapCheck(desc, check_f, _option, opt, value):
  """Optparse adapter for type checking functionality."""
  try:
    return check_f(value)
  except ValueError:
    raise optparse.OptionValueError(
        'Invalid %s given: --%s=%s' % (desc, opt, value))


class Option(optparse.Option):
  """Subclass to implement path evaluation & other useful types."""

  _EXTRA_TYPES = ('path', 'gs_path')
  TYPES = optparse.Option.TYPES + _EXTRA_TYPES
  TYPE_CHECKER = optparse.Option.TYPE_CHECKER.copy()
  for t in _EXTRA_TYPES:
    TYPE_CHECKER[t] = functools.partial(OptparseWrapCheck, t, VALID_TYPES[t])


class FilteringOption(Option):
  """Subclass that supports Option filtering for FilteringOptionParser"""

  def take_action(self, action, dest, opt, value, values, parser):
    if action in FilteringOption.ACTIONS:
      Option.take_action(self, action, dest, opt, value, values, parser)

    if value is None:
      value = []
    elif not self.nargs or self.nargs <= 1:
      value = [value]

    parser.AddParsedArg(self, opt, [str(v) for v in value])


# TODO: logging.Formatter is not a subclass of object in python
# 2.6. Make ColoredFormatter explicitly inherit from object so that
# functions such as super() will not fail. This should be removed
# after python is upgraded to 2.7 on master2 (crbug.com/409273).
class ColoredFormatter(logging.Formatter, object):
  """A logging formatter that can color the messages."""

  _COLOR_MAPPING = {
      'WARNING': terminal.Color.YELLOW,
      'ERROR': terminal.Color.RED,
  }

  def __init__(self, *args, **kwargs):
    """Initializes the formatter.

    Args:
      args: See logging.Formatter for specifics.
      kwargs: See logging.Formatter for specifics.
      enable_color: Whether to enable colored logging. Defaults
        to None, where terminal.Color will set to a sane default.
    """
    self.color = terminal.Color(enabled=kwargs.pop('enable_color', None))
    super(ColoredFormatter, self).__init__(*args, **kwargs)

  def format(self, record, **kwargs):
    """Formats |record| with color."""
    msg = super(ColoredFormatter, self).format(record, **kwargs)
    color = self._COLOR_MAPPING.get(record.levelname)
    return msg if not color else self.color.Color(color, msg)


class ChromiteStreamHandler(logging.StreamHandler):
  """A stream handler for logging."""


class BaseParser(object):
  """Base parser class that includes the logic to add logging controls."""

  DEFAULT_LOG_LEVELS = ('fatal', 'critical', 'error', 'warning', 'notice',
                        'info', 'debug')

  DEFAULT_LOG_LEVEL = 'info'
  ALLOW_LOGGING = True

  def __init__(self, **kwargs):
    """Initialize this parser instance.

    kwargs:
      logging: Defaults to ALLOW_LOGGING from the class; if given,
        add --log-level.
      default_log_level: If logging is enabled, override the default logging
        level.  Defaults to the class's DEFAULT_LOG_LEVEL value.
      log_levels: If logging is enabled, this overrides the enumeration of
        allowed logging levels.  If not given, defaults to the classes
        DEFAULT_LOG_LEVELS value.
      manual_debug: If logging is enabled and this is True, suppress addition
        of a --debug alias.  This option defaults to True unless 'debug' has
        been exempted from the allowed logging level targets.
      caching: If given, must be either a callable that discerns the cache
        location if it wasn't specified (the prototype must be akin to
        lambda parser, values:calculated_cache_dir_path; it may return None to
        indicate that it handles setting the value on its own later in the
        parsing including setting the env), or True; if True, the
        machinery defaults to invoking the class's FindCacheDir method
        (which can be overridden).  FindCacheDir $CROS_CACHEDIR, falling
        back to $REPO/.cache, finally falling back to $TMP.
        Note that the cache_dir is not created, just discerned where it
        should live.
        If False, or caching is not given, then no --cache-dir option will be
        added.
    """
    self.debug_enabled = False
    self.caching_group = None
    self.debug_group = None
    self.default_log_level = None
    self.log_levels = None
    self.logging_enabled = kwargs.get('logging', self.ALLOW_LOGGING)
    self.default_log_level = kwargs.get('default_log_level',
                                        self.DEFAULT_LOG_LEVEL)
    self.log_levels = tuple(x.lower() for x in
                            kwargs.get('log_levels', self.DEFAULT_LOG_LEVELS))
    self.debug_enabled = (not kwargs.get('manual_debug', False)
                          and 'debug' in self.log_levels)
    self.caching = kwargs.get('caching', False)

  @staticmethod
  def PopUsedArgs(kwarg_dict):
    """Removes keys used by the base parser from the kwarg namespace."""
    parser_keys = ['logging', 'default_log_level', 'log_levels', 'manual_debug',
                   'caching']
    for key in parser_keys:
      kwarg_dict.pop(key, None)

  def SetupOptions(self):
    """Sets up special chromite options for an OptionParser."""
    if self.logging_enabled:
      self.debug_group = self.add_option_group('Debug options')
      self.add_option_to_group(
          self.debug_group, '--log-level', choices=self.log_levels,
          default=self.default_log_level,
          help='Set logging level to report at.')
      self.add_option_to_group(
          self.debug_group, '--log_format', action='store',
          default=constants.LOGGER_FMT,
          help='Set logging format to use.')
      if self.debug_enabled:
        self.add_option_to_group(
            self.debug_group, '--debug', action='store_const', const='debug',
            dest='log_level', help='Alias for `--log-level=debug`. '
            'Useful for debugging bugs/failures.')
      self.add_option_to_group(
          self.debug_group, '--nocolor', action='store_false', dest='color',
          default=None,
          help='Do not use colorized output (or `export NOCOLOR=true`)')

    if self.caching:
      self.caching_group = self.add_option_group('Caching Options')
      self.add_option_to_group(
          self.caching_group, '--cache-dir', default=None, type='path',
          help='Override the calculated chromeos cache directory; '
          "typically defaults to '$REPO/.cache' .")

  def SetupLogging(self, opts):
    """Sets up logging based on |opts|."""
    value = opts.log_level.upper()
    logger = logging.getLogger()
    logger.setLevel(getattr(logging, value))
    formatter = ColoredFormatter(fmt=opts.log_format,
                                 datefmt=constants.LOGGER_DATE_FMT,
                                 enable_color=opts.color)

    # Only set colored formatter for ChromiteStreamHandler instances,
    # which could have been added by ScriptWrapperMain() below.
    chromite_handlers = [x for x in logger.handlers if
                         isinstance(x, ChromiteStreamHandler)]
    for handler in chromite_handlers:
      handler.setFormatter(formatter)

    return value

  def DoPostParseSetup(self, opts, args):
    """Method called to handle post opts/args setup.

    This can be anything from logging setup to positional arg count validation.

    Args:
      opts: optparse.Values or argparse.Namespace instance
      args: position arguments unconsumed from parsing.

    Returns:
      (opts, args), w/ whatever modification done.
    """
    if self.logging_enabled:
      value = self.SetupLogging(opts)
      if self.debug_enabled:
        opts.debug = (value == 'DEBUG')

    if self.caching:
      path = os.environ.get(constants.SHARED_CACHE_ENVVAR)
      if path is not None and opts.cache_dir is None:
        opts.cache_dir = os.path.abspath(path)

      opts.cache_dir_specified = opts.cache_dir is not None
      if not opts.cache_dir_specified:
        func = self.FindCacheDir if not callable(self.caching) else self.caching
        opts.cache_dir = func(self, opts)
      if opts.cache_dir is not None:
        self.ConfigureCacheDir(opts.cache_dir)

    # Overrides for automatic path-to-locator conversion.
    for option in _LOCATOR_OVERRIDE_OPTIONS:
      value = getattr(opts, '%s_locator_override' % option, None)
      if value:
        setattr(opts, option, value)

    return opts, args

  @staticmethod
  def ConfigureCacheDir(cache_dir):
    if cache_dir is None:
      os.environ.pop(constants.SHARED_CACHE_ENVVAR, None)
      logging.debug('Removed cache_dir setting')
    else:
      os.environ[constants.SHARED_CACHE_ENVVAR] = cache_dir
      logging.debug('Configured cache_dir to %r', cache_dir)

  @classmethod
  def FindCacheDir(cls, _parser, _opts):
    logging.debug('Cache dir lookup.')
    return path_util.FindCacheDir()

  def add_option_group(self, *args, **kwargs):
    """Returns a new option group see optparse.OptionParser.add_option_group."""
    raise NotImplementedError('Subclass must override this method')

  @staticmethod
  def add_option_to_group(group, *args, **kwargs):
    """Adds the given option defined by args and kwargs to group."""
    group.add_option(*args, **kwargs)


class ArgumentNamespace(argparse.Namespace):
  """Class to mimic argparse.Namespace with value freezing support."""
  __metaclass__ = cros_build_lib.FrozenAttributesClass
  _FROZEN_ERR_MSG = 'Option values are frozen, cannot alter %s.'


# Note that because optparse.Values is not a new-style class this class
# must use the mixin FrozenAttributesMixin rather than the metaclass
# FrozenAttributesClass.
class OptionValues(cros_build_lib.FrozenAttributesMixin, optparse.Values):
  """Class to mimic optparse.Values with value freezing support."""
  _FROZEN_ERR_MSG = 'Option values are frozen, cannot alter %s.'

  def __init__(self, defaults, *args, **kwargs):
    cros_build_lib.FrozenAttributesMixin.__init__(self)
    optparse.Values.__init__(self, defaults, *args, **kwargs)

    # Used by FilteringParser.
    self.parsed_args = None


class OptionParser(optparse.OptionParser, BaseParser):
  """Custom parser adding our custom option class in.

  Aside from adding a couple of types (path for absolute paths,
  gs_path for google storage urls, and log_level for logging level control),
  this additionally exposes logging control by default; if undesired,
  either derive from this class setting ALLOW_LOGGING to False, or
  pass in logging=False to the constructor.
  """

  DEFAULT_OPTION_CLASS = Option

  def __init__(self, usage=None, **kwargs):
    BaseParser.__init__(self, **kwargs)
    self.PopUsedArgs(kwargs)
    kwargs.setdefault('option_class', self.DEFAULT_OPTION_CLASS)
    optparse.OptionParser.__init__(self, usage=usage, **kwargs)
    self.SetupOptions()

  def parse_args(self, args=None, values=None):
    # If no Values object is specified then use our custom OptionValues.
    if values is None:
      values = OptionValues(defaults=self.defaults)

    opts, remaining = optparse.OptionParser.parse_args(
        self, args=args, values=values)
    return self.DoPostParseSetup(opts, remaining)


PassedOption = collections.namedtuple(
    'PassedOption', ['opt_inst', 'opt_str', 'value_str'])


class FilteringParser(OptionParser):
  """Custom option parser for filtering options."""

  DEFAULT_OPTION_CLASS = FilteringOption

  def parse_args(self, args=None, values=None):
    # If no Values object is specified then use our custom OptionValues.
    if values is None:
      values = OptionValues(defaults=self.defaults)

    values.parsed_args = []

    return OptionParser.parse_args(self, args=args, values=values)

  def AddParsedArg(self, opt_inst, opt_str, value_str):
    """Add a parsed argument with attributes.

    Args:
      opt_inst: An instance of a raw optparse.Option object that represents the
                option.
      opt_str: The option string.
      value_str: A list of string-ified values dentified by OptParse.
    """
    self.values.parsed_args.append(PassedOption(opt_inst, opt_str, value_str))

  @staticmethod
  def FilterArgs(parsed_args, filter_fn):
    """Filter the argument by passing it through a function.

    Args:
      parsed_args: The list of parsed argument namedtuples to filter.  Tuples
        are of the form (opt_inst, opt_str, value_str).
      filter_fn: A function with signature f(PassedOption), and returns True if
        the argument is to be passed through.  False if not.

    Returns:
      A tuple containing two lists - one of accepted arguments and one of
      removed arguments.
    """
    removed = []
    accepted = []
    for arg in parsed_args:
      target = accepted if filter_fn(arg) else removed
      target.append(arg.opt_str)
      target.extend(arg.value_str)

    return accepted, removed


class SharedParser(argparse.ArgumentParser):
  """A type of parser that may be used as a shared parent for subparsers."""

  def __init__(self, **kwargs):
    kwargs.setdefault('add_help', False)
    argparse.ArgumentParser.__init__(self, **kwargs)


class ArgumentParser(BaseParser, argparse.ArgumentParser):
  """Custom argument parser for use by chromite.

  This class additionally exposes logging control by default; if undesired,
  either derive from this class setting ALLOW_LOGGING to False, or
  pass in logging=False to the constructor.
  """

  def __init__(self, usage=None, **kwargs):
    kwargs.setdefault('formatter_class', argparse.RawDescriptionHelpFormatter)
    BaseParser.__init__(self, **kwargs)
    self.PopUsedArgs(kwargs)
    argparse.ArgumentParser.__init__(self, usage=usage, **kwargs)
    self._SetupTypes()
    self.SetupOptions()
    self._SetupLocatorOverride()

  def _SetupTypes(self):
    """Register types with ArgumentParser."""
    for t, check_f in VALID_TYPES.iteritems():
      self.register('type', t, check_f)

  def _SetupLocatorOverride(self):
    """Create hidden arguments for automatic path-to-locator conversion."""
    group = self.add_argument_group('Locators', description=argparse.SUPPRESS)
    for option in _LOCATOR_OVERRIDE_OPTIONS:
      group.add_argument('--%s-locator-override' % option,
                         help=argparse.SUPPRESS)

  def add_option_group(self, *args, **kwargs):
    """Return an argument group rather than an option group."""
    return self.add_argument_group(*args, **kwargs)

  @staticmethod
  def add_option_to_group(group, *args, **kwargs):
    """Adds an argument rather than an option to the given group."""
    return group.add_argument(*args, **kwargs)

  def parse_args(self, args=None, namespace=None):
    """Translates OptionParser call to equivalent ArgumentParser call."""
    # If no Namespace object is specified then use our custom ArgumentNamespace.
    if namespace is None:
      namespace = ArgumentNamespace()

    # Unlike OptionParser, ArgParser works only with a single namespace and no
    # args. Re-use BaseParser DoPostParseSetup but only take the namespace.
    namespace = argparse.ArgumentParser.parse_args(
        self, args=args, namespace=namespace)
    return self.DoPostParseSetup(namespace, None)[0]


class _ShutDownException(SystemExit):
  """Exception raised when user hits CTRL+C."""

  def __init__(self, sig_num, message):
    self.signal = sig_num
    # Setup a usage message primarily for any code that may intercept it
    # while this exception is crashing back up the stack to us.
    SystemExit.__init__(self, message)
    self.args = (sig_num, message)


def _DefaultHandler(signum, _frame):
  # Don't double process sigterms; just trigger shutdown from the first
  # exception.
  signal.signal(signum, signal.SIG_IGN)
  raise _ShutDownException(
      signum, 'Received signal %i; shutting down' % (signum,))


def _RestartInChroot(cmd, chroot_args):
  """Rerun inside the chroot.

  Args:
    cmd: Command line to run inside the chroot as a list of strings.
    chroot_args: Arguments to pass directly to cros_sdk (or None).
  """
  return cros_build_lib.RunCommand(cmd, error_code_ok=True,
                                   enter_chroot=True, chroot_args=chroot_args,
                                   cwd=constants.SOURCE_ROOT,
                                   mute_output=False).returncode


def _AddCliCommandOption(argv, option, value=None):
  """Adds an option to command line |argv|.

  Use this to add options to a CliCommand argument list rather than
  extending the list directly in order to avoid bugs when using
  argparse.REMAINDER.

  For example, with `brillo chroot` we want this:
    brillo chroot --extra-arg -- ls
  not this:
    brillo chroot -- ls --extra-arg

  Args:
    argv: Current argument list; will be modified by this function.
    option: New option to add.
    value: Option value if required; None to omit.

  Returns:
    |argv|.

  Raises:
    ValueError: |option| is not an optional argument.
  """
  if not option.startswith('-'):
    raise ValueError('"%s" must be an option (starting with -)' % option)

  # Insert at index 2 to put the option after the subcommand for readability,
  # e.g. `brillo chroot --option` rather than `brillo --option chroot`.
  argv.insert(2, option)
  if value is not None:
    argv.insert(3, value)
  return argv


def RunInsideChroot(command, auto_detect_brick=False,
                    auto_detect_workspace=True, auto_locator_override=True):
  """Restart the current command inside the chroot.

  This method is only valid for any code that is run via ScriptWrapperMain.
  It allows proper cleanup of the local context by raising an exception handled
  in ScriptWrapperMain.

  If cwd is in a brick, and --board/--host is not explicitly set, set
  --brick explicitly as we might not be able to detect the curr_brick_locator
  inside the chroot (cwd will have changed).

  Args:
    command: An instance of CliCommand to be restarted inside the chroot.
    auto_detect_brick: If true, sets --brick explicitly.
    auto_detect_workspace: If true, sets up workspace automatically.
    auto_locator_override: If true, adds arguments to override absolute
      or relative paths with locators for certain options.
  """
  if cros_build_lib.IsInsideChroot():
    return

  # Produce the command line to execute inside the chroot.
  argv = sys.argv[:]
  argv[0] = path_util.ToChrootPath(argv[0])

  target_arg = any(getattr(command.options, arg, None)
                   for arg in ('blueprint', 'board', 'brick', 'host'))
  if auto_detect_brick and not target_arg and command.curr_brick_locator:
    _AddCliCommandOption(argv, '--brick', command.curr_brick_locator)

  # Provide locators so that paths can be found from inside the chroot.
  if auto_locator_override:
    for option in _LOCATOR_OVERRIDE_OPTIONS:
      path = getattr(command.options, option, None)
      if path and not workspace_lib.IsLocator(path):
        locator = workspace_lib.PathToLocator(path)
        if locator:
          _AddCliCommandOption(argv, '--%s-locator-override' % option, locator)

  # Enter the chroot for the workspace, if we are in a workspace.
  # Set log-level of cros_sdk to be same as log-level of command entering the
  # chroot.
  chroot_args = ['--log-level', command.options.log_level]
  if auto_detect_workspace:
    workspace_path = workspace_lib.WorkspacePath()
    if workspace_path:
      chroot_args.extend(['--chroot', workspace_lib.ChrootPath(workspace_path),
                          '--workspace', workspace_path])

  raise ChrootRequiredError(argv, chroot_args)


def ReExec():
  """Restart the current command.

  This method is only valid for any code that is run via ScriptWrapperMain.
  It allows proper cleanup of the local context by raising an exception handled
  in ScriptWrapperMain.
  """
  # The command to exec.
  raise ExecRequiredError(sys.argv[:])


def ScriptWrapperMain(find_target_func, argv=None,
                      log_level=logging.DEBUG,
                      log_format=constants.LOGGER_FMT):
  """Function usable for chromite.script.* style wrapping.

  Note that this function invokes sys.exit on the way out by default.

  Args:
    find_target_func: a function, which, when given the absolute
      pathway the script was invoked via (for example,
      /home/ferringb/cros/trunk/chromite/bin/cros_sdk; note that any
      trailing .py from the path name will be removed),
      will return the main function to invoke (that functor will take
      a single arg- a list of arguments, and shall return either None
      or an integer, to indicate the exit code).
    argv: sys.argv, or an equivalent tuple for testing.  If nothing is
      given, sys.argv is defaulted to.
    log_level: Default logging level to start at.
    log_format: Default logging format to use.
  """
  if argv is None:
    argv = sys.argv[:]
  target = os.path.abspath(argv[0])
  name = os.path.basename(target)
  if target.endswith('.py'):
    target = os.path.splitext(target)[0]
  target = find_target_func(target)
  if target is None:
    print('Internal error detected- no main functor found in module %r.' %
          (name,), file=sys.stderr)
    sys.exit(100)

  # Set up basic logging information for all modules that use logging.
  # Note a script target may setup default logging in its module namespace
  # which will take precedence over this.
  logger = logging.getLogger()
  logger.setLevel(log_level)
  logger_handler = ChromiteStreamHandler()
  logger_handler.setFormatter(
      logging.Formatter(fmt=log_format, datefmt=constants.LOGGER_DATE_FMT))
  logger.addHandler(logger_handler)

  signal.signal(signal.SIGTERM, _DefaultHandler)

  ret = 1
  try:
    ret = target(argv[1:])
  except _ShutDownException as e:
    sys.stdout.flush()
    print('%s: Signaled to shutdown: caught %i signal.' % (name, e.signal),
          file=sys.stderr)
    sys.stderr.flush()
  except SystemExit as e:
    # Right now, let this crash through- longer term, we'll update the scripts
    # in question to not use sys.exit, and make this into a flagged error.
    raise
  except ChrootRequiredError as e:
    ret = _RestartInChroot(e.cmd, e.chroot_args)
  except ExecRequiredError as e:
    logging.shutdown()
    # This does not return.
    os.execv(e.cmd[0], e.cmd)
  except Exception as e:
    sys.stdout.flush()
    print('%s: Unhandled exception:' % (name,), file=sys.stderr)
    sys.stderr.flush()
    raise
  finally:
    logging.shutdown()

  if ret is None:
    ret = 0
  sys.exit(ret)
