Browse Source
TC is more connected with project teams with the weekly meeting and PTG TC+Leadership interaction sessions. Also, TC liaisons did not work the way we expected it. In Zed PTG, we decided to remove it. - https://etherpad.opendev.org/p/tc-zed-ptg Change-Id: I08702b015245df35d40e08fa08a3269cc6bb1cacchanges/91/837891/2
10 changed files with 1 additions and 414 deletions
@ -1,143 +0,0 @@
|
||||
# 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 of the TC. |
||||
""" |
||||
|
||||
from docutils import nodes |
||||
from docutils.parsers.rst import directives |
||||
from docutils.parsers.rst.directives import tables |
||||
from docutils.utils import SystemMessagePropagation |
||||
from sphinx.util import logging |
||||
|
||||
from openstack_governance import projects |
||||
|
||||
LOG = logging.getLogger(__name__) |
||||
|
||||
|
||||
class TCLiaisonsTable(tables.Table): |
||||
"""Insert the members table using the referenced file as source. |
||||
""" |
||||
|
||||
HEADERS = ('TC Member', 'Projects') |
||||
|
||||
option_spec = {'class': directives.class_option, |
||||
'name': directives.unchanged, |
||||
'datafile': directives.unchanged, |
||||
} |
||||
|
||||
has_content = False |
||||
|
||||
def run(self): |
||||
env = self.state.document.settings.env |
||||
|
||||
# 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: |
||||
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 = projects.load_project_file(filename) |
||||
liaisons = {} |
||||
for project_name, project in data_iter.items(): |
||||
proj_liaisons = project.get('liaisons', {}) |
||||
|
||||
for liaison in proj_liaisons.get('tc_members', []): |
||||
try: |
||||
liaisons[liaison].extend([project_name]) |
||||
except KeyError: |
||||
liaisons[liaison] = [] |
||||
liaisons[liaison].extend([project_name]) |
||||
|
||||
table_node = self.build_table( |
||||
liaisons, |
||||
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(col_widths)) |
||||
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 member, tc_projects in table_data.items(): |
||||
trow = nodes.row() |
||||
# Iterate over the headers in the same order every time. |
||||
name = nodes.entry() |
||||
name += nodes.paragraph(text=str(member)) |
||||
trow += name |
||||
project = nodes.entry() |
||||
project_list = nodes.paragraph() |
||||
for proj in tc_projects: |
||||
project_list += nodes.reference( |
||||
proj, proj, refuri="projects/%s.html" % proj) |
||||
project_list += nodes.Text(", ") |
||||
project += project_list |
||||
trow += project |
||||
rows.append(trow) |
||||
tbody.extend(rows) |
||||
|
||||
return table |
||||
|
||||
|
||||
def setup(app): |
||||
LOG.info('loading tc liaisons extension') |
||||
app.add_directive('liaisonstable', TCLiaisonsTable) |
@ -1,9 +0,0 @@
|
||||
=========== |
||||
TC Liaisons |
||||
=========== |
||||
|
||||
OpenStack Project Team TC Liasons |
||||
================================= |
||||
|
||||
.. liaisonstable:: |
||||
:datafile: ../reference/projects.yaml |
@ -1,95 +0,0 @@
|
||||
#!/usr/bin/env python3 |
||||
|
||||
# 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. |
||||
|
||||
import argparse |
||||
import collections |
||||
import random |
||||
|
||||
from openstack_governance import members |
||||
from openstack_governance import projects |
||||
|
||||
|
||||
def main(): |
||||
parser = argparse.ArgumentParser() |
||||
parser.add_argument( |
||||
'--member-file', |
||||
default='reference/members.yaml', |
||||
help='location of members file, (%(default)s)', |
||||
) |
||||
parser.add_argument( |
||||
'--projects-file', |
||||
default='reference/projects.yaml', |
||||
help='location of projects.yaml, (%(default)s)', |
||||
) |
||||
parser.add_argument( |
||||
'--replace-all', |
||||
action='store_true', |
||||
help='Replace all assigned liaisons (%(default)s)', |
||||
) |
||||
parser.add_argument( |
||||
'--remove-all', |
||||
action='store_true', |
||||
help='Remove all assigned liaisons (%(default)s)', |
||||
) |
||||
args = parser.parse_args() |
||||
|
||||
member_nics = [ |
||||
m['irc'] |
||||
for m in members.parse_members_file(args.member_file) |
||||
] |
||||
|
||||
project_data = projects.load_project_file(args.projects_file) |
||||
|
||||
num_teams = len(project_data) |
||||
assignments_per = num_teams // (len(member_nics) // 2) |
||||
|
||||
member_counts = collections.Counter({ |
||||
nic: 0 |
||||
for nic in member_nics |
||||
}) |
||||
|
||||
if not args.replace_all: |
||||
for _, team in project_data.items(): |
||||
proj_liaisons = team.get('liaisons', {}) |
||||
for member in proj_liaisons.get('tc_members', []): |
||||
member_counts.update({member: 1}) |
||||
|
||||
choices = [] |
||||
for member, count in sorted(member_counts.items()): |
||||
choices.extend([member] * (assignments_per - count)) |
||||
# Make sure we have a list in order that isn't assigning the same |
||||
# person to a team twice. |
||||
|
||||
for name, team in project_data.items(): |
||||
proj_liaisons = team.get('liaisons', {}) |
||||
liaisons = proj_liaisons.get('tc_members', []) |
||||
if args.remove_all: |
||||
team['liaisons']['tc_members'] = [] |
||||
continue |
||||
if args.replace_all: |
||||
liaisons = [] |
||||
while len(liaisons) < 2: |
||||
random.shuffle(choices) |
||||
next_choice = choices.pop() |
||||
while next_choice in liaisons: |
||||
choices.insert(0, next_choice) |
||||
next_choice = choices.pop() |
||||
liaisons.append(next_choice) |
||||
team['liaisons']['tc_members'] = liaisons |
||||
|
||||
projects.write_project_file(project_data, args.projects_file) |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
main() |
Loading…
Reference in new issue