Ejemplo n.º 1
0
def usage(shorthelp=False,
          writeto_stdout=False,
          detailed_error=None,
          exitcode=None):
    """Writes __main__'s docstring to stderr with some help text.

  Args:
    shorthelp: bool, if True, prints only flags from the main module,
        rather than all flags.
    writeto_stdout: bool, if True, writes help message to stdout,
        rather than to stderr.
    detailed_error: str, additional detail about why usage info was presented.
    exitcode: optional integer, if set, exits with this status code after
        writing help.
  """
    if writeto_stdout:
        stdfile = sys.stdout
    else:
        stdfile = sys.stderr

    doc = sys.modules['__main__'].__doc__
    if not doc:
        doc = '\nUSAGE: %s [flags]\n' % sys.argv[0]
        doc = flags.text_wrap(doc, indent='       ', firstline_indent='')
    else:
        # Replace all '%s' with sys.argv[0], and all '%%' with '%'.
        num_specifiers = doc.count('%') - 2 * doc.count('%%')
        try:
            doc %= (sys.argv[0], ) * num_specifiers
        except (OverflowError, TypeError, ValueError):
            # Just display the docstring as-is.
            pass
    if shorthelp:
        flag_str = FLAGS.main_module_help()
    else:
        flag_str = FLAGS.get_help()
    try:
        stdfile.write(doc)
        if flag_str:
            stdfile.write('\nflags:\n')
            stdfile.write(flag_str)
        stdfile.write('\n')
        if detailed_error is not None:
            stdfile.write('\n%s\n' % detailed_error)
    except IOError as e:
        # We avoid printing a huge backtrace if we get EPIPE, because
        # "foo.par --help | less" is a frequent use case.
        if e.errno != errno.EPIPE:
            raise
    if exitcode is not None:
        sys.exit(exitcode)
Ejemplo n.º 2
0
def usage(shorthelp=False, writeto_stdout=False, detailed_error=None,
          exitcode=None):
  """Writes __main__'s docstring to stderr with some help text.

  Args:
    shorthelp: bool, if True, prints only flags from this module,
        rather than all flags.
    writeto_stdout: bool, if True, writes help message to stdout,
        rather than to stderr.
    detailed_error: str, additional detail about why usage info was presented.
    exitcode: optional integer, if set, exits with this status code after
        writing help.
  """
  if writeto_stdout:
    stdfile = sys.stdout
  else:
    stdfile = sys.stderr

  doc = sys.modules['__main__'].__doc__
  if not doc:
    doc = '\nUSAGE: %s [flags]\n' % sys.argv[0]
    doc = flags.text_wrap(doc, indent='       ', firstline_indent='')
  else:
    # Replace all '%s' with sys.argv[0], and all '%%' with '%'.
    num_specifiers = doc.count('%') - 2 * doc.count('%%')
    try:
      doc %= (sys.argv[0],) * num_specifiers
    except (OverflowError, TypeError, ValueError):
      # Just display the docstring as-is.
      pass
  if shorthelp:
    flag_str = FLAGS.main_module_help()
  else:
    flag_str = str(FLAGS)
  try:
    stdfile.write(doc)
    if flag_str:
      stdfile.write('\nflags:\n')
      stdfile.write(flag_str)
    stdfile.write('\n')
    if detailed_error is not None:
      stdfile.write('\n%s\n' % detailed_error)
  except IOError as e:
    # We avoid printing a huge backtrace if we get EPIPE, because
    # "foo.par --help | less" is a frequent use case.
    if e.errno != errno.EPIPE:
      raise
  if exitcode is not None:
    sys.exit(exitcode)
Ejemplo n.º 3
0
def usage(shorthelp=False, writeto_stdout=False, detailed_error=None,
          exitcode=None):
    """Writes __main__'s docstring to stderr with some help text.
    Args:
      shorthelp: bool, if True, prints only flags from the main module,
          rather than all flags.
      writeto_stdout: bool, if True, writes help message to stdout,
          rather than to stderr.
      detailed_error: str, additional detail about why usage info was presented.
      exitcode: optional integer, if set, exits with this status code after
          writing help.
    """
    if writeto_stdout:
        stdfile = sys.stdout
    else:
        stdfile = sys.stderr

    doc = sys.modules['__main__'].__doc__
    if not doc:
        doc = f'USAGE: python -m benchmarks.driver <exp> [flags]\n\n'
        doc = flags.text_wrap(doc, indent='       ', firstline_indent='')
    if shorthelp:
        flag_str = FLAGS.main_module_help()
    else:
        flag_str = str(FLAGS)
    try:
        stdfile.write(doc)
        if flag_str:
            stdfile.write('\nflags:\n')
            stdfile.write(flag_str)
        stdfile.write('\n')
        if detailed_error is not None:
            stdfile.write('\n%s\n' % detailed_error)
    except IOError as e:
        # We avoid printing a huge backtrace if we get EPIPE, because
        # "foo.par --help | less" is a frequent use case.
        if e.errno != errno.EPIPE:
            raise
    if exitcode is not None:
        sys.exit(exitcode)
