Пример #1
0
    def _generate_nodes(self, name, command, parent, nested, commands=None):
        """Generate the relevant Sphinx nodes.

        Format a `click.Group` or `click.Command`.

        :param name: Name of command, as used on the command line
        :param command: Instance of `click.Group` or `click.Command`
        :param parent: Instance of `click.Context`, or None
        :param nested: The granularity of subcommand details.
        :param commands: Display only listed commands or skip the section if
            empty
        :returns: A list of nested docutil nodes
        """
        ctx = click.Context(command, info_name=name, parent=parent)

        if CLICK_VERSION >= (7, 0) and command.hidden:
            return []

        # Title

        section = nodes.section(
            '',
            nodes.title(text=name),
            ids=[nodes.make_id(ctx.command_path)],
            names=[nodes.fully_normalize_name(ctx.command_path)],
        )

        # Summary

        source_name = ctx.command_path
        result = statemachine.ViewList()

        lines = _format_command(ctx, nested, commands)
        for line in lines:
            LOG.debug(line)
            result.append(line, source_name)

        sphinx_nodes.nested_parse_with_titles(self.state, result, section)

        # Subcommands

        if nested == NESTED_FULL:
            commands = _filter_commands(ctx, commands)
            for command in commands:
                section.extend(
                    self._generate_nodes(command.name, command, ctx, nested))

        return [section]
Пример #2
0
    def run(self):
        env = self.state.document.settings.env
        app = env.app

        config_file = self.options.get('config-file')

        # if the config_file option was not defined, attempt to reuse the
        # 'oslo_policy.sphinxpolicygen' extension's setting
        if not config_file and hasattr(env.config,
                                       'policy_generator_config_file'):
            config_file = env.config.policy_generator_config_file

        # If we are given a file that isn't an absolute path, look for it
        # in the source directory if it doesn't exist.
        candidates = [
            config_file,
            os.path.join(
                app.srcdir,
                config_file,
            ),
        ]
        for c in candidates:
            if os.path.isfile(c):
                config_path = c
                break
        else:
            raise ValueError('could not find config file in: %s' %
                             str(candidates))

        self.info('loading config file %s' % config_path)

        conf = cfg.ConfigOpts()
        opts = generator.GENERATOR_OPTS + generator.RULE_OPTS
        conf.register_cli_opts(opts)
        conf.register_opts(opts)
        conf(args=['--config-file', config_path], )
        namespaces = conf.namespace[:]

        result = statemachine.ViewList()
        source_name = '<' + __name__ + '>'
        for line in _format_policy(namespaces):
            result.append(line, source_name)

        node = nodes.section()
        node.document = self.state.document
        nested_parse_with_titles(self.state, result, node)

        return node.children
Пример #3
0
    def run(self):
        self.result = sm.ViewList()

        cls_path = self.arguments[0]

        try:
            cls = importlib.import_module(cls_path)
        except Exception as exc:
            raise self.error(exc)

        self.add_class_docstring(cls)

        node = nodes.paragraph()
        node.document = self.state.document
        self.state.nested_parse(self.result, 0, node)
        return node.children
Пример #4
0
    def run(self):
        all_projects = _get_project_data()

        # Build the view of the data to be parsed for rendering.
        result = statemachine.ViewList()
        for project_name in sorted(all_projects.keys()):
            project_info = all_projects[project_name]
            for line in _project_to_rst(project_name, project_info):
                result.append(line, '<' + __name__ + '>')

        # Parse what we have into a new section.
        node = nodes.section()
        node.document = self.state.document
        nested_parse_with_titles(self.state, result, node)

        return node.children
    def run(self):
        # fill the content code with the options from the directive
        path = self.options['path']
        section = self.options['section']

        # Parse the ini file and make any special tables
        ini = read_ini(path)
        tables = []
        for ts, inputs, outputs in timing_entries(ini, section):
            for name, val in inputs.items():
                if name == "TABLE_ADDRESS":
                    tables = self.make_long_tables(ini, section, path)
                elif name == "TABLE_DATA":
                    tables = self.make_all_seq_tables(ini, section)
            for name, val in outputs.items():
                # TODO: PCAP_DATA
                if name == "DATA":
                    tables = self.make_pcap_table(ini, section)

        plot_content = [
            "from common.python.timing_plot import make_timing_plot",
            "make_timing_plot('%s', '%s')" % (path, section)
        ]

        # override include_input so we get the result
        old_insert_input = self.state_machine.insert_input
        self.state_machine.insert_input = self.catch_insert_input

        plot_directive.plot_directive(self.name, self.arguments, self.options,
                                      plot_content, self.lineno,
                                      self.content_offset, self.block_text,
                                      self.state, self.state_machine)

        self.state_machine.insert_input = old_insert_input
        plot_node = sequence_plot_node()
        node = sequence_plot_node()

        # do a nested parse of the lines
        self.state.nested_parse(
            statemachine.ViewList(initlist=self.total_lines),
            self.content_offset, plot_node)

        # add the directives
        node.append(plot_node)
        for table_node in tables:
            node.append(table_node)
        return [node]
