Merge lp:~thumper/launchpad/set-empty-review-type-as-none into lp:launchpad

Proposed by Tim Penhey
Status: Merged
Merged at revision: 9960
Proposed branch: lp:~thumper/launchpad/set-empty-review-type-as-none
Merge into: lp:launchpad
Diff against target: 173 lines (+86/-31)
2 files modified
lib/lp/code/model/branchmergeproposal.py (+19/-7)
lib/lp/code/model/tests/test_branchmergeproposals.py (+67/-24)
To merge this branch: bzr merge lp:~thumper/launchpad/set-empty-review-type-as-none
Reviewer Review Type Date Requested Status
Michael Hudson-Doyle Approve
Review via email: mp+15302@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Tim Penhey (thumper) wrote :

The failure to claim team reviews was primarily due to the mismatch between '' and None and the ways that the zope form machinery, the api and the email interface interact.

This branch normalizes the review_type at the model level to avoid this complication.

tests:
  TestBranchMergeProposalNominateReviewer

Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :

As said on IRC:

In test_pending_review_registrant it's not super obvious to me that the merge_proposal.registrant is who's passed into nominateReviewer, could you give makeProposalWithReviewer an optional "requester" argument?

All else fine, nice to get this little mystery under control.

Revision history for this message
Michael Hudson-Doyle (mwhudson) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/code/model/branchmergeproposal.py'
--- lib/lp/code/model/branchmergeproposal.py 2009-11-11 02:33:20 +0000
+++ lib/lp/code/model/branchmergeproposal.py 2009-11-27 03:48:14 +0000
@@ -502,13 +502,27 @@
502 self.syncUpdate()502 self.syncUpdate()
503 return proposal503 return proposal
504504
505 def _normalizeReviewType(self, review_type):
506 """Normalse the review type.
507
508 If review_type is None, it stays None. Otherwise the review_type is
509 converted to lower case, and if the string is empty is gets changed to
510 None.
511 """
512 if review_type is not None:
513 review_type = review_type.strip()
514 if review_type == '':
515 review_type = None
516 else:
517 review_type = review_type.lower()
518 return review_type
519
505 def nominateReviewer(self, reviewer, registrant, review_type=None,520 def nominateReviewer(self, reviewer, registrant, review_type=None,
506 _date_created=DEFAULT, _notify_listeners=True):521 _date_created=DEFAULT, _notify_listeners=True):
507 """See `IBranchMergeProposal`."""522 """See `IBranchMergeProposal`."""
508 # Return the existing vote reference or create a new one.523 # Return the existing vote reference or create a new one.
509 # Lower case the review type.524 # Lower case the review type.
510 if review_type is not None:525 review_type = self._normalizeReviewType(review_type)
511 review_type = review_type.lower()
512 vote_reference = self.getUsersVoteReference(reviewer, review_type)526 vote_reference = self.getUsersVoteReference(reviewer, review_type)
513 if vote_reference is None:527 if vote_reference is None:
514 vote_reference = CodeReviewVoteReference(528 vote_reference = CodeReviewVoteReference(
@@ -559,6 +573,7 @@
559 #:param _date_created: The date the message was created. Provided573 #:param _date_created: The date the message was created. Provided
560 # only for testing purposes, as it can break574 # only for testing purposes, as it can break
561 # BranchMergeProposal.root_message.575 # BranchMergeProposal.root_message.
576 review_type = self._normalizeReviewType(review_type)
562 assert owner is not None, 'Merge proposal messages need a sender'577 assert owner is not None, 'Merge proposal messages need a sender'
563 parent_message = None578 parent_message = None
564 if parent is not None:579 if parent is not None:
@@ -590,8 +605,7 @@
590 def getUsersVoteReference(self, user, review_type=None):605 def getUsersVoteReference(self, user, review_type=None):
591 """Get the existing vote reference for the given user."""606 """Get the existing vote reference for the given user."""
592 # Lower case the review type.607 # Lower case the review type.
593 if review_type is not None:608 review_type = self._normalizeReviewType(review_type)
594 review_type = review_type.lower()
595 if user is None:609 if user is None:
596 return None610 return None
597 if user.is_team:611 if user.is_team:
@@ -656,9 +670,7 @@
656 """See `IBranchMergeProposal`."""670 """See `IBranchMergeProposal`."""
657 if _validate:671 if _validate:
658 validate_message(original_email)672 validate_message(original_email)
659 # Lower case the review type.673 review_type = self._normalizeReviewType(review_type)
660 if review_type is not None:
661 review_type = review_type.lower()
662 code_review_message = CodeReviewComment(674 code_review_message = CodeReviewComment(
663 branch_merge_proposal=self, message=message, vote=vote,675 branch_merge_proposal=self, message=message, vote=vote,
664 vote_tag=review_type)676 vote_tag=review_type)
665677
=== modified file 'lib/lp/code/model/tests/test_branchmergeproposals.py'
--- lib/lp/code/model/tests/test_branchmergeproposals.py 2009-11-03 21:05:14 +0000
+++ lib/lp/code/model/tests/test_branchmergeproposals.py 2009-11-27 03:48:14 +0000
@@ -1437,39 +1437,82 @@
1437 merge_proposal = self.factory.makeBranchMergeProposal()1437 merge_proposal = self.factory.makeBranchMergeProposal()
1438 self.assertEqual([], list(merge_proposal.votes))1438 self.assertEqual([], list(merge_proposal.votes))
14391439
1440 def makeProposalWithReviewer(self, reviewer=None, review_type=None,
1441 registrant=None):
1442 """Make a proposal and request a review from reviewer.
1443
1444 If no reviewer is passed in, make a reviewer.
1445 """
1446 if reviewer is None:
1447 reviewer = self.factory.makePerson()
1448 merge_proposal = self.factory.makeBranchMergeProposal()
1449 if registrant is None:
1450 registrant = merge_proposal.registrant
1451 login_person(merge_proposal.source_branch.owner)
1452 merge_proposal.nominateReviewer(
1453 reviewer=reviewer, registrant=registrant, review_type=review_type)
1454 return merge_proposal, reviewer
1455
1456 def test_pending_review_registrant(self):
1457 # The registrant passed into the nominateReviewer call is the
1458 # registrant of the vote reference.
1459 registrant = self.factory.makePerson()
1460 merge_proposal, reviewer = self.makeProposalWithReviewer(
1461 registrant=registrant)
1462 vote_reference = list(merge_proposal.votes)[0]
1463 self.assertEqual(registrant, vote_reference.registrant)
1464
1465 def assertOneReviewPending(self, merge_proposal, reviewer, review_type):
1466 # Check that there is one and only one review pending with the
1467 # specified reviewer and review_type.
1468 votes = list(merge_proposal.votes)
1469 self.assertEqual(1, len(votes))
1470 vote_reference = votes[0]
1471 self.assertEqual(reviewer, vote_reference.reviewer)
1472 if review_type is None:
1473 self.assertIs(None, vote_reference.review_type)
1474 else:
1475 self.assertEqual(review_type, vote_reference.review_type)
1476 self.assertIs(None, vote_reference.comment)
1477
1440 def test_nominate_creates_reference(self):1478 def test_nominate_creates_reference(self):
1441 """A new vote reference is created when a reviewer is nominated."""1479 # A new vote reference is created when a reviewer is nominated.
1442 merge_proposal = self.factory.makeBranchMergeProposal()1480 merge_proposal, reviewer = self.makeProposalWithReviewer(
1443 login_person(merge_proposal.source_branch.owner)
1444 reviewer = self.factory.makePerson()
1445 merge_proposal.nominateReviewer(
1446 reviewer=reviewer,
1447 registrant=merge_proposal.source_branch.owner,
1448 review_type='General')1481 review_type='General')
1449 votes = list(merge_proposal.votes)1482 self.assertOneReviewPending(merge_proposal, reviewer, 'general')
1450 self.assertEqual(1, len(votes))1483
1451 vote_reference = votes[0]1484 def test_nominate_with_None_review_type(self):
1452 self.assertEqual(reviewer, vote_reference.reviewer)1485 # Reviews nominated with a review type of None, make vote references
1453 self.assertEqual(merge_proposal.source_branch.owner,1486 # with a review_type of None.
1454 vote_reference.registrant)1487 merge_proposal, reviewer = self.makeProposalWithReviewer(
1455 self.assertEqual('general', vote_reference.review_type)1488 review_type=None)
1489 self.assertOneReviewPending(merge_proposal, reviewer, None)
1490
1491 def test_nominate_with_whitespace_review_type(self):
1492 # A review nominated with a review type that just contains whitespace
1493 # or the empty string, makes a vote reference with a review_type of
1494 # None.
1495 merge_proposal, reviewer = self.makeProposalWithReviewer(
1496 review_type='')
1497 self.assertOneReviewPending(merge_proposal, reviewer, None)
1498 merge_proposal, reviewer = self.makeProposalWithReviewer(
1499 review_type=' ')
1500 self.assertOneReviewPending(merge_proposal, reviewer, None)
1501 merge_proposal, reviewer = self.makeProposalWithReviewer(
1502 review_type='\t')
1503 self.assertOneReviewPending(merge_proposal, reviewer, None)
14561504
1457 def test_nominate_multiple_with_different_types(self):1505 def test_nominate_multiple_with_different_types(self):
1458 # While an individual can only be requested to do one review1506 # While an individual can only be requested to do one review
1459 # (test_nominate_updates_reference) a team can have multiple1507 # (test_nominate_updates_reference) a team can have multiple
1460 # nominations for different review types.1508 # nominations for different review types.
1461 merge_proposal = self.factory.makeBranchMergeProposal()
1462 login_person(merge_proposal.source_branch.owner)
1463 reviewer = self.factory.makePerson()1509 reviewer = self.factory.makePerson()
1464 review_team = self.factory.makeTeam(owner=reviewer)1510 review_team = self.factory.makeTeam(owner=reviewer)
1465 merge_proposal.nominateReviewer(1511 merge_proposal, reviewer = self.makeProposalWithReviewer(
1466 reviewer=review_team,1512 reviewer=review_team, review_type='general-1')
1467 registrant=merge_proposal.source_branch.owner,1513 merge_proposal.nominateReviewer(
1468 review_type='general-1')1514 reviewer=review_team,
1469 # Second nomination of the same type fails.1515 registrant=merge_proposal.registrant,
1470 merge_proposal.nominateReviewer(
1471 reviewer=review_team,
1472 registrant=merge_proposal.source_branch.owner,
1473 review_type='general-2')1516 review_type='general-2')
14741517
1475 votes = list(merge_proposal.votes)1518 votes = list(merge_proposal.votes)