Example #1
0
    def __call__(self, parser, namespace, values, option_string=None):
      """Render a help document according to the style in values.

      Args:
        parser: The ArgParse object.
        namespace: The ArgParse namespace.
        values: The --document flag ArgDict() value:
          style=STYLE
            The output style. Must be specified.
          title=DOCUMENT TITLE
            The document title.
          notes=SENTENCES
            Inserts SENTENCES into the document NOTES section.
        option_string: The ArgParse flag string.

      Raises:
        parser_errors.ArgumentError: For unknown flag value attribute name.
      """
      base.LogCommand(parser.prog, namespace)
      if default_style:
        # --help
        metrics.Loaded()
      style = default_style
      notes = None
      title = None

      for attributes in values:
        for name, value in six.iteritems(attributes):
          if name == 'notes':
            notes = value
          elif name == 'style':
            style = value
          elif name == 'title':
            title = value
          else:
            raise parser_errors.ArgumentError(
                'Unknown document attribute [{0}]'.format(name))

      if title is None:
        title = command.dotted_name

      metrics.Help(command.dotted_name, style)
      # '--help' is set by the --help flag, the others by gcloud <style> ... .
      if style in ('--help', 'help', 'topic'):
        style = 'text'
      md = io.StringIO(markdown.Markdown(command))
      out = (io.StringIO() if console_io.IsInteractive(output=True)
             else None)

      if style == 'linter':
        meta_data = GetCommandMetaData(command)
      else:
        meta_data = None
      render_document.RenderDocument(style, md, out=out or log.out, notes=notes,
                                     title=title, command_metadata=meta_data)
      metrics.Ran()
      if out:
        console_io.More(out.getvalue())

      sys.exit(0)
Example #2
0
 def Run(self, test_file_path, path, style, suffix, exception=None):
     file_base = '_'.join(path)
     markdown_path = self.GetTestdataPath(test_file_path,
                                          file_base + '.src.md')
     try:
         markdown_data = console_attr.Decode(
             pkg_resources.GetResourceFromFile(markdown_path))
     except IOError:
         file_base = '_'.join(['gcloud'] + path)
         markdown_path = self.GetTestdataPath(test_file_path, 'markdown',
                                              file_base + '.md')
         markdown_data = console_attr.Decode(
             pkg_resources.GetResourceFromFile(markdown_path))
     f = io.StringIO(markdown_data)
     try:
         e = None
         render_document.RenderDocument(style,
                                        fin=f,
                                        out=log.out,
                                        notes='A special note.',
                                        title=' '.join(['gcloud'] + path))
     except Exception as e:  # pylint: disable=broad-except
         e = e.message
     if e != exception:
         if not exception:
             self.fail('Exception not expected but [%s] caught.' % e)
         else:
             self.fail('Exception [%s] expected but caught [%s].' %
                       (exception, e))
     self.AssertOutputIsGolden(test_file_path, file_base + suffix)
     self.ClearOutput()
Example #3
0
 def Run(self,
         style,
         markdown,
         expected=None,
         exception=None,
         notes=None,
         title=None,
         command_metadata=None):
     fin = io.StringIO(markdown)
     err = None
     try:
         render_document.RenderDocument(style=style,
                                        fin=fin,
                                        notes=notes,
                                        title=title,
                                        command_metadata=command_metadata)
     except Exception as e:  # pylint: disable=broad-except
         err = six.text_type(e)
     if err != exception:
         if not exception:
             self.fail('Exception not expected but [%s] caught.' % err)
         else:
             self.fail('Exception [%s] expected but caught [%s].' %
                       (exception, err))
     actual = self.GetOutput()
     self.assertMultiLineEqual(expected, actual)
     self.ClearOutput()
  def Visit(self, node, parent, is_group):
    """Renders document file for each node in the CLI tree.

    Args:
      node: group/command CommandCommon info.
      parent: The parent Visit() return value, None at the top level.
      is_group: True if node is a group, otherwise its is a command.

    Returns:
      The parent value, ignored here.
    """

    if self._style == 'linter':
      meta_data = actions.GetCommandMetaData(node)
    else:
      meta_data = None
    command = node.GetPath()
    path = os.path.join(self._directory, '_'.join(command)) + self._suffix
    with files.FileWriter(path) as f:
      md = markdown.Markdown(node)
      render_document.RenderDocument(style=self._style,
                                     title=' '.join(command),
                                     fin=io.StringIO(md),
                                     out=f,
                                     command_metadata=meta_data)
    return parent