Пример #6
0
    def _generate_nodes(self, title, command_name, command_class,
                        ignored_opts):
        """Generate the relevant Sphinx nodes.

        This is a little funky. Parts of this use raw docutils nodes while
        other parts use reStructuredText and nested parsing. The reason for
        this is simple: it avoids us having to reinvent the wheel. While raw
        docutils nodes are helpful for the simpler elements of the output,
        they don't provide an easy way to use Sphinx's own directives, such as
        the 'option' directive. Refer to [1] for more information.

        [1] http://www.sphinx-doc.org/en/stable/extdev/markupapi.html

        :param title: Title of command
        :param command_name: Name of command, as used on the command line
        :param command_class: Subclass of :py:class:`cliff.command.Command`
        :param prefix: Prefix to apply before command, if any
        :param ignored_opts: A list of options to exclude from output, if any
        :returns: A list of nested docutil nodes
        """
        command = command_class(None, None)
        parser = command.get_parser(command_name)
        ignored_opts = ignored_opts or []

        # Drop the automatically-added help action
        for action in list(parser._actions):
            for option_string in action.option_strings:
                if option_string in ignored_opts:
                    del parser._actions[parser._actions.index(action)]
                    break

        section = nodes.section('',
                                nodes.title(text=title),
                                ids=[nodes.make_id(title)],
                                names=[nodes.fully_normalize_name(title)])

        source_name = '<{}>'.format(command.__class__.__name__)
        result = statemachine.ViewList()

        for line in _format_parser(parser):
            result.append(line, source_name)

        self.state.nested_parse(result, 0, section)

        return [section]
Пример #7
0
    def _generate_nodes(self, name, command, parent=None, show_nested=False, link_commands_prefix=None):
        """Generate the relevant Sphinx nodes.

        Format a `click.Group` or `click.Command`.

        :param name: Name of command, as used on the command line
        :param command: Instance of `click.Group` or `click.Command`
        :param parent: Instance of `click.Context`, or None
        :param show_nested: Whether subcommands should be included in output
        :returns: A list of nested docutil nodes
        """
        ctx = click.Context(command, info_name=name, parent=parent)

        # Title

        section = nodes.section(
            '',
            nodes.title(text=name),
            ids=[nodes.make_id(ctx.command_path)],
            names=[nodes.fully_normalize_name(ctx.command_path)])

        # Summary

        source_name = ctx.command_path
        result = statemachine.ViewList()

        lines = _format_command(ctx, show_nested, link_commands_prefix)
        for line in lines:
            result.append(line, source_name)

        self.state.nested_parse(result, 0, section)

        # Subcommands

        if show_nested:
            commands = getattr(ctx.command, 'commands', {})
            for command_name, command_obj in sorted(commands.items()):
                section.extend(self._generate_nodes(
                    command_name,
                    command_obj,
                    ctx,
                    show_nested,
                    link_commands_prefix))

        return [section]
Пример #8
0
    def _generate_section(self,
                          name,
                          config,
                          cfg_section='default',
                          remove_sasbase=False):
        """Generate the relevant Sphinx nodes.

        Generates a section for the Tree datamodel.  Formats a tree section
        as a list-table directive.

        Parameters:
            name (str):
                The name of the config to be documented, e.g. 'sdsswork'
            config (dict):
                The tree dictionary of the loaded config environ
            cfg_section (str):
                The section of the config to load
            remove_sasbase (bool):
                If True, removes the SAS_BASE_DIR from the beginning of each path

        Returns:
            A section docutil node

        """

        # the source name
        source_name = name

        # Title
        section = nodes.section(
            '',
            nodes.title(text=cfg_section),
            ids=[nodes.make_id(cfg_section)],
            names=[nodes.fully_normalize_name(cfg_section)])

        # Summarize
        result = statemachine.ViewList()
        base = config['default']['filesystem'] if remove_sasbase else None
        lines = _format_command(cfg_section, config[cfg_section], base=base)
        for line in lines:
            result.append(line, source_name)

        self.state.nested_parse(result, 0, section)

        return [section]
Пример #9
0
def _nodes_from_rst(
    state: statemachine.State,
    rst_source: str,
) -> List[nodes.Node]:
    """Turn an RST string into a list of nodes.

    These nodes can be used in the document.
    """
    node = nodes.Element()
    node.document = state.document
    nested_parse_with_titles(
        state=state,
        content=statemachine.ViewList(
            statemachine.string2lines(rst_source),
            source='[towncrier-fragments]',
        ),
        node=node,
    )
    return node.children
