diff --git a/doc/source/conf.py b/doc/source/conf.py index 1b7ad8c278..d92ed424ee 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -78,6 +78,7 @@ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'oslosphinx', 'ext.resources', + 'ext.tablefromtext', 'stevedore.sphinxext'] todo_include_todos = True diff --git a/doc/source/ext/tablefromtext.py b/doc/source/ext/tablefromtext.py new file mode 100644 index 0000000000..84586ff59e --- /dev/null +++ b/doc/source/ext/tablefromtext.py @@ -0,0 +1,119 @@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# -*- coding: utf-8 -*- + +import os +import re + +from docutils import nodes +from docutils.parsers.rst import directives +from docutils.parsers.rst.directives.tables import Table + + +class TableFromText(Table): + """ + Take input from a file and create a simple table. + + Exanple: + + .. table_from_text:: ../setup.cfg + :header: Name,Plug-in + :regex: (.*)=(.*) + :start-after: heat.constraints = + :end-before: heat.stack_lifecycle_plugins = + :sort: + + file: input file relative to source directory + header: comma separated list of column titles + regex: regular expression to parse the source line into columns + start-after: string to look for to start column data + end-before: string to look for to end column data + sort: flag for sorting column data + """ + + required_arguments = 1 + option_spec = { + 'header': directives.unchanged_required, + 'regex': directives.unchanged_required, + 'start-after': directives.unchanged_required, + 'end-before': directives.unchanged_required, + 'sort': directives.flag + } + + def run(self): + header = self.options.get('header').split(',') + lines = self._get_lines() + regex = self.options.get('regex') + max_cols = len(header) + + table = nodes.table() + tgroup = nodes.tgroup(max_cols) + table += tgroup + + col_widths = self.get_column_widths(max_cols) + tgroup.extend(nodes.colspec(colwidth=col_width) for + col_width in col_widths) + + thead = nodes.thead() + tgroup += thead + thead += self.create_table_row(header) + + tbody = nodes.tbody() + tgroup += tbody + + for row in lines: + matched = re.search(regex, row) + if matched: + tbody += self.create_table_row(matched.groups()) + + return [table] + + def create_table_row(self, row_cells): + row = nodes.row() + + for cell in row_cells: + entry = nodes.entry() + row += entry + entry += nodes.paragraph(text=cell.strip()) + + return row + + def _get_lines(self): + env = self.state.document.settings.env + sourcefile = os.path.join(env.srcdir, self.arguments[0]) + startafter = self.options.get('start-after') + endbefore = self.options.get('end-before') + + lines = [line.strip() for line in open(sourcefile)] + + if startafter is not None or endbefore is not None: + includeline = not startafter + result = [] + for line in lines: + if not includeline and startafter and startafter in line: + includeline = True + elif includeline and endbefore and endbefore in line: + includeline = False + break + elif includeline: + result.append(line) + lines = result + + if 'sort' in self.options: + lines = sorted(lines) + + return lines + + +def setup(app): + app.add_directive('table_from_text', TableFromText) diff --git a/doc/source/template_guide/hot_spec.rst b/doc/source/template_guide/hot_spec.rst index 12ad2561a0..73f00b75c2 100644 --- a/doc/source/template_guide/hot_spec.rst +++ b/doc/source/template_guide/hot_spec.rst @@ -510,6 +510,16 @@ For example constraints: - custom_constraint: nova.keypair +The following section lists the custom constraints and the plug-ins +that support them. + +.. table_from_text:: ../../setup.cfg + :header: Name,Plug-in + :regex: (.*)=(.*) + :start-after: heat.constraints = + :end-before: heat.stack_lifecycle_plugins = + :sort: + .. _hot_spec_pseudo_parameters: Pseudo parameters