Example #5
0
def _ProcessResult(command, terms_to_locations):
    """Helper function to create help text resource for listing results.

  Args:
    command: dict, json representation of command.
    terms_to_locations: {str: str}, lookup from terms to where they were found.

  Returns:
    A modified copy of the json command with a summary, and with the dict
        of subcommands replaced with just a list of available subcommands.
  """
    new_command = copy.deepcopy(command)
    if lookup.COMMANDS in new_command.keys():
        new_command[lookup.COMMANDS] = sorted(
            [c[lookup.NAME] for c in new_command[lookup.COMMANDS].values()])
    summary = search_util.GetSummary(command, terms_to_locations)
    # Render the summary for console printing, but ignoring console width.
    md = StringIO.StringIO(summary)
    rendered_summary = StringIO.StringIO()
    render_document.RenderDocument('text',
                                   md,
                                   out=rendered_summary,
                                   width=len(summary))
    # Remove indents and blank lines so summary can be easily
    # printed in a table.
    new_command[lookup.SUMMARY] = '\n'.join([
        l.lstrip() for l in rendered_summary.getvalue().splitlines()
        if l.lstrip()
    ])
    return new_command
    def Visit(self, node, parent, is_group):
        """Renders a help text doc for each node in the CLI tree.

    Args:
      node: group/command CommandCommon info.
      parent: The parent Visit() return value, None at the top level.
      is_group: True if node is a group, otherwise its is a command.

    Returns:
      The parent value, ignored here.
    """
        # Set up the destination dir for this level.
        command = node.GetPath()
        if is_group:
            directory = os.path.join(self._directory, *command[1:])
            files.MakeDir(directory, mode=0755)
        else:
            directory = os.path.join(self._directory, *command[1:-1])

        # Render the help text document.
        path = os.path.join(directory, 'GROUP' if is_group else command[-1])
        with open(path, 'w') as f:
            md = markdown.Markdown(node)
            render_document.RenderDocument(style='text',
                                           fin=cStringIO.StringIO(md),
                                           out=f)
        return parent
Example #7
0
def SummaryTransform(r):
    """A resource transform function to summarize a command search result.

  Uses the "results" attribute of the command to build a summary that includes
  snippets of the help text of the command that include the searched terms.
  Occurrences of the search term will be stylized.

  Args:
    r: a json representation of a command.

  Returns:
    str, a summary of the command.
  """
    summary = GetSummary(r, r[lookup.RESULTS])
    md = io.StringIO(summary)
    rendered_summary = io.StringIO()
    # Render summary as markdown, ignoring console width.
    render_document.RenderDocument(
        'text',
        md,
        out=rendered_summary,
        # Increase length in case of indentation.
        width=len(summary) * 2)
    final_summary = '\n'.join([
        l.lstrip() for l in rendered_summary.getvalue().splitlines()
        if l.lstrip()
    ])
    return final_summary
Example #8
0
 def Run(self, args):
     if not args.quiet:
         render_document.RenderDocument(fin=StringIO.StringIO(_SPLASH))
     config = configuration.Config(context='gcloud ')
     application.main(cli=self._cli_power_users_only,
                      args=args,
                      config=config)
Example #9
0
        def __call__(self, parser, namespace, values, option_string=None):
            """Render a help document according to the style in values.

      Args:
        parser: The ArgParse object.
        namespace: The ArgParse namespace.
        values: The --document flag ArgDict() value:
          style=STYLE
            The output style. Must be specified.
          title=DOCUMENT TITLE
            The document title.
          notes=SENTENCES
            Inserts SENTENCES into the document NOTES section.
        option_string: The ArgParse flag string.

      Raises:
        ArgumentTypeError: For unknown flag value attribute name.
      """
            if default_style:
                # --help
                metrics.Loaded()
            style = default_style
            notes = None
            title = None

            for attributes in values:
                for name, value in attributes.iteritems():
                    if name == 'notes':
                        notes = value
                    elif name == 'style':
                        style = value
                    elif name == 'title':
                        title = value
                    else:
                        raise argparse.ArgumentTypeError(
                            'Unknown document attribute [{}]'.format(name))

            if title is None:
                title = command.dotted_name

            metrics.Help(command.dotted_name, style)
            # 'help' is set by the help command, '--help' by the --help flag.
            if style in ('--help', 'help'):
                style = 'text'
            md = cStringIO.StringIO(markdown.Markdown(command))
            out = (cStringIO.StringIO() if console_io.IsInteractive(
                output=True) else None)
            render_document.RenderDocument(style,
                                           md,
                                           out=out,
                                           notes=notes,
                                           title=title)
            metrics.Ran()
            if out:
                console_io.More(out.getvalue())

            sys.exit(0)