Пример #10
0
def _nodes_from_rst(
    state: statemachine.State,
    rst_source: str,
) -> List[nodes.Node]:
    """Turn an RST string into a list of nodes.

    These nodes can be used in the document.
    """
    node = nodes.Element()
    node.document = state.document
    nested_parse_with_titles(
        state=state,
        content=statemachine.ViewList(
            statemachine.string2lines(rst_source),
            source="[ansible-navigator autogenerated]",
        ),
        node=node,
    )
    return node.children  # type: ignore
Пример #11
0
    def _generate_app_node(self, app, application_name):
        ignored_opts = self._get_ignored_opts()

        parser = app.parser

        self._drop_ignored_options(parser, ignored_opts)

        parser.prog = application_name

        source_name = '<{}>'.format(app.__class__.__name__)
        result = statemachine.ViewList()
        for line in _format_parser(parser):
            result.append(line, source_name)

        section = nodes.section()
        self.state.nested_parse(result, 0, section)

        # return [section.children]
        return section.children
Пример #12
0
    def _generate_nodes(self, title, command_name, command_class,
                        ignored_opts):
        """Generate the relevant Sphinx nodes.

        This doesn't bother using raw docutils nodes as they simply don't offer
        the power of directives, like Sphinx's 'option' directive. Instead, we
        generate reStructuredText and parse this in a nested context (to obtain
        correct header levels). Refer to [1] for more information.

        [1] http://www.sphinx-doc.org/en/stable/extdev/markupapi.html

        :param title: Title of command
        :param command_name: Name of command, as used on the command line
        :param command_class: Subclass of :py:class:`cliff.command.Command`
        :param prefix: Prefix to apply before command, if any
        :param ignored_opts: A list of options to exclude from output, if any
        :returns: A list of nested docutil nodes
        """
        command = command_class(None, None)
        parser = command.get_parser(command_name)
        ignored_opts = ignored_opts or []

        # Drop any ignored actions
        for action in list(parser._actions):
            for option_string in action.option_strings:
                if option_string in ignored_opts:
                    del parser._actions[parser._actions.index(action)]
                    break

        section = nodes.section('',
                                nodes.title(text=title),
                                ids=[nodes.make_id(title)],
                                names=[nodes.fully_normalize_name(title)])

        source_name = '<{}>'.format(command.__class__.__name__)
        result = statemachine.ViewList()

        for line in _format_parser(parser):
            result.append(line, source_name)

        self.state.nested_parse(result, 0, section)

        return [section]
Пример #13
0
    def run(self):
        tagname = ' '.join(self.content)
        LOG.info('building list of projects tagged %r' % tagname)
        if not tagname:
            error = self.state_machine.reporter.error(
                'No tagname in tagged-projects directive',
                nodes.literal_block(self.block_text, self.block_text),
                line=self.lineno)
            return [error]

        # Build the view of the data to be parsed for rendering.
        result = statemachine.ViewList()
        project_data = _projects_by_tag.get(tagname)
        source_name = '<' + __name__ + '>'
        if not project_data:
            result.append(
                '.. note:: No projects are using %s, yet.' % tagname,
                source_name,
            )
        else:
            team_deliverables = defaultdict(list)

            for team_name, deliverable in project_data:
                team = projects.slugify(team_name)
                if deliverable is None:
                    team_deliverables[team] = []
                else:
                    team_deliverables[team].append(deliverable)

            for team in sorted(team_deliverables, key=lambda x: x.lower()):
                line = '- :ref:`project-%s`%s %s' % (
                    team,
                    ':' if team_deliverables[team] else '',
                    ', '.join(team_deliverables[team]))
                result.append(line, source_name)

        # Parse what we have into a new section.
        node = nodes.section()
        node.document = self.state.document
        nested_parse_with_titles(self.state, result, node)

        return node.children
Пример #14
0
    def _generate_nodes(self,
                        name,
                        command,
                        parent=None,
                        show_nested=False,
                        commands=None):
        """Generate the relevant Sphinx nodes.

        Format a `click.Group` or `click.Command`.

        :param name: Name of command, as used on the command line
        :param command: Instance of `click.Group` or `click.Command`
        :param parent: Instance of `click.Context`, or None
        :param show_nested: Whether subcommands should be included in output
        :param commands: Display only listed commands or skip the section if
            empty
        :returns: A list of nested docutil nodes
        """
        node = nodes.Element()
        ctx = self._get_context(name, command, parent)

        # Summary

        source_name = ctx.command_path
        result = statemachine.ViewList()

        lines = _format_command(ctx, show_nested, commands)

        for line in lines:
            result.append(line, source_name)

        nested_parse_with_titles(self.state, result, node)

        # Subcommands
        if show_nested:
            commands = _filter_commands(ctx, commands)
            for command in commands:
                node.extend(
                    self._generate_nodes(command.name, command, ctx,
                                         show_nested))

        return node[:]
