From 45f3c5d005087da5beb2729edddfa68cfd8f5ac4 Mon Sep 17 00:00:00 2001 From: Tristan Cacqueray Date: Wed, 16 Mar 2016 16:24:20 -0400 Subject: [PATCH] Add statistics rendering tool Change-Id: I5ef2bd5361385ab203b5ea093603fd91d16661fd --- openstack_election/cmds/render_statistics.py | 111 +++++++++++++++++++ openstack_election/utils.py | 8 ++ setup.cfg | 2 +- 3 files changed, 120 insertions(+), 1 deletion(-) create mode 100755 openstack_election/cmds/render_statistics.py diff --git a/openstack_election/cmds/render_statistics.py b/openstack_election/cmds/render_statistics.py new file mode 100755 index 00000000..9a926371 --- /dev/null +++ b/openstack_election/cmds/render_statistics.py @@ -0,0 +1,111 @@ +# 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. + +from __future__ import absolute_import +from __future__ import print_function +from __future__ import unicode_literals + +import argparse +import datetime +import os +import pytz + +from openstack_election import utils + +counts = {'projects': 0, 'nominations': 0, 'with_candidate': 0} + + +def name_fix(name): + name = name[:-4] + name = name.replace('_', ' ') + name = name.title() + return name + + +def as_percentage(progress, total): + try: + p = (100.0 * (float(progress) / float(total))) + except ZeroDivisionError: + p = 0.0 + return p + + +def as_utctime(dt): + return "%s" % (dt.strftime("%Y-%m-%d %T UTC")) + + +def collect_project_stats(basedir, verbose): + global counts + + for directory, dirnames, filenames in os.walk(basedir): + project = directory[len(basedir):] + candidates = filter(lambda x: x.endswith('.txt'), filenames) + candidates = [name_fix(n) for n in candidates] + candidates_count = len(candidates) + + if not filenames == []: + counts['projects'] += 1 + if candidates_count != 0: + counts['with_candidate'] += 1 + if candidates_count >= 2: + counts['nominations'] += 1 + + if verbose: + print("%-25s : %s" % (project, candidates)) + + +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, + help='Which nominations to look at') + parser.add_argument('-b', '--basedir', + default=os.getcwd(), + help='Path to git clone of openstack/election') + + args = parser.parse_args() + + args.basedir = os.path.join(args.basedir, 'candidates', args.release, '') + args.basedir = os.path.expanduser(args.basedir) + collect_project_stats(args.basedir, args.verbose) + + now = datetime.datetime.now(tz=pytz.utc) + now = now.replace(microsecond=0) + start = utils.get_event('PTL nomination starts') + end = utils.get_event('PTL nomination ends') + duration = (end - start) + remaining = (end - now) + progress = (duration - remaining) + + p_progress = as_percentage(progress.total_seconds(), + duration.total_seconds()) + p_candidate = as_percentage(counts['with_candidate'], counts['projects']) + p_nominations = as_percentage(counts['nominations'], counts['projects']) + + if args.verbose: + print("-" * 51) + print("%-25s @ %s" % ("Nominations started", as_utctime(start))) + print("%-25s @ %s" % ("Nominations end", as_utctime(end))) + print("%-25s : %s" % ("Nominations duration", duration)) + print("%-25s : %s" % ("Nominations remaining", remaining)) + print("%-25s : %6.2f%%" % ("Nominations progress", p_progress)) + print("-" * 51) + print("%-25s : %5d" % ("Projects", counts['projects'])) + print("%-25s : %5d (%6.2f%%)" % ("Projects with candidates", + counts['with_candidate'], + p_candidate)) + print("%-25s : %5d (%6.2f%%)" % ("Projects with election", + counts['nominations'], + p_nominations)) + print("=" * 51) + print("%-25s @ %s" % ("Stats gathered", as_utctime(now))) diff --git a/openstack_election/utils.py b/openstack_election/utils.py index 6d4746de..d7066676 100644 --- a/openstack_election/utils.py +++ b/openstack_election/utils.py @@ -57,6 +57,14 @@ def load_exceptions(): exceptions[e.split(':')[0]] = " ".join(e.split(':')[1:])[:-1].strip() +def get_event(event_name): + for e in conf['timelines']: + if e['name'] == event_name: + d = datetime.datetime.strptime(e['date'], "%Y-%m-%dT%H:%M") + return d.replace(tzinfo=pytz.utc) + raise ValueError("Couldn't find event_name %s" % event_name) + + # Gerrit functions def gerrit_datetime(dt): return dt.strftime('%Y-%m-%d %H:%M:%S %z') diff --git a/setup.cfg b/setup.cfg index 4ad81b09..71c0bc51 100644 --- a/setup.cfg +++ b/setup.cfg @@ -23,7 +23,7 @@ console_scripts = check-all-candidacies = openstack_election.cmds.check_all_candidacies:main check-candidacy = openstack_election.cmds.check_candidacy:main check-candidacy-manual = openstack_election.cmds.check_manual:main - + render-statistics = openstack_election.cmds.render_statistics:main [build_sphinx] all_files = 1