Skip to content

Commit 0c0980c

Browse files
author
Sasha Romijn
committed
Fix ietf-tools#2420 - Add reviewer back to top of the queue after rejected/withdrawn reviews.
- Legacy-Id: 17058
1 parent 8bb6955 commit 0c0980c

3 files changed

Lines changed: 48 additions & 5 deletions

File tree

ietf/doc/views_review.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,9 @@ def reject_reviewer_assignment(request, name, assignment_id):
363363
state=review_assignment.state,
364364
)
365365

366+
policy = get_reviewer_queue_policy(review_assignment.review_request.team)
367+
policy.return_reviewer_to_top_rotation(review_assignment.reviewer.person)
368+
366369
msg = render_to_string("review/reviewer_assignment_rejected.txt", {
367370
"by": request.user.person,
368371
"message_to_secretary": form.cleaned_data.get("message_to_secretary")
@@ -409,6 +412,9 @@ def withdraw_reviewer_assignment(request, name, assignment_id):
409412
state=review_assignment.state,
410413
)
411414

415+
policy = get_reviewer_queue_policy(review_assignment.review_request.team)
416+
policy.return_reviewer_to_top_rotation(review_assignment.reviewer.person)
417+
412418
msg = "Review assignment withdrawn by %s"%request.user.person
413419

414420
email_review_assignment_change(request, review_assignment, "Reviewer assignment withdrawn", msg, by=request.user.person, notify_secretary=True, notify_reviewer=True, notify_requested_by=False)

ietf/review/policies.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,14 @@ def default_reviewer_rotation_list(self, dont_skip_person_ids=None):
5050
Return a list of reviewers (Person objects) in the default reviewer rotation for a policy.
5151
"""
5252
raise NotImplementedError # pragma: no cover
53-
53+
54+
def return_reviewer_to_top_rotation(self, reviewer_person):
55+
"""
56+
Return a reviewer to the top of the rotation, e.g. because they rejected a review,
57+
and should retroactively not have been rotated over.
58+
"""
59+
raise NotImplementedError # pragma: no cover
60+
5461
def update_policy_state_for_assignment(self, assignee_person, add_skip=False):
5562
"""
5663
Update the skip_count if the assignment was in order, and
@@ -363,7 +370,6 @@ class RotateAlphabeticallyReviewerQueuePolicy(AbstractReviewerQueuePolicy):
363370
NextReviewerInTeam is used to store a pointer to where the queue is currently
364371
positioned.
365372
"""
366-
367373
def default_reviewer_rotation_list(self, include_unavailable=False, dont_skip_person_ids=None):
368374
reviewers = list(Person.objects.filter(role__name="reviewer", role__group=self.team))
369375
reviewers.sort(key=lambda p: p.last_name())
@@ -393,6 +399,14 @@ def default_reviewer_rotation_list(self, include_unavailable=False, dont_skip_pe
393399

394400
return rotation_list
395401

402+
def return_reviewer_to_top_rotation(self, reviewer_person):
403+
# As RotateAlphabetically does not keep a full rotation list,
404+
# returning someone to a particular order is complex.
405+
# Instead, the "assign me next" flag is set.
406+
settings = self._reviewer_settings_for(reviewer_person)
407+
settings.request_assignment_next = True
408+
settings.save()
409+
396410

397411
class LeastRecentlyUsedReviewerQueuePolicy(AbstractReviewerQueuePolicy):
398412
"""
@@ -418,6 +432,12 @@ def default_reviewer_rotation_list(self, include_unavailable=False, dont_skip_pe
418432

419433
return rotation_list
420434

435+
def return_reviewer_to_top_rotation(self, reviewer_person):
436+
# Reviewer rotation for this policy ignored rejected/withdrawn
437+
# reviews, so it automatically adjusts the position of someone
438+
# who rejected a review and no action is needed.
439+
pass
440+
421441

422442
QUEUE_POLICY_NAME_MAPPING = {
423443
'RotateAlphabetically': RotateAlphabeticallyReviewerQueuePolicy,

ietf/review/test_policies.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ def test_invalid_policy_name(self):
3535
get_reviewer_queue_policy(team)
3636

3737

38-
class RotateAlphabeticallyReviewerQueuePolicyTest(TestCase):
38+
class RotateAlphabeticallyReviewerAndGenericQueuePolicyTest(TestCase):
3939
"""
40-
These tests also cover the common behaviour in RotateAlphabeticallyReviewerQueuePolicy,
40+
These tests also cover the common behaviour in AbstractReviewerQueuePolicy,
4141
as that's difficult to test on it's own.
4242
"""
4343
def test_default_reviewer_rotation_list(self):
@@ -197,7 +197,16 @@ def get_skip_next(person):
197197
self.assertEqual(get_skip_next(reviewers[3]), 1)
198198
self.assertEqual(get_skip_next(reviewers[4]), 0)
199199

200-
200+
def test_return_reviewer_to_top_rotation(self):
201+
team = ReviewTeamFactory(acronym="rotationteam", name="Review Team",
202+
list_email="rotationteam@ietf.org",
203+
parent=Group.objects.get(acronym="farfut"))
204+
reviewer = create_person(team, "reviewer", name="reviewer", username="reviewer")
205+
policy = RotateAlphabeticallyReviewerQueuePolicy(team)
206+
policy.return_reviewer_to_top_rotation(reviewer)
207+
self.assertTrue(ReviewerSettings.objects.get(person=reviewer).request_assignment_next)
208+
209+
201210
class LeastRecentlyUsedReviewerQueuePolicyTest(TestCase):
202211
"""
203212
These tests only cover where this policy deviates from
@@ -255,6 +264,14 @@ def test_default_reviewer_rotation_list(self):
255264
self.assertNotIn(unavailable_reviewer, rotation)
256265
self.assertEqual(rotation, [reviewers[2], reviewers[3], reviewers[4], reviewers[0], reviewers[1]])
257266

267+
def test_return_reviewer_to_top_rotation(self):
268+
team = ReviewTeamFactory(acronym="rotationteam", name="Review Team",
269+
list_email="rotationteam@ietf.org",
270+
parent=Group.objects.get(acronym="farfut"))
271+
reviewer = create_person(team, "reviewer", name="reviewer", username="reviewer")
272+
policy = LeastRecentlyUsedReviewerQueuePolicy(team)
273+
policy.return_reviewer_to_top_rotation(reviewer)
274+
258275

259276
class AssignmentOrderResolverTests(TestCase):
260277
def test_determine_ranking(self):

0 commit comments

Comments
 (0)