Пример #15
0
 def run(self):
     """Include the text in a `note` block and add a reference via
     nested parsing."""
     viewlist = statemachine.ViewList()
     viewlist.append(
         ".. note:: "
         "When new to *HydPy*, consider reading section "
         ":ref:`How to understand integration tests? "
         "<understand_integration_tests>` first.",
         "fakefile.rst",
         1,
     )
     node = docutils_nodes.section()
     node.document = self.state.document
     sphinx_nodes.nested_parse_with_titles(
         self.state,
         viewlist,
         node,
     )
     return node.children
Пример #16
0
    def _generate_nodes(self, snakefile, rules):
        """Generate Sphinx nodes from parsed snakefile"""

        section = nodes.section('',
                                nodes.title("thetitle"),
                                ids=[nodes.make_id(snakefile)],
                                names=[nodes.fully_normalize_name(snakefile)])

        result = statemachine.ViewList()

        for rule in rules:
            result.append(".. class:: {}".format(rule.name), snakefile)
            result.append("", snakefile)
            if rule.docstring:
                for line in rule.docstring.splitlines():
                    result.append("   " + line, snakefile)
                result.append("", snakefile)

        self.state.nested_parse(result, 0, section)

        return [section]
Пример #17
0
    def _generate_nodes(self, name, command, templates=None):
        """Generate the relevant Sphinx nodes.

        Generates a section for the Tree datamodel.  Formats a tree section
        as a list-table directive.

        Parameters:
            name (str):
                The name of the config to be documented, e.g. 'sdsswork'
            command (object):
                The loaded module
            templates (bool):
                If True, generate a section for the path templates

        Returns:
            A section docutil node

        """

        # the source name
        source_name = name

        # Title
        section = nodes.section('',
                                nodes.title(text=name),
                                ids=[nodes.make_id(name)],
                                names=[nodes.fully_normalize_name(name)])

        # Summarize
        result = statemachine.ViewList()

        if templates:
            lines = _format_templates(name, command, command.templates)

        for line in lines:
            result.append(line, source_name)

        self.state.nested_parse(result, 0, section)

        return [section]
Пример #18
0
    def run(self):
        self.env = self.state.document.settings.env

        command = load_module(self.arguments[0])

        if 'prog' in self.options:
            prog_name = self.options.get('prog')
        else:
            raise self.error(':prog: must be specified')

        # get options
        remove_sasbase = 'remove-sasbase' in self.options

        # get drs
        drs = self.options.get('drs')
        new, old = drs.replace(' ', '').split(',')

        # compute and format the changelog lines
        lines = command(new, old, remove_sas=remove_sasbase, to_list=True)
        title = lines[0]
        lines = lines[1:]
        lines = _format_changelog(lines)

        # the source name
        source_name = title

        # Title
        section = nodes.section(
            '',
            nodes.title(text=source_name),
            ids=[nodes.make_id(source_name)],
            names=[nodes.fully_normalize_name(source_name)])

        result = statemachine.ViewList()
        for line in lines:
            result.append(line, source_name)

        self.state.nested_parse(result, 0, section)

        return [section]
Пример #19
0
    def _generate_nodes(self, title, app, app_name, ignored_opts):
        """Generate the relevant Sphinx nodes.

        This is a little funky. Parts of this use raw docutils nodes while
        other parts use reStructuredText and nested parsing. The reason for
        this is simple: it avoids us having to reinvent the wheel. While raw
        docutils nodes are helpful for the simpler elements of the output,
        they don't provide an easy way to use Sphinx's own directives, such as
        the 'option' directive. Refer to [1] for more information.

        [1] http://www.sphinx-doc.org/en/stable/extdev/markupapi.html

        :param title: Title of command
        :param app: Subclass of :py:class`cliff.app.App`
        :param app_name: The name of the cliff application.
            This is used as the command name.
        :param ignored_opts: A list of options to exclude from output, if any
        :returns: A list of docutil nodes
        """
        parser = app.parser
        ignored_opts = ignored_opts or []

        # Drop the automatically-added help action
        for action in list(parser._actions):
            for option_string in action.option_strings:
                if option_string in ignored_opts:
                    del parser._actions[parser._actions.index(action)]
                    break

        parser.prog = app_name

        source_name = '<{}>'.format(app.__class__.__name__)
        result = statemachine.ViewList()
        for line in _format_parser(parser):
            result.append(line, source_name)

        section = nodes.section()
        self.state.nested_parse(result, 0, section)
        return section.children
