Add member table generation
This is taken from the OpenStack governance repo to generate the member table from a data file. Change-Id: I348d046603290fe6042b7d9070a6a71552742914 Signed-off-by: Dean Troyer <dtroyer@gmail.com>
This commit is contained in:
parent
e81e9dcf22
commit
6d93be5276
|
@ -0,0 +1,156 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
"""Build a table of the current members
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
from docutils import nodes
|
||||||
|
from docutils.parsers.rst.directives.tables import Table
|
||||||
|
from docutils.parsers.rst import directives
|
||||||
|
|
||||||
|
# Full name (IRC) <E-mail> [expires in] {role}
|
||||||
|
_PATTERN = re.compile('(?P<name>.*)\s+\((?P<irc>.*)\)\s+\<(?P<email>.*)\>\s+\[(?P<date>.*)\](\s+\{(?P<role>.*)\})?') # noqa
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_members_file(app, filename):
|
||||||
|
"""Load the members file and return each row as a dictionary.
|
||||||
|
"""
|
||||||
|
with open(filename, 'r') as f:
|
||||||
|
for linum, line in enumerate(f, 1):
|
||||||
|
line = line.strip()
|
||||||
|
if not line or line.startswith('#'):
|
||||||
|
continue
|
||||||
|
m = _PATTERN.match(line)
|
||||||
|
if not m:
|
||||||
|
app.warning('Could not parse line %d of %s: %r' %
|
||||||
|
(linum, filename, line))
|
||||||
|
continue
|
||||||
|
yield m.groupdict()
|
||||||
|
|
||||||
|
|
||||||
|
class MembersTable(Table):
|
||||||
|
"""Insert the members table using the referenced file as source.
|
||||||
|
"""
|
||||||
|
|
||||||
|
HEADERS = ('Full Name', 'IRC Nickname', 'E-mail', 'Term Expires', 'Role')
|
||||||
|
HEADER_MAP = {
|
||||||
|
'Full Name': 'name',
|
||||||
|
'IRC Nickname': 'irc',
|
||||||
|
'E-mail': 'email',
|
||||||
|
'Term Expires': 'date',
|
||||||
|
'Role': 'role',
|
||||||
|
}
|
||||||
|
|
||||||
|
option_spec = {'class': directives.class_option,
|
||||||
|
'name': directives.unchanged,
|
||||||
|
'datafile': directives.unchanged,
|
||||||
|
}
|
||||||
|
|
||||||
|
has_content = False
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
env = self.state.document.settings.env
|
||||||
|
app = env.app
|
||||||
|
config = app.config
|
||||||
|
|
||||||
|
# The required argument to the directive is the name of the
|
||||||
|
# file to parse.
|
||||||
|
datafile = self.options.get('datafile')
|
||||||
|
if not datafile:
|
||||||
|
error = self.state_machine.reporter.error(
|
||||||
|
'No filename in membertable directive',
|
||||||
|
nodes.literal_block(self.block_text, self.block_text),
|
||||||
|
line=self.lineno)
|
||||||
|
return [error]
|
||||||
|
|
||||||
|
# Handle the width settings and title
|
||||||
|
try:
|
||||||
|
# Since docutils 0.13, get_column_widths returns a (widths,
|
||||||
|
# colwidths) tuple, where widths is a string (i.e. 'auto').
|
||||||
|
# See https://sourceforge.net/p/docutils/patches/120/.
|
||||||
|
col_widths = self.get_column_widths(len(self.HEADERS))
|
||||||
|
title, messages = self.make_title()
|
||||||
|
except SystemMessagePropagation as detail:
|
||||||
|
return [detail.args[0]]
|
||||||
|
except Exception as err:
|
||||||
|
error = self.state_machine.reporter.error(
|
||||||
|
'Error processing memberstable directive:\n%s' % err,
|
||||||
|
nodes.literal_block(self.block_text, self.block_text),
|
||||||
|
line=self.lineno,
|
||||||
|
)
|
||||||
|
return [error]
|
||||||
|
|
||||||
|
# Now find the real path to the file, relative to where we are.
|
||||||
|
rel_filename, filename = env.relfn2path(datafile)
|
||||||
|
|
||||||
|
# Build the table node using the parsed file
|
||||||
|
data_iter = _parse_members_file(app, filename)
|
||||||
|
table_node = self.build_table(
|
||||||
|
data_iter,
|
||||||
|
col_widths,
|
||||||
|
)
|
||||||
|
table_node['classes'] += self.options.get('class', [])
|
||||||
|
self.add_name(table_node)
|
||||||
|
|
||||||
|
if title:
|
||||||
|
table_node.insert(0, title)
|
||||||
|
|
||||||
|
return [table_node] + messages
|
||||||
|
|
||||||
|
def build_table(self, table_data, col_widths):
|
||||||
|
table = nodes.table()
|
||||||
|
|
||||||
|
# Set up the column specifications
|
||||||
|
# based on the widths.
|
||||||
|
tgroup = nodes.tgroup(cols=len(self.HEADERS))
|
||||||
|
table += tgroup
|
||||||
|
tgroup.extend(nodes.colspec(colwidth=col_width)
|
||||||
|
for col_width in col_widths)
|
||||||
|
|
||||||
|
# Set the headers
|
||||||
|
thead = nodes.thead()
|
||||||
|
tgroup += thead
|
||||||
|
row_node = nodes.row()
|
||||||
|
thead += row_node
|
||||||
|
row_node.extend(
|
||||||
|
nodes.entry(h, nodes.paragraph(text=h))
|
||||||
|
for h in self.HEADERS
|
||||||
|
)
|
||||||
|
|
||||||
|
# The body of the table is made up of rows.
|
||||||
|
# Each row contains a series of entries,
|
||||||
|
# and each entry contains a paragraph of text.
|
||||||
|
tbody = nodes.tbody()
|
||||||
|
tgroup += tbody
|
||||||
|
rows = []
|
||||||
|
for row in table_data:
|
||||||
|
trow = nodes.row()
|
||||||
|
# Iterate over the headers in the same order every time.
|
||||||
|
for h in self.HEADERS:
|
||||||
|
# Get the cell value from the row data, replacing None
|
||||||
|
# in re match group with empty string.
|
||||||
|
cell = row.get(self.HEADER_MAP[h]) or ''
|
||||||
|
entry = nodes.entry()
|
||||||
|
para = nodes.paragraph(text=str(cell))
|
||||||
|
entry += para
|
||||||
|
trow += entry
|
||||||
|
rows.append(trow)
|
||||||
|
tbody.extend(rows)
|
||||||
|
|
||||||
|
return table
|
||||||
|
|
||||||
|
|
||||||
|
def setup(app):
|
||||||
|
app.info('loading members extension')
|
||||||
|
app.add_directive('memberstable', MembersTable)
|
|
@ -14,9 +14,9 @@
|
||||||
# documentation root, use os.path.abspath to make it absolute, like shown
|
# documentation root, use os.path.abspath to make it absolute, like shown
|
||||||
# here.
|
# here.
|
||||||
#
|
#
|
||||||
# import os
|
import os
|
||||||
# import sys
|
import sys
|
||||||
# sys.path.insert(0, os.path.abspath('.'))
|
sys.path.insert(0, os.path.join(os.path.abspath('.'), '_exts'))
|
||||||
|
|
||||||
|
|
||||||
# -- Project information -----------------------------------------------------
|
# -- Project information -----------------------------------------------------
|
||||||
|
@ -41,7 +41,8 @@ release = u'0.1'
|
||||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||||
# ones.
|
# ones.
|
||||||
extensions = [
|
extensions = [
|
||||||
'openstackdocstheme'
|
'members',
|
||||||
|
'openstackdocstheme',
|
||||||
]
|
]
|
||||||
|
|
||||||
# Add any paths that contain templates here, relative to this directory.
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
|
|
|
@ -17,6 +17,12 @@ documentation the links below are directly there.
|
||||||
* `The Four Opens <https://governance.openstack.org/tc/reference/opens.html>`__
|
* `The Four Opens <https://governance.openstack.org/tc/reference/opens.html>`__
|
||||||
* `StarlingX Charter <stx_charter.html>`__
|
* `StarlingX Charter <stx_charter.html>`__
|
||||||
|
|
||||||
|
Current Members
|
||||||
|
===============
|
||||||
|
|
||||||
|
.. memberstable::
|
||||||
|
:datafile: ../../reference/tsc/members
|
||||||
|
|
||||||
Indices and Tables
|
Indices and Tables
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
# Full name (IRC) <E-mail> [expires in] {role}
|
||||||
|
Ian Jolliffe (ijolliffe) <Ian.Jolliffe@windriver.com> [TBD]
|
||||||
|
Brent Rowsell () <Brent.Rowsell@windriver.com> [TBD]
|
||||||
|
Dean Troyer (dtroyer) <dtroyer@gmail.com> [TBD]
|
||||||
|
Saul Wold (sdw) <sgw@linux.intel.com> [TBD]
|
|
@ -0,0 +1,25 @@
|
||||||
|
[metadata]
|
||||||
|
name = starlingx-governance
|
||||||
|
version = 2018.1
|
||||||
|
summary = StarlingX Governance Documents
|
||||||
|
description-file =
|
||||||
|
README.rst
|
||||||
|
author = StarlingX TSC
|
||||||
|
author-email = starlingx-discuss@lists.starlingx.io
|
||||||
|
home-page = http://www.starlingx.io/
|
||||||
|
|
||||||
|
[files]
|
||||||
|
packages =
|
||||||
|
starlingx_governance
|
||||||
|
|
||||||
|
[build_sphinx]
|
||||||
|
all_files = 1
|
||||||
|
build-dir = doc/build
|
||||||
|
source-dir = doc/source
|
||||||
|
warning-is-error = 1
|
||||||
|
|
||||||
|
[pbr]
|
||||||
|
warnerrors = True
|
||||||
|
|
||||||
|
[flake8]
|
||||||
|
ignore = E501,E226,H405
|
|
@ -0,0 +1,22 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
|
||||||
|
import setuptools
|
||||||
|
|
||||||
|
setuptools.setup(
|
||||||
|
setup_requires=['pbr'],
|
||||||
|
pbr=True)
|
7
tox.ini
7
tox.ini
|
@ -37,6 +37,13 @@ commands =
|
||||||
-o -type f -name '*.yaml' \
|
-o -type f -name '*.yaml' \
|
||||||
-print0 | xargs -0 yamllint"
|
-print0 | xargs -0 yamllint"
|
||||||
|
|
||||||
|
[testenv:pep8]
|
||||||
|
basepython = python3
|
||||||
|
usedevelop = False
|
||||||
|
skip_install = True
|
||||||
|
deps = pep8
|
||||||
|
commands = pep8
|
||||||
|
|
||||||
[testenv:venv]
|
[testenv:venv]
|
||||||
basepython = python3
|
basepython = python3
|
||||||
commands = {posargs}
|
commands = {posargs}
|
||||||
|
|
Loading…
Reference in New Issue