Example #10
0
 def Run(self, args):
     if not args.quiet:
         render_document.RenderDocument(fin=StringIO.StringIO(_SPLASH))
     config = configuration.Config(
         context=args.context,
         hidden=args.hidden,
         prompt=args.prompt,
         suggest=args.suggest,
     )
     application.main(args=args, config=config)
def PrintReleaseNotesDiff(release_notes_url, current_version, latest_version):
    """Prints the release notes diff based on your current version.

  If any of the arguments are None, a generic message will be printed telling
  the user to go to the web to view the release notes.  If the release_notes_url
  is also None, it will print the developers site page for the SDK.

  Args:
    release_notes_url: str, The URL to download the latest release notes from.
    current_version: str, The current version of the SDK you have installed.
    latest_version: str, The version you are about to update to.
  """
    if release_notes_url and current_version and latest_version:
        notes = ReleaseNotes.FromURL(release_notes_url)
        if notes:
            release_notes_diff = notes.Diff(latest_version, current_version)
        else:
            release_notes_diff = None
    else:
        release_notes_diff = None

    if not release_notes_diff:
        # We failed to print the release notes.  Send people to either the release
        # notes if we have a link, or just to the developers page if we don't.
        url = (release_notes_url if release_notes_url else
               config.INSTALLATION_CONFIG.documentation_url)
        log.status.write(
            'For the latest full release notes, please visit:\n  {0}\n\n'.
            format(url))
        return

    if len(release_notes_diff) > ReleaseNotes.MAX_DIFF:
        log.status.Print("""\
A lot has changed since your last upgrade.  For the latest full release notes,
please visit:
  {0}
""".format(release_notes_url))
        return

    log.status.Print("""\
The following release notes are new in this upgrade.
Please read carefully for information about new features, breaking changes,
and bugs fixed.  The latest full release notes can be viewed at:
  {0}
""".format(release_notes_url))

    full_text = StringIO.StringIO()
    for _, text in release_notes_diff:
        full_text.write(text)
        full_text.write('\n')

    full_text.seek(0)
    render_document.RenderDocument('text', full_text, log.status)
    log.status.Print()
Example #12
0
 def Run(self, args):
     if not args.quiet:
         render_document.RenderDocument(fin=io.StringIO(_SPLASH))
     config = configuration.Config(
         context=args.context,
         debug=args.debug,
         hidden=args.hidden,
         prompt=args.prompt,
         suggest=args.suggest,
     )
     _AppendMetricsEnvironment('interactive_shell')
     application.main(args=args, config=config)
def GenerateMarkdownFromCliTree(command, root, directory):
    """DFS on the command subtree, markdown generated at each level."""
    path = os.path.join(directory, '_'.join(
        command[cli_tree.LOOKUP_PATH])) + '.md'
    with open(path, 'w') as f:
        md = cli_tree_markdown.Markdown(command, root)
        render_document.RenderDocument(style='markdown',
                                       title=' '.join(
                                           command[cli_tree.LOOKUP_PATH]),
                                       fin=io.StringIO(md),
                                       out=f)
    for cmd in command[cli_tree.LOOKUP_COMMANDS].values():
        GenerateMarkdownFromCliTree(cmd, root, directory)
Example #14
0
 def Run(self, args):
   # TODO(b/69033748): drop this workaround when the trees are packaged
   if args.update_cli_trees:
     generate_cli_trees.UpdateCliTrees(
         warn_on_exceptions=True, verbose=not args.quiet)
   if not args.quiet:
     render_document.RenderDocument(fin=io.StringIO(_SPLASH))
   config = configuration.Config(
       context=args.context,
       hidden=args.hidden,
       prompt=args.prompt,
       suggest=args.suggest,
   )
   application.main(args=args, config=config)