Пример #20
0
    def run(self):
        env = self.state.document.settings.env
        app = env.app

        tagname = ' '.join(self.content)
        app.info('building list of projects tagged %r' % tagname)
        if not tagname:
            error = self.state_machine.reporter.error(
                'No tagname in tagged-projects directive',
                nodes.literal_block(self.block_text, self.block_text),
                line=self.lineno)
            return [error]

        # Build the view of the data to be parsed for rendering.
        result = statemachine.ViewList()
        project_data = _projects_by_tag.get(tagname)
        source_name = '<' + __name__ + '>'
        if not project_data:
            result.append(
                '.. note:: No projects are using %s, yet.' % tagname,
                source_name,
            )
        else:
            for team_name, deliverable in sorted(project_data):
                if deliverable is None:
                    line = '- :ref:`project-%s`' % projects.slugify(team_name)
                else:
                    line = '- %s (:ref:`project-%s`)' % (
                        deliverable,
                        projects.slugify(team_name),
                    )
                result.append(line, source_name)

        # Parse what we have into a new section.
        node = nodes.section()
        node.document = self.state.document
        nested_parse_with_titles(self.state, result, node)

        return node.children
Пример #21
0
def _nodes_from_rst(
    state: statemachine.State,
    rst_source: str,
) -> List[nodes.Node]:
    """Turn an RST string into a list of nodes.

    These nodes can be used in the document.

    :param state: The superclass for a docutils statemachine which contains a list or transitions
        and transition methods
    :param rst_source: The source of the RST content from which nodes will be extracted
    :returns: A list of nodes extracted from the RST content
    """
    node = nodes.Element()
    node.document = state.document
    nested_parse_with_titles(
        state=state,
        content=statemachine.ViewList(
            statemachine.string2lines(rst_source),
            source="[ansible-navigator autogenerated]",
        ),
        node=node,
    )
    return node.children
Пример #22
0
    def _generate_nodes(self, name, command, parent=None, options={}):
        """Generate the relevant Sphinx nodes.
        Format a `click.Group` or `click.Command`.
        :param name: Name of command, as used on the command line
        :param command: Instance of `click.Group` or `click.Command`
        :param parent: Instance of `click.Context`, or None
        :param show_nested: Whether subcommands should be included in output
        :returns: A list of nested docutil nodes
        """

        # Title
        source_name = name
        content = [nodes.title(text=name)]
        subtitle = self.options.get('subtitle', None)
        description = self.options.get('description', None)

        if subtitle:
            content.append(nodes.subtitle(text=subtitle))
        if description:
            content.append(nodes.paragraph(text=description))

        section = nodes.section(
            '',
            *content,
            ids=[nodes.make_id(source_name)],
            names=[nodes.fully_normalize_name(source_name)])

        # Summary

        result = statemachine.ViewList()
        lines = _format_command(name, command, **options)
        for line in lines:
            result.append(line, source_name)
        self.state.nested_parse(result, 0, section)

        return [section]
Пример #23
0
    def run(self):
        """Load and find config options to document."""
        modules = [c.strip() for c in self.content if c.strip()]

        if not modules:
            raise self.error('No modules provided to document.')

        env = self.state.document.settings.env
        app = env.app

        result = sm.ViewList()
        source = '<{}>'.format(__name__)

        target = self.options.get('config-target', '')
        title = self.options.get(
            'table-title',
            'Description of {} configuration options'.format(target))

        # See if there are option sets that need to be ignored
        exclude = self.options.get('exclude-list', '')
        exclude_list = [e.strip() for e in exclude.split(',') if e.strip()]

        exclusive = self.options.get('exclusive-list', '')
        exclusive_list = [e.strip() for e in exclusive.split(',') if e.strip()]

        result.append('.. _{}:'.format(title.replace(' ', '-')), source)
        result.append('', source)
        result.append('.. list-table:: {}'.format(title), source)
        result.append('   :header-rows: 1', source)
        result.append('   :class: config-ref-table', source)
        result.append('', source)
        result.append('   * - Configuration option = Default value', source)
        result.append('     - Description', source)

        options = []
        for module in modules:
            retval = self._doc_module(module, exclude_list, exclusive_list)
            if retval:
                options.extend(retval)
            else:
                LOG.info('[config-table] No options found in {}'.format(
                         module))

        # Get options sorted alphabetically but with deprecated options last
        list.sort(options, key=lambda opt: opt.name)
        list.sort(options, key=lambda opt: opt.deprecated_for_removal)

        for opt in options:
            result.append(
                '   * - ``{}`` = ``{}``'.format(
                    opt.name, self._get_default(opt)),
                source)
            result.append(
                '     - ({}) {}{}'.format(
                    opt.type, opt.help,
                    ' **DEPRECATED**' if opt.deprecated_for_removal else ''),
                source)

        node = nodes.section()
        node.document = self.state.document
        self.state.nested_parse(result, 0, node)
        return node.children