def ProcessError(
        err,
        name='unknown',
        message_prefix='You have encountered a bug in the BigQuery CLI.'):
    """Translate an error message into some printing and a return code."""

    if isinstance(err, SystemExit):
        return err.code  # sys.exit called somewhere, hopefully intentionally.

    response = []
    retcode = 1

    (etype, value, tb) = sys.exc_info()
    trace = ''.join(traceback.format_exception(etype, value, tb))
    # pragma pylint: disable=line-too-long
    contact_us_msg = (
        'Please file a bug report in our '
        'public '
        'issue tracker:\n'
        '  https://issuetracker.google.com/issues/new?component=187149&template=0\n'
        'Please include a brief description of '
        'the steps that led to this issue, as well as '
        'any rows that can be made public from '
        'the following information: \n\n')
    platform_str = ':'.join([
        platform.python_implementation(),
        platform.python_version(),
        platform.platform()
    ])
    error_details = textwrap.dedent("""\
     ========================================
     == Platform ==
       %s
     == bq version ==
       %s
     == Command line ==
       %s
     == UTC timestamp ==
       %s
     == Error trace ==
     %s
     ========================================
     """) % (platform_str, six.ensure_str(VERSION_NUMBER), [
        six.ensure_str(item) for item in sys.argv
    ], time.strftime('%Y-%m-%d %H:%M:%S',
                     time.gmtime()), six.ensure_str(trace))

    codecs.register_error('strict', codecs.replace_errors)
    message = bigquery_client.EncodeForPrinting(err)
    if isinstance(err, (bigquery_client.BigqueryNotFoundError,
                        bigquery_client.BigqueryDuplicateError)):
        response.append('BigQuery error in %s operation: %s' % (name, message))
        retcode = 2
    elif isinstance(err, bigquery_client.BigqueryTermsOfServiceError):
        response.append(str(err) + '\n')
        response.append(_BIGQUERY_TOS_MESSAGE)
    elif isinstance(err, bigquery_client.BigqueryInvalidQueryError):
        response.append('Error in query string: %s' % (message, ))
    elif (isinstance(err, bigquery_client.BigqueryError)
          and not isinstance(err, bigquery_client.BigqueryInterfaceError)):
        response.append('BigQuery error in %s operation: %s' % (name, message))
    elif isinstance(err, (app.UsageError, TypeError)):
        response.append(message)
    elif (isinstance(err, SyntaxError)
          or isinstance(err, bigquery_client.BigquerySchemaError)):
        response.append('Invalid input: %s' % (message, ))
    elif isinstance(err, flags.Error):
        response.append('Error parsing command: %s' % (message, ))
    elif isinstance(err, KeyboardInterrupt):
        response.append('')
    else:  # pylint: disable=broad-except
        # Errors with traceback information are printed here.
        # The traceback module has nicely formatted the error trace
        # for us, so we don't want to undo that via TextWrap.
        if isinstance(err, bigquery_client.BigqueryInterfaceError):
            message_prefix = (
                'Bigquery service returned an invalid reply in %s operation: %s.'
                '\n\n'
                'Please make sure you are using the latest version '
                'of the bq tool and try again. '
                'If this problem persists, you may have encountered a bug in the '
                'bigquery client.' % (name, message))
        elif isinstance(err, oauth2client_4_0.client.Error):
            message_prefix = (
                'Authorization error. This may be a network connection problem, '
                'so please try again. If this problem persists, the credentials '
                'may be corrupt. Try deleting and re-creating your credentials. '
                'You can delete your credentials using '
                '"bq init --delete_credentials".'
                '\n\n'
                'If this problem still occurs, you may have encountered a bug '
                'in the bigquery client.')
        elif (isinstance(err, six.moves.http_client.HTTPException)
              or isinstance(err, googleapiclient.errors.Error)
              or isinstance(err, httplib2.HttpLib2Error)):
            message_prefix = (
                'Network connection problem encountered, please try again.'
                '\n\n'
                'If this problem persists, you may have encountered a bug in the '
                'bigquery client.')

        message = message_prefix + ' ' + contact_us_msg
        wrap_error_message = True
        if wrap_error_message:
            message = flags.text_wrap(message)
        print(message)
        print(error_details)
        response.append('Unexpected exception in %s operation: %s' %
                        (name, message))

    response_message = '\n'.join(response)
    wrap_error_message = True
    if wrap_error_message:
        response_message = flags.text_wrap(response_message)
    print(response_message)
    return retcode
