Merge lp:~thumper/launchpad/claim-review-into-model-attempt2 into lp:launchpad/db-devel
- claim-review-into-model-attempt2
- Merge into db-devel
Proposed by
Tim Penhey
Status: | Rejected |
---|---|
Rejected by: | Tim Penhey |
Proposed branch: | lp:~thumper/launchpad/claim-review-into-model-attempt2 |
Merge into: | lp:launchpad/db-devel |
Prerequisite: | lp:~thumper/launchpad/claim-review-into-model |
Diff against target: |
534 lines (+243/-54) 14 files modified
lib/canonical/launchpad/interfaces/_schema_circular_imports.py (+2/-0) lib/lp/code/browser/branch.py (+1/-1) lib/lp/code/browser/branchmergeproposal.py (+2/-2) lib/lp/code/configure.zcml (+1/-1) lib/lp/code/errors.py (+63/-0) lib/lp/code/interfaces/branchmergeproposal.py (+28/-38) lib/lp/code/interfaces/codereviewvote.py (+4/-1) lib/lp/code/mail/codehandler.py (+2/-2) lib/lp/code/model/branch.py (+3/-2) lib/lp/code/model/branchmergeproposal.py (+36/-3) lib/lp/code/model/codereviewvote.py (+6/-0) lib/lp/code/model/tests/test_branch.py (+2/-2) lib/lp/code/model/tests/test_branchmergeproposals.py (+90/-2) lib/lp/code/stories/webservice/xx-branchmergeproposal.txt (+3/-0) |
To merge this branch: | bzr merge lp:~thumper/launchpad/claim-review-into-model-attempt2 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Canonical Launchpad Engineering | Pending | ||
Review via email: mp+15718@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Tim Penhey (thumper) wrote : | # |
Revision history for this message
Tim Penhey (thumper) wrote : | # |
I'm going to change the approach and make claimReview on the CodeReviewVoteR
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/canonical/launchpad/interfaces/_schema_circular_imports.py' |
2 | --- lib/canonical/launchpad/interfaces/_schema_circular_imports.py 2009-11-06 21:06:38 +0000 |
3 | +++ lib/canonical/launchpad/interfaces/_schema_circular_imports.py 2009-12-06 23:36:19 +0000 |
4 | @@ -111,6 +111,8 @@ |
5 | IBranchMergeProposal['all_comments'].value_type.schema = ICodeReviewComment |
6 | IBranchMergeProposal['nominateReviewer'].queryTaggedValue( |
7 | LAZR_WEBSERVICE_EXPORTED)['return_type'].schema = ICodeReviewVoteReference |
8 | +IBranchMergeProposal['claimReview'].queryTaggedValue( |
9 | + LAZR_WEBSERVICE_EXPORTED)['return_type'].schema = ICodeReviewVoteReference |
10 | IBranchMergeProposal['votes'].value_type.schema = ICodeReviewVoteReference |
11 | |
12 | IHasBranches['getBranches'].queryTaggedValue( |
13 | |
14 | === modified file 'lib/lp/code/browser/branch.py' |
15 | --- lib/lp/code/browser/branch.py 2009-11-25 23:25:51 +0000 |
16 | +++ lib/lp/code/browser/branch.py 2009-12-06 23:36:18 +0000 |
17 | @@ -80,10 +80,10 @@ |
18 | latest_proposals_for_each_branch) |
19 | from lp.code.enums import ( |
20 | BranchLifecycleStatus, BranchType, UICreatableBranchType) |
21 | +from lp.code.errors import InvalidBranchMergeProposal |
22 | from lp.code.interfaces.branch import ( |
23 | BranchCreationForbidden, BranchExists, IBranch, |
24 | user_has_special_branch_access) |
25 | -from lp.code.interfaces.branchmergeproposal import InvalidBranchMergeProposal |
26 | from lp.code.interfaces.branchtarget import IBranchTarget |
27 | from lp.code.interfaces.codeimport import CodeImportReviewStatus |
28 | from lp.code.interfaces.codeimportjob import ( |
29 | |
30 | === modified file 'lib/lp/code/browser/branchmergeproposal.py' |
31 | --- lib/lp/code/browser/branchmergeproposal.py 2009-11-24 01:53:32 +0000 |
32 | +++ lib/lp/code/browser/branchmergeproposal.py 2009-12-06 23:36:19 +0000 |
33 | @@ -71,8 +71,8 @@ |
34 | from lp.code.enums import ( |
35 | BranchMergeProposalStatus, BranchType, CodeReviewNotificationLevel, |
36 | CodeReviewVote) |
37 | -from lp.code.interfaces.branchmergeproposal import ( |
38 | - IBranchMergeProposal, WrongBranchMergeProposal) |
39 | +from lp.code.errors import WrongBranchMergeProposal |
40 | +from lp.code.interfaces.branchmergeproposal import IBranchMergeProposal |
41 | from lp.code.interfaces.codereviewcomment import ICodeReviewComment |
42 | from lp.code.interfaces.codereviewvote import ( |
43 | ICodeReviewVoteReference) |
44 | |
45 | === modified file 'lib/lp/code/configure.zcml' |
46 | --- lib/lp/code/configure.zcml 2009-11-16 22:53:42 +0000 |
47 | +++ lib/lp/code/configure.zcml 2009-12-06 23:36:18 +0000 |
48 | @@ -257,7 +257,7 @@ |
49 | updatePreviewDiff"/> |
50 | <require |
51 | permission="launchpad.AnyPerson" |
52 | - attributes=" |
53 | + attributes="claimReview |
54 | createComment |
55 | createCommentFromMessage"/> |
56 | </class> |
57 | |
58 | === added file 'lib/lp/code/errors.py' |
59 | --- lib/lp/code/errors.py 1970-01-01 00:00:00 +0000 |
60 | +++ lib/lp/code/errors.py 2009-12-06 23:36:18 +0000 |
61 | @@ -0,0 +1,63 @@ |
62 | +# Copyright 2009 Canonical Ltd. This software is licensed under the |
63 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
64 | + |
65 | +"""Errors used in the lp/code modules.""" |
66 | + |
67 | +__metaclass__ = type |
68 | +__all__ = [ |
69 | + 'BadBranchMergeProposalSearchContext', |
70 | + 'BadStateTransition', |
71 | + 'BranchMergeProposalExists', |
72 | + 'ClaimantHasPersonalReview', |
73 | + 'ClaimantNotInReviewerTeam', |
74 | + 'InvalidBranchMergeProposal', |
75 | + 'NoSuchReview', |
76 | + 'UserNotBranchReviewer', |
77 | + 'WrongBranchMergeProposal', |
78 | +] |
79 | + |
80 | + |
81 | +class BadBranchMergeProposalSearchContext(Exception): |
82 | + """The context is not valid for a branch merge proposal search.""" |
83 | + |
84 | + |
85 | +class BadStateTransition(Exception): |
86 | + """The user requested a state transition that is not possible.""" |
87 | + |
88 | + |
89 | +class ClaimantHasPersonalReview(Exception): |
90 | + """The claimant already has a personal review. """ |
91 | + |
92 | + |
93 | +class ClaimantNotInReviewerTeam(Exception): |
94 | + """The claimant is not in the reviewer team.""" |
95 | + |
96 | + |
97 | +class InvalidBranchMergeProposal(Exception): |
98 | + """Raised during the creation of a new branch merge proposal. |
99 | + |
100 | + The text of the exception is the rule violation. |
101 | + """ |
102 | + |
103 | + |
104 | +class BranchMergeProposalExists(InvalidBranchMergeProposal): |
105 | + """Raised if there is already a matching BranchMergeProposal.""" |
106 | + |
107 | + |
108 | +class NoSuchReview(Exception): |
109 | + """There is no review found for the reviewer.""" |
110 | + |
111 | + |
112 | +class UserNotBranchReviewer(Exception): |
113 | + """The user who attempted to review the merge proposal isn't a reviewer. |
114 | + |
115 | + A specific reviewer may be set on a branch. If a specific reviewer |
116 | + isn't set then any user in the team of the owner of the branch is |
117 | + considered a reviewer. |
118 | + """ |
119 | + |
120 | + |
121 | +class WrongBranchMergeProposal(Exception): |
122 | + """The comment requested is not associated with this merge proposal.""" |
123 | + |
124 | + |
125 | |
126 | === modified file 'lib/lp/code/interfaces/branchmergeproposal.py' |
127 | --- lib/lp/code/interfaces/branchmergeproposal.py 2009-10-23 00:48:47 +0000 |
128 | +++ lib/lp/code/interfaces/branchmergeproposal.py 2009-12-06 23:36:18 +0000 |
129 | @@ -7,11 +7,7 @@ |
130 | |
131 | __metaclass__ = type |
132 | __all__ = [ |
133 | - 'BadBranchMergeProposalSearchContext', |
134 | - 'BadStateTransition', |
135 | - 'BranchMergeProposalExists', |
136 | 'BRANCH_MERGE_PROPOSAL_FINAL_STATES', |
137 | - 'InvalidBranchMergeProposal', |
138 | 'IBranchMergeProposal', |
139 | 'IBranchMergeProposalGetter', |
140 | 'IBranchMergeProposalJob', |
141 | @@ -20,10 +16,9 @@ |
142 | 'ICreateMergeProposalJobSource', |
143 | 'IMergeProposalCreatedJob', |
144 | 'IMergeProposalCreatedJobSource', |
145 | - 'UserNotBranchReviewer', |
146 | - 'WrongBranchMergeProposal', |
147 | ] |
148 | |
149 | + |
150 | from lazr.lifecycle.event import ObjectModifiedEvent |
151 | from zope.event import notify |
152 | from zope.interface import Attribute, Interface |
153 | @@ -47,38 +42,6 @@ |
154 | REQUEST_USER) |
155 | |
156 | |
157 | -class InvalidBranchMergeProposal(Exception): |
158 | - """Raised during the creation of a new branch merge proposal. |
159 | - |
160 | - The text of the exception is the rule violation. |
161 | - """ |
162 | - |
163 | - |
164 | -class BranchMergeProposalExists(InvalidBranchMergeProposal): |
165 | - """Raised if there is already a matching BranchMergeProposal.""" |
166 | - |
167 | - |
168 | -class UserNotBranchReviewer(Exception): |
169 | - """The user who attempted to review the merge proposal isn't a reviewer. |
170 | - |
171 | - A specific reviewer may be set on a branch. If a specific reviewer |
172 | - isn't set then any user in the team of the owner of the branch is |
173 | - considered a reviewer. |
174 | - """ |
175 | - |
176 | - |
177 | -class BadStateTransition(Exception): |
178 | - """The user requested a state transition that is not possible.""" |
179 | - |
180 | - |
181 | -class WrongBranchMergeProposal(Exception): |
182 | - """The comment requested is not associated with this merge proposal.""" |
183 | - |
184 | - |
185 | -class BadBranchMergeProposalSearchContext(Exception): |
186 | - """The context is not valid for a branch merge proposal search.""" |
187 | - |
188 | - |
189 | BRANCH_MERGE_PROPOSAL_FINAL_STATES = ( |
190 | BranchMergeProposalStatus.REJECTED, |
191 | BranchMergeProposalStatus.MERGED, |
192 | @@ -445,6 +408,33 @@ |
193 | the details are updated. |
194 | """ |
195 | |
196 | + @operation_parameters( |
197 | + reviewer=Reference( |
198 | + title=_("A team with an existing pending review."), |
199 | + schema=IPerson), |
200 | + review_type=Text()) |
201 | + @call_with(claimant=REQUEST_USER) |
202 | + @operation_returns_entry(Interface) # Really ICodeReviewVoteReference |
203 | + @export_write_operation() |
204 | + def claimReview(claimant, reviewer, review_type=None): |
205 | + """Change a pending review for reviewer into a review for claimant. |
206 | + |
207 | + Pending team reviews can be claimed by members of that team. This |
208 | + allows reviews to be moved of the general team todo list, and onto a |
209 | + personal todo list. |
210 | + |
211 | + :param claimant: The person claiming the team review. |
212 | + :param reviewer: The team with a pending review. |
213 | + :param review_type: The review_type of the pending review. |
214 | + :return: The updated `CodeReviewVoteReference`. |
215 | + :raises ClaimantHasPersonalReview: If the claimant already has a |
216 | + personal review. |
217 | + :raises ClaimantNotInReviewerTeam: If the claimant is not in the |
218 | + reviewer team. |
219 | + :raises NoSuchReview: If there is no review found for the reviewer |
220 | + with the specified review_type. |
221 | + """ |
222 | + |
223 | def getUsersVoteReference(user): |
224 | """Get the existing vote reference for the given user. |
225 | |
226 | |
227 | === modified file 'lib/lp/code/interfaces/codereviewvote.py' |
228 | --- lib/lp/code/interfaces/codereviewvote.py 2009-10-09 04:15:55 +0000 |
229 | +++ lib/lp/code/interfaces/codereviewvote.py 2009-12-06 23:36:19 +0000 |
230 | @@ -9,7 +9,7 @@ |
231 | ] |
232 | |
233 | from zope.interface import Interface |
234 | -from zope.schema import Datetime, Int, TextLine |
235 | +from zope.schema import Bool, Datetime, Int, TextLine |
236 | |
237 | from canonical.launchpad import _ |
238 | from canonical.launchpad.fields import PublicPersonChoice |
239 | @@ -66,3 +66,6 @@ |
240 | "The code review comment that contains the most recent vote." |
241 | ), |
242 | required=True, schema=ICodeReviewComment)) |
243 | + |
244 | + is_pending = exported( |
245 | + Bool(title=_("Is the pending?"), required=True, readonly=True)) |
246 | |
247 | === modified file 'lib/lp/code/mail/codehandler.py' |
248 | --- lib/lp/code/mail/codehandler.py 2009-10-23 19:33:09 +0000 |
249 | +++ lib/lp/code/mail/codehandler.py 2009-12-06 23:36:18 +0000 |
250 | @@ -36,10 +36,10 @@ |
251 | from canonical.launchpad.webapp.interfaces import ILaunchBag |
252 | from lazr.uri import URI |
253 | from lp.code.enums import BranchType, CodeReviewVote |
254 | +from lp.code.errors import BranchMergeProposalExists, UserNotBranchReviewer |
255 | from lp.code.interfaces.branchlookup import IBranchLookup |
256 | from lp.code.interfaces.branchmergeproposal import ( |
257 | - BranchMergeProposalExists, IBranchMergeProposalGetter, |
258 | - ICreateMergeProposalJobSource, UserNotBranchReviewer) |
259 | + IBranchMergeProposalGetter, ICreateMergeProposalJobSource) |
260 | from lp.code.interfaces.branchnamespace import ( |
261 | lookup_branch_namespace, split_unique_name) |
262 | from lp.code.interfaces.branchtarget import check_default_stacked_on |
263 | |
264 | === modified file 'lib/lp/code/model/branch.py' |
265 | --- lib/lp/code/model/branch.py 2009-11-26 22:55:06 +0000 |
266 | +++ lib/lp/code/model/branch.py 2009-12-06 23:36:19 +0000 |
267 | @@ -47,6 +47,8 @@ |
268 | from lp.code.enums import ( |
269 | BranchLifecycleStatus, BranchMergeControlStatus, |
270 | BranchMergeProposalStatus, BranchType) |
271 | +from lp.code.errors import ( |
272 | + BranchMergeProposalExists, InvalidBranchMergeProposal) |
273 | from lp.code.mail.branch import send_branch_modified_notifications |
274 | from lp.code.model.branchmergeproposal import ( |
275 | BranchMergeProposal, BranchMergeProposalGetter) |
276 | @@ -63,8 +65,7 @@ |
277 | from lp.code.interfaces.branchcollection import IAllBranches |
278 | from lp.code.interfaces.branchlookup import IBranchLookup |
279 | from lp.code.interfaces.branchmergeproposal import ( |
280 | - BRANCH_MERGE_PROPOSAL_FINAL_STATES, BranchMergeProposalExists, |
281 | - InvalidBranchMergeProposal) |
282 | + BRANCH_MERGE_PROPOSAL_FINAL_STATES) |
283 | from lp.code.interfaces.branchnamespace import IBranchNamespacePolicy |
284 | from lp.code.interfaces.branchpuller import IBranchPuller |
285 | from lp.code.interfaces.branchtarget import IBranchTarget |
286 | |
287 | === modified file 'lib/lp/code/model/branchmergeproposal.py' |
288 | --- lib/lp/code/model/branchmergeproposal.py 2009-12-06 23:36:17 +0000 |
289 | +++ lib/lp/code/model/branchmergeproposal.py 2009-12-06 23:36:18 +0000 |
290 | @@ -30,6 +30,10 @@ |
291 | from canonical.database.sqlbase import quote, SQLBase, sqlvalues |
292 | |
293 | from lp.code.enums import BranchMergeProposalStatus, CodeReviewVote |
294 | +from lp.code.errors import ( |
295 | + BadBranchMergeProposalSearchContext, BadStateTransition, |
296 | + ClaimantHasPersonalReview, ClaimantNotInReviewerTeam, NoSuchReview, |
297 | + UserNotBranchReviewer, WrongBranchMergeProposal) |
298 | from lp.code.model.branchrevision import BranchRevision |
299 | from lp.code.model.codereviewcomment import CodeReviewComment |
300 | from lp.code.model.codereviewvote import ( |
301 | @@ -42,10 +46,8 @@ |
302 | from lp.code.interfaces.branch import IBranchNavigationMenu |
303 | from lp.code.interfaces.branchcollection import IAllBranches |
304 | from lp.code.interfaces.branchmergeproposal import ( |
305 | - BadBranchMergeProposalSearchContext, BadStateTransition, |
306 | BRANCH_MERGE_PROPOSAL_FINAL_STATES as FINAL_STATES, |
307 | - IBranchMergeProposal, IBranchMergeProposalGetter, UserNotBranchReviewer, |
308 | - WrongBranchMergeProposal) |
309 | + IBranchMergeProposal, IBranchMergeProposalGetter) |
310 | from lp.code.interfaces.branchtarget import IHasBranchTarget |
311 | from lp.registry.interfaces.person import IPerson |
312 | from lp.registry.interfaces.product import IProduct |
313 | @@ -538,6 +540,37 @@ |
314 | notify(ReviewerNominatedEvent(vote_reference)) |
315 | return vote_reference |
316 | |
317 | + def claimReview(self, claimant, reviewer, review_type=None): |
318 | + """See `IBranchMergeProposal`.""" |
319 | + review_type = self._normalizeReviewType(review_type) |
320 | + vote_reference = self.getUsersVoteReference(reviewer, review_type) |
321 | + if vote_reference is None: |
322 | + if review_type is None: |
323 | + error_str = 'No review found for %(reviewer)s' |
324 | + else: |
325 | + error_str = ( |
326 | + 'No "%(review_type)s" review found for %(reviewer)s') |
327 | + raise NoSuchReview( |
328 | + error_str % { |
329 | + 'reviewer': reviewer.unique_displayname, |
330 | + 'review_type': review_type}) |
331 | + claimant_review = self.getUsersVoteReference(claimant) |
332 | + if claimant_review is not None: |
333 | + if claimant_review.is_pending: |
334 | + error_str = '%s has an existing pending review' |
335 | + else: |
336 | + error_str = '%s has an existing personal review' |
337 | + raise ClaimantHasPersonalReview( |
338 | + error_str % claimant.unique_displayname) |
339 | + if not claimant.inTeam(reviewer): |
340 | + raise ClaimantNotInReviewerTeam( |
341 | + '%s is not a member of %s' % |
342 | + (claimant.unique_displayname, reviewer.unique_displayname)) |
343 | + # If we get to here then the claimant is allowed to claim the team |
344 | + # review. |
345 | + vote_reference.reviewer = claimant |
346 | + return vote_reference |
347 | + |
348 | def deleteProposal(self): |
349 | """See `IBranchMergeProposal`.""" |
350 | # Delete this proposal, but keep the superseded chain linked. |
351 | |
352 | === modified file 'lib/lp/code/model/codereviewvote.py' |
353 | --- lib/lp/code/model/codereviewvote.py 2009-06-25 04:06:00 +0000 |
354 | +++ lib/lp/code/model/codereviewvote.py 2009-12-06 23:36:19 +0000 |
355 | @@ -36,3 +36,9 @@ |
356 | review_type = StringCol(default=None) |
357 | comment = ForeignKey( |
358 | dbName='vote_message', foreignKey='CodeReviewComment', default=None) |
359 | + |
360 | + @property |
361 | + def is_pending(self): |
362 | + """See `ICodeReviewVote`""" |
363 | + # Reviews are pending if there is no associated comment. |
364 | + return self.comment is None |
365 | |
366 | === modified file 'lib/lp/code/model/tests/test_branch.py' |
367 | --- lib/lp/code/model/tests/test_branch.py 2009-11-25 23:24:58 +0000 |
368 | +++ lib/lp/code/model/tests/test_branch.py 2009-12-06 23:36:19 +0000 |
369 | @@ -37,6 +37,7 @@ |
370 | from lp.code.enums import ( |
371 | BranchLifecycleStatus, BranchSubscriptionNotificationLevel, BranchType, |
372 | BranchVisibilityRule, CodeReviewNotificationLevel) |
373 | +from lp.code.errors import InvalidBranchMergeProposal |
374 | from lp.code.interfaces.branch import ( |
375 | BranchCannotBePrivate, BranchCannotBePublic, |
376 | BranchCreatorNotMemberOfOwnerTeam, BranchCreatorNotOwner, |
377 | @@ -45,8 +46,7 @@ |
378 | from lp.code.interfaces.branchlookup import IBranchLookup |
379 | from lp.code.interfaces.branchnamespace import IBranchNamespaceSet |
380 | from lp.code.interfaces.branchmergeproposal import ( |
381 | - BRANCH_MERGE_PROPOSAL_FINAL_STATES as FINAL_STATES, |
382 | - InvalidBranchMergeProposal) |
383 | + BRANCH_MERGE_PROPOSAL_FINAL_STATES as FINAL_STATES) |
384 | from lp.code.interfaces.linkedbranch import ICanHasLinkedBranch |
385 | from lp.code.interfaces.seriessourcepackagebranch import ( |
386 | IFindOfficialBranchLinks) |
387 | |
388 | === modified file 'lib/lp/code/model/tests/test_branchmergeproposals.py' |
389 | --- lib/lp/code/model/tests/test_branchmergeproposals.py 2009-12-06 23:36:17 +0000 |
390 | +++ lib/lp/code/model/tests/test_branchmergeproposals.py 2009-12-06 23:36:19 +0000 |
391 | @@ -26,6 +26,9 @@ |
392 | from canonical.launchpad.interfaces import IPrivacy |
393 | from canonical.launchpad.interfaces.message import IMessageJob |
394 | from canonical.launchpad.webapp.testing import verifyObject |
395 | +from lp.code.errors import ( |
396 | + BadStateTransition, ClaimantHasPersonalReview, ClaimantNotInReviewerTeam, |
397 | + NoSuchReview, WrongBranchMergeProposal) |
398 | from lp.code.event.branchmergeproposal import ( |
399 | NewBranchMergeProposalEvent, NewCodeReviewCommentEvent, |
400 | ReviewerNominatedEvent) |
401 | @@ -36,11 +39,10 @@ |
402 | BranchType, CodeReviewNotificationLevel, CodeReviewVote, |
403 | BranchVisibilityRule) |
404 | from lp.code.interfaces.branchmergeproposal import ( |
405 | - BadStateTransition, |
406 | BRANCH_MERGE_PROPOSAL_FINAL_STATES as FINAL_STATES, |
407 | IBranchMergeProposal, IBranchMergeProposalGetter, IBranchMergeProposalJob, |
408 | ICreateMergeProposalJob, ICreateMergeProposalJobSource, |
409 | - IMergeProposalCreatedJob, notify_modified, WrongBranchMergeProposal) |
410 | + IMergeProposalCreatedJob, notify_modified) |
411 | from lp.code.model.branchmergeproposaljob import ( |
412 | BranchMergeProposalJob, BranchMergeProposalJobType, |
413 | CreateMergeProposalJob, MergeProposalCreatedJob, UpdatePreviewDiffJob) |
414 | @@ -1682,6 +1684,92 @@ |
415 | # Still only one vote. |
416 | self.assertEqual(1, len(list(merge_proposal.votes))) |
417 | |
418 | + |
419 | +class TestBranchMergeProposalClaimReview(TestCaseWithFactory): |
420 | + """Tests for BranchMergeProposal.claimReview.""" |
421 | + |
422 | + layer = DatabaseFunctionalLayer |
423 | + |
424 | + def setUp(self): |
425 | + TestCaseWithFactory.setUp(self) |
426 | + # Setup the proposal, claimant and team reviewer. |
427 | + self.bmp = self.factory.makeBranchMergeProposal() |
428 | + self.claimant = self.factory.makePerson() |
429 | + self.review_team = self.factory.makeTeam() |
430 | + |
431 | + def test_missing_review(self): |
432 | + # If no matching review is found, an exception is raised. |
433 | + login_person(self.claimant) |
434 | + self.assertRaises( |
435 | + NoSuchReview, |
436 | + self.bmp.claimReview, |
437 | + self.claimant, self.review_team) |
438 | + |
439 | + def _addPendingReview(self, review_type=None): |
440 | + """Add a pending review for the review_team.""" |
441 | + login_person(self.bmp.registrant) |
442 | + self.bmp.nominateReviewer( |
443 | + reviewer=self.review_team, |
444 | + registrant=self.bmp.registrant, |
445 | + review_type=review_type) |
446 | + |
447 | + def _addClaimantToReviewTeam(self): |
448 | + """Add the claimant to the review team.""" |
449 | + login_person(self.review_team.teamowner) |
450 | + self.review_team.addMember( |
451 | + person=self.claimant, reviewer=self.review_team.teamowner) |
452 | + |
453 | + def test_personal_completed_review(self): |
454 | + # If the claimant has a personal review already, then they can't claim |
455 | + # a pending team review. |
456 | + login_person(self.claimant) |
457 | + # Make sure that the personal review is done before the pending team |
458 | + # review, otherwise the pending team review will be claimed by this |
459 | + # one. |
460 | + self.bmp.createComment( |
461 | + self.claimant, 'Message subject', 'Message content', |
462 | + vote=CodeReviewVote.APPROVE) |
463 | + self._addPendingReview() |
464 | + self._addClaimantToReviewTeam() |
465 | + self.assertRaises( |
466 | + ClaimantHasPersonalReview, |
467 | + self.bmp.claimReview, |
468 | + self.claimant, self.review_team) |
469 | + |
470 | + def test_personal_pending_review(self): |
471 | + # If the claimant has a pending review already, then they can't claim |
472 | + # a pending team review. |
473 | + self._addPendingReview() |
474 | + self._addClaimantToReviewTeam() |
475 | + login_person(self.bmp.registrant) |
476 | + self.bmp.nominateReviewer( |
477 | + reviewer=self.claimant, |
478 | + registrant=self.bmp.registrant) |
479 | + login_person(self.claimant) |
480 | + self.assertRaises( |
481 | + ClaimantHasPersonalReview, |
482 | + self.bmp.claimReview, |
483 | + self.claimant, self.review_team) |
484 | + |
485 | + def test_personal_not_in_review_team(self): |
486 | + # If the claimant is not in the review team, an error is raised. |
487 | + self._addPendingReview() |
488 | + login_person(self.claimant) |
489 | + self.assertRaises( |
490 | + ClaimantNotInReviewerTeam, |
491 | + self.bmp.claimReview, |
492 | + self.claimant, self.review_team) |
493 | + |
494 | + def test_success(self): |
495 | + # If the claimant is in the review team, and does not have a personal |
496 | + # review, pending or completed, then they can claim the team review. |
497 | + self._addPendingReview() |
498 | + self._addClaimantToReviewTeam() |
499 | + login_person(self.claimant) |
500 | + result = self.bmp.claimReview(self.claimant, self.review_team) |
501 | + self.assertEqual(self.claimant, result.reviewer) |
502 | + |
503 | + |
504 | class TestBranchMergeProposalResubmit(TestCaseWithFactory): |
505 | |
506 | layer = DatabaseFunctionalLayer |
507 | |
508 | === modified file 'lib/lp/code/stories/webservice/xx-branchmergeproposal.txt' |
509 | --- lib/lp/code/stories/webservice/xx-branchmergeproposal.txt 2009-11-05 21:36:14 +0000 |
510 | +++ lib/lp/code/stories/webservice/xx-branchmergeproposal.txt 2009-12-06 23:36:19 +0000 |
511 | @@ -79,6 +79,7 @@ |
512 | branch_merge_proposal_link: u'http://api.launchpad.dev/beta/~.../+merge/...' |
513 | comment_link: None |
514 | date_created: u'...' |
515 | + is_pending: True |
516 | registrant_link: u'http://api.launchpad.dev/beta/~person-name...' |
517 | resource_type_link: u'http://api.launchpad.dev/beta/#code_review_vote_reference' |
518 | review_type: u'green' |
519 | @@ -194,6 +195,7 @@ |
520 | branch_merge_proposal_link: u'http://.../~source/fooix/fix-it/+merge/...' |
521 | comment_link: u'http://.../~source/fooix/fix-it/+merge/.../comments/...' |
522 | date_created: u'...' |
523 | + is_pending: False |
524 | registrant_link: u'http://.../~person-name...' |
525 | resource_type_link: u'http://.../#code_review_vote_reference' |
526 | review_type: u'code' |
527 | @@ -221,6 +223,7 @@ |
528 | branch_merge_proposal_link: u'http://.../~source/fooix/fix-it/+merge/...' |
529 | comment_link: None |
530 | date_created: u'...' |
531 | + is_pending: True |
532 | registrant_link: u'http://.../~target' |
533 | resource_type_link: u'http://.../#code_review_vote_reference' |
534 | review_type: u'code' |
Moves the logic of actually claiming a review into the model code itself and exposes it over the api.
This branch also creates a lp.code.errors module to hold our errors, like the lp.code.enums.
tests: geProposalClaim Review
TestBranchMer
and for the is_pending bit: xx-branchmergep roposal
webservice/