Пример #24
0
    def _generate_nodes(self, title, command_name, command_class):
        """Generate the relevant Sphinx nodes.

        This is a little funky. Parts of this use raw docutils nodes while
        other parts use reStructuredText and nested parsing. The reason for
        this is simple: it avoids us having to reinvent the wheel. While raw
        docutils nodes are helpful for the simpler elements of the output,
        they don't provide an easy way to use Sphinx's own directives, such as
        the 'option' directive. Refer to [1] for more information.

        [1] http://www.sphinx-doc.org/en/stable/extdev/markupapi.html

        :param title: Title of command
        :param command_name: Name of command, as used on the command line
        :param command_class: Subclass of :py:class:`cliff.command.Command`
        :param prefix: Prefix to apply before command, if any
        :returns: A list of nested docutil nodes
        """
        command = command_class(None, None)
        parser = command.get_parser(command_name)
        description = command.get_description()
        epilog = command.get_epilog()

        # Drop the automatically-added help action
        for action in parser._actions:
            if isinstance(action, argparse._HelpAction):
                del parser._actions[parser._actions.index(action)]

        # Title

        # We build this with plain old docutils nodes

        section = nodes.section(
            '',
            nodes.title(text=title),
            ids=[nodes.make_id(title)],
            names=[nodes.fully_normalize_name(title)])

        source_name = '<{}>'.format(command.__class__.__name__)
        result = statemachine.ViewList()

        # Description

        # We parse this as reStructuredText, allowing users to embed rich
        # information in their help messages if they so choose.

        if description:
            for line in statemachine.string2lines(
                    description, tab_width=4, convert_whitespace=True):
                result.append(line, source_name)

            result.append('', source_name)

        # Summary

        # We both build and parse this as reStructuredText

        for line in _format_parser(parser):
            result.append(line, source_name)

        self.state.nested_parse(result, 0, section)

        # Epilog

        # Like description, this is parsed as reStructuredText

        if epilog:
            result.append('', source_name)

            for line in statemachine.string2lines(
                    epilog, tab_width=4, convert_whitespace=True):
                result.append(line, source_name)

        return [section]
Пример #25
0
    def _generate_nodes(self, name, command, parent=None, show_nested=False):
        """Generate the relevant Sphinx nodes.

        Format a `click.Group` or `click.Command`.

        :param name: Name of command, as used on the command line
        :param command: Instance of `click.Group` or `click.Command`
        :param parent: Instance of `click.Context`, or None
        :param show_nested: Whether subcommands should be included in output
        :returns: A list of nested docutil nodes
        """
        ctx = click.Context(command, info_name=name, parent=parent)

        # Title

        # We build this with plain old docutils nodes

        section = nodes.section(
            '',
            nodes.title(text=name),
            ids=[nodes.make_id(ctx.command_path)],
            names=[nodes.fully_normalize_name(ctx.command_path)])

        source_name = ctx.command_path
        result = statemachine.ViewList()

        # Description

        # We parse this as reStructuredText, allowing users to embed rich
        # information in their help messages if they so choose.

        if ctx.command.help:
            for line in statemachine.string2lines(
                    ctx.command.help, tab_width=4, convert_whitespace=True):
                result.append(line, source_name)

            result.append('', source_name)

        # Summary

        if isinstance(command, click.Command):
            summary = _format_command(ctx, show_nested)
        else:
            # TODO(stephenfin): Do we care to differentiate? Perhaps we
            # shouldn't show usage for groups?
            summary = _format_command(ctx, show_nested)

        for line in summary:
            result.append(line, source_name)

        self.state.nested_parse(result, 0, section)

        # Commands

        if show_nested:
            commands = getattr(ctx.command, 'commands', {})
            for command_name, command_obj in sorted(commands.items()):
                section.extend(self._generate_nodes(
                    command_name,
                    command_obj,
                    ctx,
                    show_nested))

        return [section]
Пример #26
0
 def _construct_node(self, fns, node_id, state):
     content = self._get_result_links(fns)
     content = statemachine.ViewList(content, self.sphinx_env.docname)
     node = nodes.bullet_list(ids=[node_id], classes=['exec-usage'])
     state.nested_parse(content, 0, node)
     return node
