| |
@@ -25,9 +25,12 @@
|
| |
from sqlalchemy import func, desc, or_, and_
|
| |
import bugzilla
|
| |
from flask_fas_openid import fas_login_required
|
| |
+ import json
|
| |
+ import itertools
|
| |
|
| |
from blockerbugs import app, db, __version__
|
| |
from blockerbugs.util.bz_interface import BlockerProposal, BZInterfaceError
|
| |
+ from blockerbugs.util import pagure_bot
|
| |
from blockerbugs.models.bug import Bug
|
| |
from blockerbugs.models.milestone import Milestone
|
| |
from blockerbugs.models.update import Update
|
| |
@@ -178,6 +181,88 @@
|
| |
}
|
| |
|
| |
|
| |
+ def bugz_to_votes(bugz):
|
| |
+ """Returns votes for each bug in bugz in format:
|
| |
+ {
|
| |
+ bugid: {
|
| |
+ tracker_name: {
|
| |
+ "-1": ["nick1", "nick2"],
|
| |
+ "0": [],
|
| |
+ "+1": ["nick3"],
|
| |
+ }
|
| |
+ }
|
| |
+ }
|
| |
+ """
|
| |
+ # ignore milestone key and flatten
|
| |
+ all_bugz = itertools.chain(*bugz.values())
|
| |
+ votes = {}
|
| |
+ for bug in all_bugz:
|
| |
+ votes[bug.bugid] = json.loads(bug.votes)
|
| |
+ return votes
|
| |
+
|
| |
+
|
| |
+ def irc_voting_info(bugz):
|
| |
+ """Returns voting summary in IRC format for each bug in bugz:
|
| |
+ {
|
| |
+ bugid: "#info Ticket vote: ...\n#info Ticket vote: ..."
|
| |
+ }
|
| |
+ """
|
| |
+ voting_info = {}
|
| |
+ all_votes = bugz_to_votes(bugz)
|
| |
+ for bugid, votes in all_votes.items():
|
| |
+ info = ""
|
| |
+ for tracker, vote in votes.items():
|
| |
+ # if no one voted +1 or -1, don't show the info at all
|
| |
+ if not (vote['-1'] or vote['+1']):
|
| |
+ continue
|
| |
+ summary = f"(+{len(vote['+1'])},{len(vote['0'])},-{len(vote['-1'])})"
|
| |
+ pros = [f"+{person_vote}" for person_vote in vote['+1']]
|
| |
+ neutrals = [f"{person_vote}" for person_vote in vote['0']]
|
| |
+ cons = [f"-{person_vote}" for person_vote in vote['-1']]
|
| |
+ people = ", ".join(pros + neutrals + cons)
|
| |
+ info += f"#info Ticket vote: {pagure_bot.NICER[tracker]} {summary} ({people})\n"
|
| |
+ voting_info[bugid] = info.strip()
|
| |
+
|
| |
+ return voting_info
|
| |
+
|
| |
+
|
| |
+ def vote_count_tuple(votes, tracker_name):
|
| |
+ """Returns voting tuple for given tracker_name in format:
|
| |
+ (6, 0, 3) or None
|
| |
+ """
|
| |
+ vote = votes.get(tracker_name)
|
| |
+ if not vote:
|
| |
+ return None
|
| |
+
|
| |
+ return (len(vote['+1']), len(vote['0']), len(vote['-1']))
|
| |
+
|
| |
+
|
| |
+ def web_voting_info(bugz, milestone):
|
| |
+ """Returns voting tuple for each bug and each section in web UI,
|
| |
+ a dict in dict structure in format:
|
| |
+ {
|
| |
+ bugid: {
|
| |
+ 'Prioritized Bugs': None,
|
| |
+ 'Proposed Blockers': (6, 0, 3),
|
| |
+ ...
|
| |
+ }
|
| |
+ }
|
| |
+ """
|
| |
+ voting_info = {}
|
| |
+ all_votes = bugz_to_votes(bugz)
|
| |
+ for bugid, votes in all_votes.items():
|
| |
+ voting_info[bugid] = {
|
| |
+ 'Proposed Blockers': vote_count_tuple(votes, f'{milestone}blocker'),
|
| |
+ 'Accepted Blockers': vote_count_tuple(votes, f'{milestone}blocker'),
|
| |
+ 'Proposed Freeze Exceptions': vote_count_tuple(votes, f'{milestone}freezeexception'),
|
| |
+ 'Accepted Freeze Exceptions': vote_count_tuple(votes, f'{milestone}freezeexception'),
|
| |
+ 'Accepted 0-day Blockers': vote_count_tuple(votes, '0day'),
|
| |
+ 'Accepted Previous Release Blockers': vote_count_tuple(votes, 'previousrelease'),
|
| |
+ 'Prioritized Bugs': None # no discussion for prioritized bugs
|
| |
+ }
|
| |
+ return voting_info
|
| |
+
|
| |
+
|
| |
@main.route('/')
|
| |
def index():
|
| |
if app.debug:
|
| |
@@ -205,13 +290,15 @@
|
| |
bugz = get_milestone_bugs(milestone)
|
| |
recent_bugs = get_recent_modifications(milestone.id)
|
| |
whiteboard_change = get_recent_whiteboard_change(milestone.id)
|
| |
+ vote_info = web_voting_info(bugz, milestone.version)
|
| |
return render_template('blocker_list.html',
|
| |
buglists=bugz,
|
| |
recent=recent_bugs,
|
| |
wb_change=whiteboard_change,
|
| |
info=release_info,
|
| |
title="Fedora %s %s Blocker Bugs" % (
|
| |
- release_info['number'], release_info['phase']))
|
| |
+ release_info['number'], release_info['phase']),
|
| |
+ vote_info=vote_info)
|
| |
|
| |
|
| |
@main.route('/bug/<int:bugid>/updates')
|
| |
@@ -236,8 +323,9 @@
|
| |
abort(404)
|
| |
bugz = get_milestone_bugs(milestone)
|
| |
milestone_info = get_milestone_info(milestone)
|
| |
-
|
| |
- response = make_response(render_template('irc_format.txt', buglists=bugz, info=milestone_info))
|
| |
+ vote_info = irc_voting_info(bugz)
|
| |
+ response = make_response(render_template('irc_format.txt', buglists=bugz, info=milestone_info,
|
| |
+ vote_info=vote_info))
|
| |
response.mimetype = 'text/plain'
|
| |
return response
|
| |
|
| |
@@ -258,6 +346,7 @@
|
| |
updates=updates,
|
| |
title="Fedora %s %s Blocker Bug Updates" % (milestone_info['number'], milestone_info['phase']))
|
| |
|
| |
+
|
| |
@main.route('/milestone/<int:num>/<release_name>/requests')
|
| |
def display_release_requests(num, release_name):
|
| |
release = Release.query.filter_by(number=num).first()
|
| |
@@ -274,6 +363,7 @@
|
| |
response.mimetype = 'text/plain'
|
| |
return response
|
| |
|
| |
+
|
| |
@main.route('/milestone/<int:num>/<milestone_name>/need_testing')
|
| |
def display_updates_need_testing(num, milestone_name):
|
| |
release = Release.query.filter_by(number=num).first()
|
| |
Should fix #150