Example #15
0
def SummaryTransform(r):
  """Get summary of command with desired terms included."""
  summary = GetSummary(r, r[lookup.RESULTS])
  md = io.StringIO(summary)
  rendered_summary = io.StringIO()
  # Render summary as markdown, ignoring console width.
  render_document.RenderDocument('text',
                                 md,
                                 out=rendered_summary,
                                 # Increase length in case of indentation.
                                 width=len(summary) * 2)
  final_summary = '\n'.join(
      [l.lstrip() for l in rendered_summary.getvalue().splitlines()
       if l.lstrip()])
  return final_summary
Example #16
0
 def Run(self, style, term, markdown, expected=None, exception=None):
   os.environ['LC_ALL'] = 'en_US.UTF-8'
   os.environ['TERM'] = term
   fin = io.StringIO(markdown)
   console_attr.GetConsoleAttr(reset=True, encoding='utf-8')
   try:
     e = None
     render_document.RenderDocument(style=style, fin=fin, out=log.out)
   except Exception as e:  # pylint: disable=broad-except
     e = str(e)
   if e != exception:
     if not exception:
       self.fail('Exception not expected but [%s] caught.' % e)
     else:
       self.fail('Exception [%s] expected but caught [%s].' % (exception, e))
   actual = self.GetOutput()
   self.maxDiff = None
   self.assertMultiLineEqual(expected, actual)
   self.ClearOutput()
    def Visit(self, node, parent, is_group):
        """Renders a manpage doc for each node in the CLI tree.

    Args:
      node: group/command CommandCommon info.
      parent: The parent Visit() return value, None at the top level.
      is_group: True if node is a group, otherwise its is a command.

    Returns:
      The parent value, ignored here.
    """
        command = node.GetPath()
        path = os.path.join(self._directory, '_'.join(command)) + '.1'
        with open(path, 'w') as f:
            md = markdown.Markdown(node)
            render_document.RenderDocument(style='man',
                                           title=' '.join(command),
                                           fin=cStringIO.StringIO(md),
                                           out=f)
        return parent
 def Run(self, args):
   with open(args.md_file, 'r') as f:
     render_document.RenderDocument(args.style, f, sys.stdout)
    def Visit(self, node, parent, is_group):
        """Updates the TOC and Renders a DevSite doc for each node in the CLI tree.

    Args:
      node: group/command CommandCommon info.
      parent: The parent Visit() return value, None at the top level.
      is_group: True if node is a group, otherwise its is a command.

    Returns:
      The parent value, ignored here.
    """
        def _UpdateTOC():
            """Updates the DevSIte TOC."""
            depth = len(command) - 1
            if not depth:
                return
            if depth == 1:
                if self._toc_main:
                    # Close the current main group toc if needed.
                    self._toc_main.close()
                # Create a new main group toc.
                toc_path = os.path.join(directory, self._TOC)
                toc = open(toc_path, 'w')
                self._toc_main = toc
                title = ' '.join(command)
                toc.write('toc:\n')
                toc.write('- title: "%s"\n' % title)
                toc.write('  path: %s\n' %
                          '/'.join([self._REFERENCE] + command[1:]))
                toc.write('  section:\n')
                toc = self._toc_root
                indent = '  '
                if is_group:
                    toc.write('%s- include: %s\n' %
                              (indent, '/'.join([self._REFERENCE] +
                                                command[1:] + [self._TOC])))
                    return
            else:
                toc = self._toc_main
                indent = '  ' * (depth - 1)
                title = command[-1]
            toc.write('%s- title: "%s"\n' % (indent, title))
            toc.write('%s  path: %s\n' %
                      (indent, '/'.join([self._REFERENCE] + command[1:])))
            if is_group:
                toc.write('%s  section:\n' % indent)

        # Set up the destination dir for this level.
        command = node.GetPath()
        if is_group:
            directory = os.path.join(self._directory, *command[1:])
            files.MakeDir(directory, mode=0755)
        else:
            directory = os.path.join(self._directory, *command[1:-1])

        # Render the DevSite document.
        path = os.path.join(directory,
                            'index' if is_group else command[-1]) + '.html'
        with open(path, 'w') as f:
            md = markdown.Markdown(node)
            render_document.RenderDocument(style='devsite',
                                           title=' '.join(command),
                                           fin=cStringIO.StringIO(md),
                                           out=f)
        _UpdateTOC()
        return parent
 def Run(self, args):
     data = console_io.ReadFromFileOrStdin(args.md_file, binary=False)
     with io.StringIO(data) as f:
         render_document.RenderDocument(args.style, f, sys.stdout)