Пример #27
0
    def run(self):
        """Load and document the current config options."""

        cindershell = shell.OpenStackCinderShell()
        parser = cindershell.get_base_parser()

        api_version = api_versions.APIVersion(api_versions.MAX_VERSION)
        LOG.info('Generating CLI docs %s', api_version)

        cindershell.get_subcommand_parser(api_version, False, [])

        result = sm.ViewList()
        source = '<{}>'.format(__name__)

        result.append('.. _cinder_command_usage:', source)
        result.append('', source)
        result.append('cinder usage', source)
        result.append('------------', source)
        result.append('', source)
        result.append('.. code-block:: console', source)
        result.append('', source)
        result.append('', source)
        usage = self._get_usage_lines(parser.format_usage(),
                                      '<subcommand> ...')
        for line in usage:
            result.append('  {}'.format(line), source)
        result.append('', source)

        result.append('.. _cinder_command_options:', source)
        result.append('', source)
        result.append('Optional Arguments', source)
        result.append('~~~~~~~~~~~~~~~~~~', source)
        result.append('', source)

        # This accesses a private variable from argparse. That's a little
        # risky, but since this is just for the docs and not "production" code,
        # and since this variable hasn't changed in years, it's a calculated
        # risk to make this documentation generation easier. But if something
        # suddenly breaks, check here first.
        actions = sorted(parser._actions, key=lambda x: x.option_strings[0])
        for action in actions:
            if action.help == '==SUPPRESS==':
                continue
            opts = ', '.join(action.option_strings)
            result.append('``{}``'.format(opts), source)
            result.append('  {}'.format(action.help), source)
            result.append('', source)

        result.append('', source)
        result.append('.. _cinder_commands:', source)
        result.append('', source)
        result.append('Commands', source)
        result.append('~~~~~~~~', source)
        result.append('', source)

        for cmd in cindershell.subcommands:
            if 'completion' in cmd:
                continue
            result.append('``{}``'.format(cmd), source)
            subcmd = cindershell.subcommands[cmd]
            description = self._format_description_lines(subcmd.description)
            result.append('  {}'.format(description[0]), source)
            result.append('', source)

        result.append('', source)
        result.append('.. _cinder_command_details:', source)
        result.append('', source)
        result.append('Command Details', source)
        result.append('---------------', source)
        result.append('', source)

        for cmd in cindershell.subcommands:
            if 'completion' in cmd:
                continue
            subcmd = cindershell.subcommands[cmd]
            result.append('.. _cinder{}:'.format(cmd), source)
            result.append('', source)
            result.append(subcmd.prog, source)
            result.append('~' * len(subcmd.prog), source)
            result.append('', source)
            result.append('.. code-block:: console', source)
            result.append('', source)
            usage = self._get_usage_lines(subcmd.format_usage())
            for line in usage:
                result.append('  {}'.format(line), source)
            result.append('', source)
            description = self._format_description_lines(subcmd.description)
            result.append(description[0], source)
            result.append('', source)

            if len(subcmd._actions) == 0:
                continue

            positional = []
            optional = []
            for action in subcmd._actions:
                if len(action.option_strings):
                    if (action.option_strings[0] != '-h'
                            and action.help != '==SUPPRESS=='):
                        optional.append(action)
                else:
                    positional.append(action)

            if positional:
                result.append('**Positional arguments:**', source)
                result.append('', source)
                for action in positional:
                    result.append('``{}``'.format(action.metavar), source)
                    result.append('  {}'.format(action.help), source)
                    result.append('', source)

            if optional:
                result.append('**Optional arguments:**', source)
                result.append('', source)
                for action in optional:
                    result.append(
                        '``{} {}``'.format(', '.join(action.option_strings),
                                           action.metavar), source)
                    result.append('  {}'.format(action.help), source)
                    result.append('', source)

        node = nodes.section()
        node.document = self.state.document
        nested_parse_with_titles(self.state, result, node)
        return node.children
Пример #28
0
    def run(self):
        env = self.state.document.settings.env
        app = env.app

        def info(msg):
            app.info('[reno] %s' % (msg, ))

        title = ' '.join(self.content)
        branch = self.options.get('branch')
        reporoot_opt = self.options.get('reporoot', '.')
        reporoot = os.path.abspath(reporoot_opt)
        # When building on RTD.org the root directory may not be
        # the current directory, so look for it.
        reporoot = repo.Repo.discover(reporoot).path
        relnotessubdir = self.options.get('relnotessubdir',
                                          defaults.RELEASE_NOTES_SUBDIR)
        ignore_notes = [
            name.strip()
            for name in self.options.get('ignore-notes', '').split(',')
        ]
        conf = config.Config(reporoot, relnotessubdir)
        opt_overrides = {}
        if 'notesdir' in self.options:
            opt_overrides['notesdir'] = self.options.get('notesdir')
        version_opt = self.options.get('version')
        # FIXME(dhellmann): Force these flags True for now and figure
        # out how Sphinx passes a "false" flag later.
        # 'collapse-pre-releases' in self.options
        opt_overrides['collapse_pre_releases'] = True
        # Only stop at the branch base if we have not been told
        # explicitly which versions to include.
        opt_overrides['stop_at_branch_base'] = (version_opt is None)
        if 'earliest-version' in self.options:
            opt_overrides['earliest_version'] = self.options.get(
                'earliest-version')
        if branch:
            opt_overrides['branch'] = branch
        if ignore_notes:
            opt_overrides['ignore_notes'] = ignore_notes
        conf.override(**opt_overrides)

        notesdir = os.path.join(relnotessubdir, conf.notesdir)
        info('scanning %s for %s release notes' % (os.path.join(
            conf.reporoot, notesdir), branch or 'current branch'))

        ldr = loader.Loader(conf)
        if version_opt is not None:
            versions = [v.strip() for v in version_opt.split(',')]
        else:
            versions = ldr.versions
        info('got versions %s' % (versions, ))
        text = formatter.format_report(
            ldr,
            conf,
            versions,
            title=title,
        )
        source_name = '<%s %s>' % (__name__, branch or 'current branch')
        result = statemachine.ViewList()
        for line in text.splitlines():
            result.append(line, source_name)

        node = nodes.section()
        node.document = self.state.document
        nested_parse_with_titles(self.state, result, node)
        return node.children
