blob: 5e1a3bbf8ca7f91da5b405bcc21db9ef0622cd6e [file] [log] [blame]
# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is govered by a BSD-style
# license that can be found in the LICENSE file or at
"""Classes that implement the ranked issue dependency rerank functionality
Summary of classes:
IssueRerank: Process changes to the ranking of blocked on issues
import httplib
import logging
from framework import exceptions
from framework import jsonfeed
from framework import permissions
from tracker import rerank_helpers
from tracker import tracker_helpers
from tracker import tracker_bizobj
from tracker import tracker_views
class IssueRerank(jsonfeed.JsonFeed):
"""IssueRerank is a servlet which reranks issue dependencies"""
def AssertBasePermission(self, mr):
super(IssueRerank, self).AssertBasePermission(mr)
if (mr.target_id and mr.moved_ids and mr.split_above):
parent =, mr.parent_id)
config =, mr.project_id)
granted_perms = tracker_bizobj.GetGrantedPerms(
parent, mr.auth.effective_ids, config)
edit_perm = self.CheckPerm(
mr, permissions.EDIT_ISSUE, art=parent, granted_perms=granted_perms)
if not edit_perm:
raise permissions.PermissionException(
'You are not allowed to re-rank issue dependencies.')
def HandleRequest(self, mr):
if not mr.parent_id:'No parent issue specified.')
raise exceptions.InputException('No issue specified.')
all_issues = self._GetIssues(mr)
parent = all_issues.get(mr.parent_id)
if not parent:'Parent issue not found: %d', mr.parent_id)
raise exceptions.InputException('Parent issue not found.')
open_related, closed_related = (
tracker_helpers.GetAllowedOpenAndClosedRelatedIssues(, mr, parent))
changed_ranks = self._GetNewRankings(mr, all_issues, open_related)
if changed_ranks:
mr.cnxn, mr.parent_id, changed_ranks)
parent =, mr.parent_id)
blocked_on_issues =
mr.cnxn, parent.blocked_on_iids)
blocked_on_irvs = [
mr.project_name, blocked_on_issues.get(issue_id),
open_related, closed_related)
for issue_id in parent.blocked_on_iids]
dangling_blocked_on_irvs = [
tracker_views.DanglingIssueRefView(ref.project, ref.issue_id)
for ref in parent.dangling_blocked_on_refs]
issues = [{
'display_name': irv.display_name,
'issue_id': irv.issue_id,
'issue_ref': irv.issue_ref,
'summary': irv.summary,
'url': irv.url,
'is_open': irv.is_open,
'is_dangling': False,
} for irv in blocked_on_irvs if irv.visible]
'display_name': irv.display_name,
'issue_ref': irv.issue_ref,
'summary': irv.summary,
'url': irv.url,
'is_open': irv.is_open,
'is_dangling': True,
} for irv in dangling_blocked_on_irvs if irv.visible])
return {'issues': issues}
def _GetIssues(self, mr):
all_issue_ids = [mr.parent_id]
if mr.target_id:
if mr.moved_ids:
return, all_issue_ids)
def _GetNewRankings(self, mr, all_issues, open_related):
"""Compute new issue reference rankings."""
missing = False
if not (mr.target_id):'No target_id.')
missing = True
if not (mr.moved_ids):'No moved_ids.')
missing = True
if mr.split_above is None:'No split_above.')
missing = True
if missing:
target = all_issues.get(mr.target_id)
moved = [all_issues.get(moved_id) for moved_id in mr.moved_ids]
if not target:'Target issue not found: %d.', mr.target_id)
raise exceptions.InputException('Target issue not found.')
if None in moved:'Invalid moved issue id(s) in %r.', mr.moved_ids)
raise exceptions.InputException('Moved issue not found.')
'Moving issue(s) %r %s issue %d.',
mr.moved_ids, 'above' if mr.split_above else 'below', mr.target_id)
open_ids = [iid for iid in open_related.keys() if iid not in mr.moved_ids]
lower, higher = tracker_bizobj.SplitBlockedOnRanks(
all_issues.get(mr.parent_id), mr.target_id, mr.split_above, open_ids)
return rerank_helpers.GetInsertRankings(lower, higher, mr.moved_ids)