Ejemplo n.º 5
0
def AppcommandsUsage(shorthelp=0,
                     writeto_stdout=0,
                     detailed_error=None,
                     exitcode=None,
                     show_cmd=None,
                     show_global_flags=False):
    """Output usage or help information.

  Extracts the __doc__ string from the __main__ module and writes it to
  stderr. If that string contains a '%s' then that is replaced by the command
  pathname. Otherwise a default usage string is being generated.

  The output varies depending on the following:
  - FLAGS.help
  - FLAGS.helpshort
  - show_cmd
  - show_global_flags

  Args:
    shorthelp:      print only command and main module flags, rather than all.
    writeto_stdout: write help message to stdout, rather than to stderr.
    detailed_error: additional details about why usage info was presented.
    exitcode:       if set, exit with this status code after writing help.
    show_cmd:       show help for this command only (name of command).
    show_global_flags: show help for global flags.

  Raises:
    SystemExit: to indicate exiting the program.
  """
    if writeto_stdout:
        stdfile = sys.stdout
    else:
        stdfile = sys.stderr

    prefix = ''.rjust(GetMaxCommandLength() + 2)
    # Deal with header, containing general tool documentation
    doc = sys.modules['__main__'].__doc__
    if doc:
        help_msg = flags.doc_to_help(doc.replace('%s', GetAppBasename()))
        stdfile.write(flags.text_wrap(help_msg, flags.get_help_width()))
        stdfile.write('\n\n\n')
    if not doc or doc.find('%s') == -1:
        synopsis = 'USAGE: ' + GetSynopsis()
        stdfile.write(
            flags.text_wrap(synopsis, flags.get_help_width(), '       ', ''))
        stdfile.write('\n\n\n')
    # Special case just 'help' registered, that means run as 'tool --help'.
    if len(GetCommandList()) == 1:
        cmd_names = []
    else:
        cmd_names = [
            cmd_name for cmd_name, cmd in GetCommandList().items()
            if not cmd._hidden
        ]  # pylint: disable=protected-access
        cmd_names.sort()
        # Show list of commands
        if show_cmd is None or show_cmd == 'help':
            stdfile.write('Any of the following commands:\n')
            doc = ', '.join(cmd_names)
            stdfile.write(flags.text_wrap(doc, flags.get_help_width(), '  '))
            stdfile.write('\n\n\n')
        # Prepare list of commands to show help for
        if show_cmd is not None:
            cmd_names = [show_cmd]  # show only one command
        elif FLAGS.help or FLAGS.helpshort or shorthelp:
            cmd_names = []
    # Show the command help (none, one specific, or all)
    for name in cmd_names:
        command = GetCommandByName(name)
        try:
            cmd_help = command.CommandGetHelp(GetCommandArgv(),
                                              cmd_names=cmd_names)
        except Exception as error:  # pylint: disable=broad-except
            cmd_help = "Internal error for command '%s': %s." % (name,
                                                                 str(error))
        cmd_help = cmd_help.strip()
        all_names = ', '.join([command.CommandGetName()] +
                              (command.CommandGetAliases() or []))
        if len(all_names) + 1 >= len(prefix) or not cmd_help:
            # If command/alias list would reach over help block-indent
            # start the help block on a new line.
            stdfile.write(flags.text_wrap(all_names, flags.get_help_width()))
            stdfile.write('\n')
            prefix1 = prefix
        else:
            prefix1 = all_names.ljust(GetMaxCommandLength() + 2)
        if cmd_help:
            stdfile.write(
                flags.text_wrap(cmd_help, flags.get_help_width(), prefix,
                                prefix1))
            stdfile.write('\n\n')
        else:
            stdfile.write('\n')
        # When showing help for exactly one command we show its flags
        if len(cmd_names) == 1:
            # Need to register flags for command prior to be able to use them.
            # We do not register them globally so that they do not reappear.
            # pylint: disable=protected-access
            cmd_flags = command._command_flags
            if cmd_flags:
                stdfile.write('%sFlags for %s:\n' % (prefix, name))
                stdfile.write(cmd_flags.get_help(prefix + '  '))
                stdfile.write('\n\n')
    stdfile.write('\n')
    # Now show global flags as asked for
    if show_global_flags:
        stdfile.write('Global flags:\n')
        if shorthelp:
            stdfile.write(FLAGS.main_module_help())
        else:
            stdfile.write(FLAGS.get_help())
        stdfile.write('\n')
    else:
        stdfile.write("Run '%s --help' to get help for global flags." %
                      GetAppBasename())
    stdfile.write('\n%s\n' % _UsageFooter(detailed_error, cmd_names))
    if exitcode is not None:
        sys.exit(exitcode)
    def test_text_wrap(self):
        """Test that wrapping works as expected.

    Also tests that it is using global flags._help_width by default.
    """
        default_help_width = _helpers._DEFAULT_HELP_WIDTH
        _helpers._DEFAULT_HELP_WIDTH = 10

        # Generate a string with length 40, no spaces
        text = ''
        expect = []
        for n in range(4):
            line = str(n)
            line += '123456789'
            text += line
            expect.append(line)

        # Verify we still break
        wrapped = flags.text_wrap(text).split('\n')
        self.assertEqual(4, len(wrapped))
        self.assertEqual(expect, wrapped)

        wrapped = flags.text_wrap(text, 80).split('\n')
        self.assertEqual(1, len(wrapped))
        self.assertEqual([text], wrapped)

        # Normal case, breaking at word boundaries and rewriting new lines
        input_value = 'a b c d e f g h'
        expect = {
            1: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'],
            2: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'],
            3: ['a b', 'c d', 'e f', 'g h'],
            4: ['a b', 'c d', 'e f', 'g h'],
            5: ['a b c', 'd e f', 'g h'],
            6: ['a b c', 'd e f', 'g h'],
            7: ['a b c d', 'e f g h'],
            8: ['a b c d', 'e f g h'],
            9: ['a b c d e', 'f g h'],
            10: ['a b c d e', 'f g h'],
            11: ['a b c d e f', 'g h'],
            12: ['a b c d e f', 'g h'],
            13: ['a b c d e f g', 'h'],
            14: ['a b c d e f g', 'h'],
            15: ['a b c d e f g h']
        }
        for width, exp in expect.items():
            self.assertEqual(exp,
                             flags.text_wrap(input_value, width).split('\n'))

        # We turn lines with only whitespace into empty lines
        # We strip from the right up to the first new line
        self.assertEqual('', flags.text_wrap('  '))
        self.assertEqual('\n', flags.text_wrap('  \n  '))
        self.assertEqual('\n', flags.text_wrap('\n\n'))
        self.assertEqual('\n\n', flags.text_wrap('\n\n\n'))
        self.assertEqual('\n', flags.text_wrap('\n '))
        self.assertEqual('a\n\nb', flags.text_wrap('a\n  \nb'))
        self.assertEqual('a\n\n\nb', flags.text_wrap('a\n  \n  \nb'))
        self.assertEqual('a\nb', flags.text_wrap('  a\nb  '))
        self.assertEqual('\na\nb', flags.text_wrap('\na\nb\n'))
        self.assertEqual('\na\nb\n', flags.text_wrap('  \na\nb\n  '))
        self.assertEqual('\na\nb\n', flags.text_wrap('  \na\nb\n\n'))

        # Double newline.
        self.assertEqual('a\n\nb', flags.text_wrap(' a\n\n b'))

        # We respect prefix
        self.assertEqual(' a\n b\n c', flags.text_wrap('a\nb\nc', 80, ' '))
        self.assertEqual('a\n b\n c', flags.text_wrap('a\nb\nc', 80, ' ', ''))

        # tabs
        self.assertEqual('a\n b   c', flags.text_wrap('a\nb\tc', 80, ' ', ''))
        self.assertEqual('a\n bb  c', flags.text_wrap('a\nbb\tc', 80, ' ', ''))
        self.assertEqual('a\n bbb c', flags.text_wrap('a\nbbb\tc', 80, ' ',
                                                      ''))
        self.assertEqual('a\n bbbb    c',
                         flags.text_wrap('a\nbbbb\tc', 80, ' ', ''))
        self.assertEqual('a\n b\n c\n d',
                         flags.text_wrap('a\nb\tc\td', 3, ' ', ''))
        self.assertEqual('a\n b\n c\n d',
                         flags.text_wrap('a\nb\tc\td', 4, ' ', ''))
        self.assertEqual('a\n b\n c\n d',
                         flags.text_wrap('a\nb\tc\td', 5, ' ', ''))
        self.assertEqual('a\n b   c\n d',
                         flags.text_wrap('a\nb\tc\td', 6, ' ', ''))
        self.assertEqual('a\n b   c\n d',
                         flags.text_wrap('a\nb\tc\td', 7, ' ', ''))
        self.assertEqual('a\n b   c\n d',
                         flags.text_wrap('a\nb\tc\td', 8, ' ', ''))
        self.assertEqual('a\n b   c\n d',
                         flags.text_wrap('a\nb\tc\td', 9, ' ', ''))
        self.assertEqual('a\n b   c   d',
                         flags.text_wrap('a\nb\tc\td', 10, ' ', ''))

        # multiple tabs
        self.assertEqual('a       c', flags.text_wrap('a\t\tc', 80, ' ', ''))

        _helpers._DEFAULT_HELP_WIDTH = default_help_width  # restore