~launchpad-pqm/launchpad/devel

8687.15.17 by Karl Fogel
Add the copyright header block to the rest of the files under lib/lp/.
1
# Copyright 2009 Canonical Ltd.  This software is licensed under the
2
# GNU Affero General Public License version 3 (see the file LICENSE).
6438.2.3 by Tim Penhey
Add the tables for reviews done, and requested reviews.
3
4
"""CodeReviewVoteReference database class."""
5
6
__metaclass__ = type
7
__all__ = [
8
    'CodeReviewVoteReference',
9
    ]
10
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
11
from sqlobject import (
12
    ForeignKey,
13
    StringCol,
14
    )
6438.2.3 by Tim Penhey
Add the tables for reviews done, and requested reviews.
15
from zope.interface import implements
7719.2.16 by Paul Hummer
Implemented IBranchMergeProposal.id
16
from zope.schema import Int
6438.2.3 by Tim Penhey
Add the tables for reviews done, and requested reviews.
17
5608.9.3 by Aaron Bentley
Add CodeReviewVote.date_created
18
from canonical.database.constants import DEFAULT
19
from canonical.database.datetimecol import UtcDateTimeCol
5608.9.1 by Aaron Bentley
Initial cut of CodeReviewVote support
20
from canonical.database.sqlbase import SQLBase
7675.429.14 by Tim Penhey
Move the method into the model.
21
from lp.code.errors import (
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
22
    ClaimReviewFailed,
23
    ReviewNotPending,
24
    UserHasExistingReview,
25
    )
8138.1.2 by Jonathan Lange
Run migrater over lp.code. Many tests broken and imports failing.
26
from lp.code.interfaces.codereviewvote import ICodeReviewVoteReference
8555.2.9 by Tim Penhey
Move CodeReviewVote enum.
27
28
6438.2.1 by Tim Penhey
Renamed the CodeReviewVote class to avoid name clash with CodeReviewVote enumerated type.
29
class CodeReviewVoteReference(SQLBase):
5608.9.16 by Aaron Bentley
Updates from review
30
    """See `ICodeReviewVote`"""
31
6438.2.1 by Tim Penhey
Renamed the CodeReviewVote class to avoid name clash with CodeReviewVote enumerated type.
32
    implements(ICodeReviewVoteReference)
5608.9.1 by Aaron Bentley
Initial cut of CodeReviewVote support
33
34
    _table = 'CodeReviewVote'
7719.2.16 by Paul Hummer
Implemented IBranchMergeProposal.id
35
    id = Int()
5608.9.1 by Aaron Bentley
Initial cut of CodeReviewVote support
36
    branch_merge_proposal = ForeignKey(
37
        dbName='branch_merge_proposal', foreignKey='BranchMergeProposal',
38
        notNull=True)
5608.9.3 by Aaron Bentley
Add CodeReviewVote.date_created
39
    date_created = UtcDateTimeCol(notNull=True, default=DEFAULT)
5608.9.1 by Aaron Bentley
Initial cut of CodeReviewVote support
40
    registrant = ForeignKey(
41
        dbName='registrant', foreignKey='Person', notNull=True)
42
    reviewer = ForeignKey(
43
        dbName='reviewer', foreignKey='Person', notNull=True)
6438.2.3 by Tim Penhey
Add the tables for reviews done, and requested reviews.
44
    review_type = StringCol(default=None)
6438.2.1 by Tim Penhey
Renamed the CodeReviewVote class to avoid name clash with CodeReviewVote enumerated type.
45
    comment = ForeignKey(
46
        dbName='vote_message', foreignKey='CodeReviewComment', default=None)
7675.429.2 by Tim Penhey
Add is_pending attribute to code review vote.
47
48
    @property
49
    def is_pending(self):
50
        """See `ICodeReviewVote`"""
51
        # Reviews are pending if there is no associated comment.
52
        return self.comment is None
7675.430.3 by Tim Penhey
Move the claimReview method to the CodeReviewVoteReference.
53
7675.429.16 by Tim Penhey
Move validation out into separate methods.
54
    def _validatePending(self):
55
        """Raise if the review is not pending."""
56
        if not self.is_pending:
57
            raise ReviewNotPending('The review is not pending.')
58
59
    def _validateNoReviewForUser(self, user):
60
        """Make sure there isn't an existing review for the user."""
61
        bmp = self.branch_merge_proposal
62
        existing_review = bmp.getUsersVoteReference(user)
63
        if existing_review is not None:
64
            if existing_review.is_pending:
65
                error_str = '%s has already been asked to review this'
66
            else:
67
                error_str = '%s has already reviewed this'
68
            raise UserHasExistingReview(error_str % user.unique_displayname)
69
70
    def validateClaimReview(self, claimant):
7675.430.3 by Tim Penhey
Move the claimReview method to the CodeReviewVoteReference.
71
        """See `ICodeReviewVote`"""
7675.429.16 by Tim Penhey
Move validation out into separate methods.
72
        self._validatePending()
7675.430.3 by Tim Penhey
Move the claimReview method to the CodeReviewVoteReference.
73
        if not self.reviewer.is_team:
74
            raise ClaimReviewFailed('Cannot claim non-team reviews.')
75
        if not claimant.inTeam(self.reviewer):
76
            raise ClaimReviewFailed(
77
                '%s is not a member of %s' %
78
                (claimant.unique_displayname,
79
                 self.reviewer.unique_displayname))
7675.429.16 by Tim Penhey
Move validation out into separate methods.
80
        self._validateNoReviewForUser(claimant)
81
82
    def claimReview(self, claimant):
83
        """See `ICodeReviewVote`"""
84
        self.validateClaimReview(claimant)
7675.430.3 by Tim Penhey
Move the claimReview method to the CodeReviewVoteReference.
85
        self.reviewer = claimant
7675.429.12 by Tim Penhey
Allow the deletion of pending reviews.
86
7675.429.16 by Tim Penhey
Move validation out into separate methods.
87
    def validateReasignReview(self, reviewer):
88
        """See `ICodeReviewVote`"""
89
        self._validatePending()
90
        if not reviewer.is_team:
91
            self._validateNoReviewForUser(reviewer)
92
7675.429.14 by Tim Penhey
Move the method into the model.
93
    def reassignReview(self, reviewer):
94
        """See `ICodeReviewVote`"""
7675.429.16 by Tim Penhey
Move validation out into separate methods.
95
        self.validateReasignReview(reviewer)
7675.429.14 by Tim Penhey
Move the method into the model.
96
        self.reviewer = reviewer
97
7675.429.12 by Tim Penhey
Allow the deletion of pending reviews.
98
    def delete(self):
99
        """See `ICodeReviewVote`"""
100
        if not self.is_pending:
101
            raise ReviewNotPending('The review is not pending.')
102
        self.destroySelf()