From df232c30743a8a963e729e78f355850a871da878 Mon Sep 17 00:00:00 2001 From: Tristan Cacqueray Date: Mon, 7 Nov 2016 03:23:46 +0000 Subject: [PATCH] Refactor all parameters to configuration.yaml This change moves parameter from utils.py and index.rst to the configuration.yaml. Moreover this change does: * Use ISO 8601 dateformat in configuration * Change events extension to use datetime instead of calendar * Add a configuration extension to render doc substitutions Change-Id: Ie35cb9ae2c334814afaa36b3afd606c8bcf62616 --- configuration.yaml | 15 ++++++++ doc/source/_exts/candidates.py | 2 +- doc/source/_exts/configuration.jinja | 4 +++ doc/source/_exts/configuration.py | 35 +++++++++++++++++++ doc/source/_exts/events.jinja | 2 +- doc/source/_exts/events.py | 21 ++++------- doc/source/conf.py | 1 + doc/source/index.rst | 6 +--- openstack_election/check_candidacy.py | 7 ++-- .../cmds/check_all_candidacies.py | 4 +-- openstack_election/cmds/check_candidacy.py | 2 +- openstack_election/cmds/check_manual.py | 2 +- openstack_election/cmds/close_election.py | 2 +- openstack_election/cmds/render_statistics.py | 2 +- openstack_election/utils.py | 28 ++++++++------- 15 files changed, 91 insertions(+), 42 deletions(-) create mode 100644 doc/source/_exts/configuration.jinja create mode 100644 doc/source/_exts/configuration.py diff --git a/configuration.yaml b/configuration.yaml index cd123247..c2f9d136 100644 --- a/configuration.yaml +++ b/configuration.yaml @@ -1,4 +1,16 @@ --- +release: ocata + +tag: 'sept-2016-elections' + +timeframe: + name: 'Mitaka-Newton' + start: '2015-09-05T00:00' + end: '2016-09-04T23:59' + email_deadline: '2016-09-18T23:59' + +tc_seats: 6 + timeline: - name: 'PTL nomination' start: '2016-09-12T00:00' @@ -12,3 +24,6 @@ timeline: - name: 'TC elections' start: '2016-10-03T00:00' end: '2016-10-09T23:45' + +past_elections: + - ocata diff --git a/doc/source/_exts/candidates.py b/doc/source/_exts/candidates.py index ae0e0739..8cfb5553 100644 --- a/doc/source/_exts/candidates.py +++ b/doc/source/_exts/candidates.py @@ -83,7 +83,7 @@ def build_lists(app): " :titlesonly:", "" ] - for previous in utils.PAST_ELECTIONS: + for previous in utils.conf['past_elections']: if build_archive(previous, "ptl"): previous_toc.append(" %s/ptl.rst" % previous) if build_archive(previous, "tc"): diff --git a/doc/source/_exts/configuration.jinja b/doc/source/_exts/configuration.jinja new file mode 100644 index 00000000..2f6efd60 --- /dev/null +++ b/doc/source/_exts/configuration.jinja @@ -0,0 +1,4 @@ +.. |Timeframe| replace:: {{ timeframe['name'] }} timeframe ({{ timeframe['start_str'] }} to {{ timeframe['end_str'] }}) +.. |PreferredEmailDeadLine| replace:: {{ timeframe['email_deadline_str'] }} +.. |Projects.yaml| replace:: https://git.openstack.org/cgit/openstack/governance/tree/reference/projects.yaml?id={{ tag }} +.. |TCSeats| replace:: {{ tc_seats }} diff --git a/doc/source/_exts/configuration.py b/doc/source/_exts/configuration.py new file mode 100644 index 00000000..f2afaa0a --- /dev/null +++ b/doc/source/_exts/configuration.py @@ -0,0 +1,35 @@ +# 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 configuration substitution +""" + +import jinja2 +import jinja2.environment +import os + +from openstack_election.utils import conf + + +def build_configuration(app): + output_file = os.path.join(".", "doc", "source", "configuration.rst") + template_dir = os.path.join(".", "doc", "source", "_exts") + loader = jinja2.FileSystemLoader(template_dir) + env = jinja2.environment.Environment(trim_blocks=True, loader=loader) + template = env.get_template("configuration.jinja") + with open(output_file, "w") as out: + out.write(template.render(conf)) + + +def setup(app): + app.info('loading configuration extension') + app.connect('builder-inited', build_configuration) diff --git a/doc/source/_exts/events.jinja b/doc/source/_exts/events.jinja index 5f040318..e7d07467 100644 --- a/doc/source/_exts/events.jinja +++ b/doc/source/_exts/events.jinja @@ -5,7 +5,7 @@ diff --git a/doc/source/_exts/events.py b/doc/source/_exts/events.py index 0d75a627..278a7446 100644 --- a/doc/source/_exts/events.py +++ b/doc/source/_exts/events.py @@ -13,30 +13,23 @@ """Add election timer data """ -import calendar +import datetime import jinja2 import jinja2.environment import os -import time +import pytz from openstack_election import utils def build_timer(app): app.add_javascript("event_timer.js") - now = time.time() + now = datetime.datetime.utcnow().replace(tzinfo=pytz.utc) first_event = True for ev in utils.conf['timeline']: - ds, hs = ev['start'].split('T') - de, he = ev['end'].split('T') - start_time = calendar.timegm( - time.strptime(ev['start'], "%Y-%m-%dT%H:%M")) - end_time = calendar.timegm( - time.strptime(ev['end'], "%Y-%m-%dT%H:%M")) - - if start_time > now: + if ev['start'] > now: ev['status'] = 'future' - elif end_time > now: + elif ev['end'] > now: ev['status'] = 'current' else: ev['status'] = 'past' @@ -51,8 +44,8 @@ def build_timer(app): elif ev['status'] == 'past': mark = '*' - ev['start_str'] = "%s%s, %s UTC%s" % (mark, ds, hs, mark) - ev['end_str'] = "%s%s, %s UTC%s" % (mark, de, he, mark) + ev['start_iso'] = ev['start'].strftime("%Y-%m-%dT%H:%M") + ev['end_iso'] = ev['end'].strftime("%Y-%m-%dT%H:%M") ev['name_str'] = "%s%s%s" % (mark, ev['name'], mark) output_file = os.path.join(".", "doc", "source", "events.rst") with open(output_file, "w") as out: diff --git a/doc/source/conf.py b/doc/source/conf.py index 724b88a8..3eb39344 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -32,6 +32,7 @@ extensions = [ 'oslosphinx', 'candidates', 'events', + 'configuration', ] todo_include_todos = True diff --git a/doc/source/index.rst b/doc/source/index.rst index eb7846c7..47a8cf81 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -1,8 +1,4 @@ -.. TODO: Update below definition for new elections -.. |Timeframe| replace:: Mitaka-Newton timeframe (September 5, 2015 00:00 UTC to September 4, 2016 23:59 UTC) -.. |PreferredEmailDeadLine| replace:: September 18, 2016 -.. |Projects.yaml| replace:: http://git.openstack.org/cgit/openstack/governance/tree/reference/projects.yaml?id=sept-2016-elections -.. |TCSeats| replace:: 6 +.. include:: configuration.rst ================== OpenStack Election diff --git a/openstack_election/check_candidacy.py b/openstack_election/check_candidacy.py index 4f9fb4f5..da7254e2 100755 --- a/openstack_election/check_candidacy.py +++ b/openstack_election/check_candidacy.py @@ -31,6 +31,7 @@ def check_candidate(project_name, email, projects, limit=1): found = 0 branch = None + timeframe = utils.conf['timeframe'] if project_name in ['Stable branch maintenance']: project_list = projects.values() @@ -50,8 +51,8 @@ def check_candidate(project_name, email, projects, limit=1): for repo_name in deliverable["repos"]: query = ('is:merged after:"%s" before:"%s" ' 'owner:%s project:%s' % - (utils.gerrit_datetime(utils.PERIOD_START), - utils.gerrit_datetime(utils.PERIOD_END), + (utils.gerrit_datetime(timeframe['start']), + utils.gerrit_datetime(timeframe['end']), email, repo_name)) if branch: query += (' branch:%s' % (branch)) @@ -70,7 +71,7 @@ def check_candidate(project_name, email, projects, limit=1): return found -def check_candidacy_review(change_id, limit=1, tag=utils.PROJECTS_TAG, +def check_candidacy_review(change_id, limit=1, tag=utils.conf['tag'], review=None): projects = utils.get_projects(tag=tag) # If there is more than one review that matches this change_id then all diff --git a/openstack_election/cmds/check_all_candidacies.py b/openstack_election/cmds/check_all_candidacies.py index 7487a7d3..2bbb4724 100755 --- a/openstack_election/cmds/check_all_candidacies.py +++ b/openstack_election/cmds/check_all_candidacies.py @@ -23,7 +23,7 @@ from openstack_election import utils def get_reviews(): return utils.get_reviews('is:open project:%s file:^%s/%s/.*' % (utils.ELECTION_REPO, utils.CANDIDATE_PATH, - utils.SERIES_NAME)) + utils.conf['release'])) def main(): @@ -34,7 +34,7 @@ def main(): help=('How many validating changes to report. ' 'A negative value means report many. ' 'Default: %(default)s')) - parser.add_argument('--tag', dest='tag', default=utils.PROJECTS_TAG, + parser.add_argument('--tag', dest='tag', default=utils.conf['tag'], help=('The governance tag to validate against. ' 'Default: %(default)s')) diff --git a/openstack_election/cmds/check_candidacy.py b/openstack_election/cmds/check_candidacy.py index 341ddced..11e437fa 100755 --- a/openstack_election/cmds/check_candidacy.py +++ b/openstack_election/cmds/check_candidacy.py @@ -29,7 +29,7 @@ def main(): help=('How many validating changes to report. ' 'A negative value means report many. ' 'Default: %(default)s')) - parser.add_argument('--tag', dest='tag', default=utils.PROJECTS_TAG, + parser.add_argument('--tag', dest='tag', default=utils.conf['tag'], help=('The governance tag to validate against. ' 'Default: %(default)s')) diff --git a/openstack_election/cmds/check_manual.py b/openstack_election/cmds/check_manual.py index 0cb14672..95a6aedd 100644 --- a/openstack_election/cmds/check_manual.py +++ b/openstack_election/cmds/check_manual.py @@ -32,7 +32,7 @@ def main(): help=('How many validating changes to report. ' 'A negative value means report many. ' 'Default: %(default)s')) - parser.add_argument('--tag', dest='tag', default=utils.PROJECTS_TAG, + parser.add_argument('--tag', dest='tag', default=utils.conf['tag'], help=('The governance tag to validate against. ' 'Default: %(default)s')) diff --git a/openstack_election/cmds/close_election.py b/openstack_election/cmds/close_election.py index 1f305905..52226829 100755 --- a/openstack_election/cmds/close_election.py +++ b/openstack_election/cmds/close_election.py @@ -74,7 +74,7 @@ def main(): parser = argparse.ArgumentParser(description=desc) parser.add_argument('-v', '--verbose', action="count", default=0, help='Increase program verbosity') - parser.add_argument('-r', '--release', default=utils.SERIES_NAME, + parser.add_argument('-r', '--release', default=utils.conf['release'], help='Which nominations to look at') parser.add_argument('-b', '--basedir', default=os.getcwd(), diff --git a/openstack_election/cmds/render_statistics.py b/openstack_election/cmds/render_statistics.py index 45378a09..44f3699d 100755 --- a/openstack_election/cmds/render_statistics.py +++ b/openstack_election/cmds/render_statistics.py @@ -66,7 +66,7 @@ def main(): parser = argparse.ArgumentParser(description='Investigate Nominations') parser.add_argument('-v', '--verbose', action="count", default=0, help='Increase program verbosity') - parser.add_argument('-r', '--release', default=utils.SERIES_NAME, + parser.add_argument('-r', '--release', default=utils.conf['release'], help='Which nominations to look at') parser.add_argument('-b', '--basedir', default=os.getcwd(), diff --git a/openstack_election/utils.py b/openstack_election/utils.py index c6170b3b..676e7910 100644 --- a/openstack_election/utils.py +++ b/openstack_election/utils.py @@ -26,14 +26,6 @@ import time import urllib import yaml -# Per election constants - -SERIES_NAME = 'ocata' -# 2015-09-05 00:00:00 +0000 -PERIOD_START = datetime.datetime(2015, 9, 5, 0, 0, 0, tzinfo=pytz.utc) -# 2016-09-04 23:59:59 +0000 -PERIOD_END = datetime.datetime(2016, 9, 4, 23, 59, 59, tzinfo=pytz.utc) -PROJECTS_TAG = 'sept-2016-elections' # Library constants CANDIDATE_PATH = 'candidates' @@ -42,10 +34,22 @@ ELECTION_REPO = 'openstack/election' CGIT_URL = 'https://git.openstack.org/cgit' PROJECTS_URL = ('%s/openstack/governance/plain/reference/projects.yaml' % (CGIT_URL)) +TIME_FMT = "%b %d, %Y %H:%M %Z" -PAST_ELECTIONS = ['ocata'] - +# Election configuration conf = yaml.load(open('configuration.yaml')) + +# Convert time to datetime object +strptime = lambda x: datetime.datetime.strptime( + x, "%Y-%m-%dT%H:%M").replace(tzinfo=pytz.utc) +for key in ('start', 'end', 'email_deadline'): + conf['timeframe'][key] = strptime(conf['timeframe'][key]) + conf['timeframe'][key+'_str'] = conf['timeframe'][key].strftime(TIME_FMT) +for event in conf['timeline']: + for key in ('start', 'end'): + event[key] = strptime(event[key]) + event[key+'_str'] = event[key].strftime(TIME_FMT) + exceptions = None @@ -133,7 +137,7 @@ def check_atc_date(atc): return False expires_in = datetime.datetime.strptime(atc['expires-in'], '%B %Y') expires_in = expires_in.replace(tzinfo=pytz.utc) - return PERIOD_END < expires_in + return conf['timeframe']['end'] < expires_in def get_projects(tag=None): @@ -172,7 +176,7 @@ def dir2name(name, projects): raise ValueError(('%s does not match any project' % (name))) -def build_candidates_list(election=SERIES_NAME): +def build_candidates_list(election=conf['release']): project_list = os.listdir(os.path.join(CANDIDATE_PATH, election)) project_list.sort() candidates_lists = {}