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]
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
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
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]
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]
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]
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]
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
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
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
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]
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
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[:]
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
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]
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]
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]
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
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
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
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]
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
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]
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]
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
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
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
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
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