Пример #29
0
    def run(self):
        title = ' '.join(self.content)
        branch = self.options.get('branch')
        relnotessubdir = self.options.get(
            'relnotessubdir',
            defaults.RELEASE_NOTES_SUBDIR,
        )
        reporoot = self._find_reporoot(
            self.options.get('reporoot', '.'),
            relnotessubdir,
        )
        ignore_notes = [
            name.strip()
            for name in self.options.get('ignore-notes', '').split(',')
        ]
        conf = config.Config(reporoot, relnotessubdir)
        opt_overrides = {}
        if 'notesdir' in self.options:
            opt_overrides['notesdir'] = self.options.get('notesdir')
        version_opt = self.options.get('version')
        # FIXME(dhellmann): Force these flags True for now and figure
        # out how Sphinx passes a "false" flag later.
        # 'collapse-pre-releases' in self.options
        opt_overrides['collapse_pre_releases'] = True
        # Only stop at the branch base if we have not been told
        # explicitly which versions to include.
        opt_overrides['stop_at_branch_base'] = (version_opt is None)
        if 'earliest-version' in self.options:
            opt_overrides['earliest_version'] = self.options.get(
                'earliest-version')
        if 'unreleased-version-title' in self.options:
            opt_overrides['unreleased_version_title'] = self.options.get(
                'unreleased-version-title')

        if branch:
            opt_overrides['branch'] = branch
        if ignore_notes:
            opt_overrides['ignore_notes'] = ignore_notes
        conf.override(**opt_overrides)

        notesdir = os.path.join(relnotessubdir, conf.notesdir)
        LOG.info('scanning %s for %s release notes' % (os.path.join(
            conf.reporoot, notesdir), branch or 'current branch'))

        ldr = loader.Loader(conf)
        if version_opt is not None:
            versions = [v.strip() for v in version_opt.split(',')]
        else:
            versions = ldr.versions
        LOG.info('got versions %s' % (versions, ))
        text = formatter.format_report(
            ldr,
            conf,
            versions,
            title=title,
            branch=branch,
        )
        source_name = '<%s %s>' % (__name__, branch or 'current branch')
        result = statemachine.ViewList()
        for line_num, line in enumerate(text.splitlines(), 1):
            LOG.debug('%4d: %s', line_num, line)
            result.append(line, source_name, line_num)

        node = nodes.section()
        node.document = self.state.document
        nested_parse_with_titles(self.state, result, node)
        return node.children
Пример #30
0
    def _generate_nodes(self,
                        name,
                        command,
                        parent=None,
                        show_nested=False,
                        flat_toctree=False,
                        hide_options=False,
                        options_suffix=False,
                        commands=None):
        """Generate the relevant Sphinx nodes.

        Format a `click.Group` or `click.Command`.

        :param name: Name of command, as used on the command line
        :param command: Instance of `click.Group` or `click.Command`
        :param parent: Instance of `click.Context`, or None
        :param show_nested: Whether subcommands should be included in output
        :param flat_toctree: Whether a flat toctree is generated for
            subcommands (instead of a hierarchical one)
        :param hide_options: Hide [OPTIONS] in generated command
        :param options_suffix: Show [OPTIONS] at the end in generated command
        :param commands: Display only listed commands or skip the section if empty
        :returns: A list of nested docutil nodes
        """
        ctx = click.Context(command, info_name=name, parent=parent)

        if CLICK_VERSION >= (7, 0) and command.hidden:
            return []

        # Title

        section = nodes.section(
            '',
            nodes.title(text=name),
            ids=[nodes.make_id(ctx.command_path)],
            names=[nodes.fully_normalize_name(ctx.command_path)])

        # Summary

        source_name = ctx.command_path
        result = statemachine.ViewList()

        lines = _format_command(ctx, show_nested, hide_options, options_suffix,
                                commands)
        for line in lines:
            LOG.debug(line)
            result.append(line, source_name)

        self.state.nested_parse(result, 0, section)

        # Subcommands

        section_list = [section]
        if show_nested:
            commands = _filter_commands(ctx, commands)
            for command in commands:
                new_section = self._generate_nodes(command.name, command, ctx,
                                                   show_nested, flat_toctree,
                                                   hide_options,
                                                   options_suffix)

                if flat_toctree:
                    section_list.extend(new_section)
                else:
                    section.extend(new_section)
        return section_list