Merge lp:~stevenk/launchpad/preload-landing_candidates into lp:launchpad
- preload-landing_candidates
- Merge into devel
Proposed by
Steve Kowalik
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 16507 | ||||
Proposed branch: | lp:~stevenk/launchpad/preload-landing_candidates | ||||
Merge into: | lp:launchpad | ||||
Diff against target: |
502 lines (+80/-95) 3 files modified
lib/lp/code/browser/branch.py (+8/-1) lib/lp/code/browser/tests/test_branch.py (+69/-93) lib/lp/code/configure.zcml (+3/-1) |
||||
To merge this branch: | bzr merge lp:~stevenk/launchpad/preload-landing_candidates | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
William Grant | code | Approve | |
Review via email: mp+150255@code.launchpad.net |
Commit message
Preload candidate branches in BranchView.
Description of the change
Preload candidate branches in BranchView.
Clean up a bunch of test_branch, having it use create_view or create_
To post a comment you must log in.
Revision history for this message
William Grant (wgrant) : | # |
review:
Approve
(code)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/lp/code/browser/branch.py' | |||
2 | --- lib/lp/code/browser/branch.py 2013-02-21 05:43:21 +0000 | |||
3 | +++ lib/lp/code/browser/branch.py 2013-02-25 05:26:21 +0000 | |||
4 | @@ -127,11 +127,14 @@ | |||
5 | 127 | from lp.code.interfaces.branchmergeproposal import IBranchMergeProposal | 127 | from lp.code.interfaces.branchmergeproposal import IBranchMergeProposal |
6 | 128 | from lp.code.interfaces.branchtarget import IBranchTarget | 128 | from lp.code.interfaces.branchtarget import IBranchTarget |
7 | 129 | from lp.code.interfaces.codereviewvote import ICodeReviewVoteReference | 129 | from lp.code.interfaces.codereviewvote import ICodeReviewVoteReference |
8 | 130 | from lp.code.model.branch import Branch | ||
9 | 131 | from lp.code.model.branchcollection import GenericBranchCollection | ||
10 | 130 | from lp.registry.interfaces.person import IPersonSet | 132 | from lp.registry.interfaces.person import IPersonSet |
11 | 131 | from lp.registry.interfaces.productseries import IProductSeries | 133 | from lp.registry.interfaces.productseries import IProductSeries |
12 | 132 | from lp.registry.vocabularies import UserTeamsParticipationPlusSelfVocabulary | 134 | from lp.registry.vocabularies import UserTeamsParticipationPlusSelfVocabulary |
13 | 133 | from lp.services import searchbuilder | 135 | from lp.services import searchbuilder |
14 | 134 | from lp.services.config import config | 136 | from lp.services.config import config |
15 | 137 | from lp.services.database.bulk import load_related | ||
16 | 135 | from lp.services.database.constants import UTC_NOW | 138 | from lp.services.database.constants import UTC_NOW |
17 | 136 | from lp.services.feeds.browser import ( | 139 | from lp.services.feeds.browser import ( |
18 | 137 | BranchFeedLink, | 140 | BranchFeedLink, |
19 | @@ -554,7 +557,11 @@ | |||
20 | 554 | @cachedproperty | 557 | @cachedproperty |
21 | 555 | def landing_candidates(self): | 558 | def landing_candidates(self): |
22 | 556 | """Return a decorated list of landing candidates.""" | 559 | """Return a decorated list of landing candidates.""" |
24 | 557 | candidates = self.context.landing_candidates | 560 | candidates = list(self.context.landing_candidates) |
25 | 561 | branches = load_related( | ||
26 | 562 | Branch, candidates, ['source_branchID', 'prerequisite_branchID']) | ||
27 | 563 | GenericBranchCollection.preloadVisibleStackedOnBranches( | ||
28 | 564 | branches, self.user) | ||
29 | 558 | return [proposal for proposal in candidates | 565 | return [proposal for proposal in candidates |
30 | 559 | if check_permission('launchpad.View', proposal)] | 566 | if check_permission('launchpad.View', proposal)] |
31 | 560 | 567 | ||
32 | 561 | 568 | ||
33 | === modified file 'lib/lp/code/browser/tests/test_branch.py' | |||
34 | --- lib/lp/code/browser/tests/test_branch.py 2012-11-14 15:45:10 +0000 | |||
35 | +++ lib/lp/code/browser/tests/test_branch.py 2013-02-25 05:26:21 +0000 | |||
36 | @@ -1,4 +1,4 @@ | |||
38 | 1 | # Copyright 2009-2012 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2009-2013 Canonical Ltd. This software is licensed under the |
39 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
40 | 3 | 3 | ||
41 | 4 | """Unit tests for BranchView.""" | 4 | """Unit tests for BranchView.""" |
42 | @@ -10,6 +10,8 @@ | |||
43 | 10 | 10 | ||
44 | 11 | from BeautifulSoup import BeautifulSoup | 11 | from BeautifulSoup import BeautifulSoup |
45 | 12 | import pytz | 12 | import pytz |
46 | 13 | from storm.store import Store | ||
47 | 14 | from testtools.matchers import Equals | ||
48 | 13 | from zope.component import getUtility | 15 | from zope.component import getUtility |
49 | 14 | from zope.publisher.interfaces import NotFound | 16 | from zope.publisher.interfaces import NotFound |
50 | 15 | from zope.security.proxy import removeSecurityProxy | 17 | from zope.security.proxy import removeSecurityProxy |
51 | @@ -22,12 +24,7 @@ | |||
52 | 22 | BugTaskStatus, | 24 | BugTaskStatus, |
53 | 23 | UNRESOLVED_BUGTASK_STATUSES, | 25 | UNRESOLVED_BUGTASK_STATUSES, |
54 | 24 | ) | 26 | ) |
61 | 25 | from lp.code.browser.branch import ( | 27 | from lp.code.browser.branch import BranchMirrorStatusView |
56 | 26 | BranchMirrorStatusView, | ||
57 | 27 | BranchReviewerEditView, | ||
58 | 28 | BranchView, | ||
59 | 29 | ) | ||
60 | 30 | from lp.code.browser.branchlisting import PersonOwnedBranchesView | ||
62 | 31 | from lp.code.bzr import ( | 28 | from lp.code.bzr import ( |
63 | 32 | BranchFormat, | 29 | BranchFormat, |
64 | 33 | ControlFormat, | 30 | ControlFormat, |
65 | @@ -48,6 +45,7 @@ | |||
66 | 48 | login_person, | 45 | login_person, |
67 | 49 | logout, | 46 | logout, |
68 | 50 | person_logged_in, | 47 | person_logged_in, |
69 | 48 | StormStatementRecorder, | ||
70 | 51 | TestCaseWithFactory, | 49 | TestCaseWithFactory, |
71 | 52 | ) | 50 | ) |
72 | 53 | from lp.testing.layers import ( | 51 | from lp.testing.layers import ( |
73 | @@ -57,6 +55,7 @@ | |||
74 | 57 | from lp.testing.matchers import ( | 55 | from lp.testing.matchers import ( |
75 | 58 | BrowsesWithQueryLimit, | 56 | BrowsesWithQueryLimit, |
76 | 59 | Contains, | 57 | Contains, |
77 | 58 | HasQueryCount, | ||
78 | 60 | ) | 59 | ) |
79 | 61 | from lp.testing.pages import ( | 60 | from lp.testing.pages import ( |
80 | 62 | extract_text, | 61 | extract_text, |
81 | @@ -76,7 +75,7 @@ | |||
82 | 76 | layer = LaunchpadFunctionalLayer | 75 | layer = LaunchpadFunctionalLayer |
83 | 77 | 76 | ||
84 | 78 | def setUp(self): | 77 | def setUp(self): |
86 | 79 | TestCaseWithFactory.setUp(self) | 78 | super(TestBranchMirrorHidden, self).setUp() |
87 | 80 | config.push( | 79 | config.push( |
88 | 81 | "test", dedent("""\ | 80 | "test", dedent("""\ |
89 | 82 | [codehosting] | 81 | [codehosting] |
90 | @@ -85,15 +84,14 @@ | |||
91 | 85 | 84 | ||
92 | 86 | def tearDown(self): | 85 | def tearDown(self): |
93 | 87 | config.pop("test") | 86 | config.pop("test") |
95 | 88 | TestCaseWithFactory.tearDown(self) | 87 | super(TestBranchMirrorHidden, self).tearDown() |
96 | 89 | 88 | ||
97 | 90 | def testNormalBranch(self): | 89 | def testNormalBranch(self): |
98 | 91 | # A branch from a normal location is fine. | 90 | # A branch from a normal location is fine. |
99 | 92 | branch = self.factory.makeAnyBranch( | 91 | branch = self.factory.makeAnyBranch( |
100 | 93 | branch_type=BranchType.MIRRORED, | 92 | branch_type=BranchType.MIRRORED, |
101 | 94 | url="http://example.com/good/mirror") | 93 | url="http://example.com/good/mirror") |
104 | 95 | view = BranchView(branch, LaunchpadTestRequest()) | 94 | view = create_initialized_view(branch, '+index') |
103 | 96 | view.initialize() | ||
105 | 97 | self.assertTrue(view.user is None) | 95 | self.assertTrue(view.user is None) |
106 | 98 | self.assertEqual( | 96 | self.assertEqual( |
107 | 99 | "http://example.com/good/mirror", view.mirror_location) | 97 | "http://example.com/good/mirror", view.mirror_location) |
108 | @@ -101,10 +99,8 @@ | |||
109 | 101 | def testLocationlessRemoteBranch(self): | 99 | def testLocationlessRemoteBranch(self): |
110 | 102 | # A branch from a normal location is fine. | 100 | # A branch from a normal location is fine. |
111 | 103 | branch = self.factory.makeAnyBranch( | 101 | branch = self.factory.makeAnyBranch( |
116 | 104 | branch_type=BranchType.REMOTE, | 102 | branch_type=BranchType.REMOTE, url=None) |
117 | 105 | url=None) | 103 | view = create_initialized_view(branch, '+index') |
114 | 106 | view = BranchView(branch, LaunchpadTestRequest()) | ||
115 | 107 | view.initialize() | ||
118 | 108 | self.assertTrue(view.user is None) | 104 | self.assertTrue(view.user is None) |
119 | 109 | self.assertIs(None, view.mirror_location) | 105 | self.assertIs(None, view.mirror_location) |
120 | 110 | 106 | ||
121 | @@ -114,11 +110,9 @@ | |||
122 | 114 | branch = self.factory.makeAnyBranch( | 110 | branch = self.factory.makeAnyBranch( |
123 | 115 | branch_type=BranchType.MIRRORED, | 111 | branch_type=BranchType.MIRRORED, |
124 | 116 | url="http://private.example.com/bzr-mysql/mysql-5.0") | 112 | url="http://private.example.com/bzr-mysql/mysql-5.0") |
127 | 117 | view = BranchView(branch, LaunchpadTestRequest()) | 113 | view = create_initialized_view(branch, '+index') |
126 | 118 | view.initialize() | ||
128 | 119 | self.assertTrue(view.user is None) | 114 | self.assertTrue(view.user is None) |
131 | 120 | self.assertEqual( | 115 | self.assertEqual("<private server>", view.mirror_location) |
130 | 121 | "<private server>", view.mirror_location) | ||
132 | 122 | 116 | ||
133 | 123 | def testHiddenBranchAsBranchOwner(self): | 117 | def testHiddenBranchAsBranchOwner(self): |
134 | 124 | # A branch location with a defined private host is visible to the | 118 | # A branch location with a defined private host is visible to the |
135 | @@ -126,12 +120,10 @@ | |||
136 | 126 | owner = self.factory.makePerson(email="eric@example.com") | 120 | owner = self.factory.makePerson(email="eric@example.com") |
137 | 127 | branch = self.factory.makeAnyBranch( | 121 | branch = self.factory.makeAnyBranch( |
138 | 128 | branch_type=BranchType.MIRRORED, | 122 | branch_type=BranchType.MIRRORED, |
141 | 129 | owner=owner, | 123 | owner=owner, url="http://private.example.com/bzr-mysql/mysql-5.0") |
140 | 130 | url="http://private.example.com/bzr-mysql/mysql-5.0") | ||
142 | 131 | # Now log in the owner. | 124 | # Now log in the owner. |
143 | 132 | login('eric@example.com') | 125 | login('eric@example.com') |
146 | 133 | view = BranchView(branch, LaunchpadTestRequest()) | 126 | view = create_initialized_view(branch, '+index') |
145 | 134 | view.initialize() | ||
147 | 135 | self.assertEqual(view.user, owner) | 127 | self.assertEqual(view.user, owner) |
148 | 136 | self.assertEqual( | 128 | self.assertEqual( |
149 | 137 | "http://private.example.com/bzr-mysql/mysql-5.0", | 129 | "http://private.example.com/bzr-mysql/mysql-5.0", |
150 | @@ -143,33 +135,26 @@ | |||
151 | 143 | owner = self.factory.makePerson(email="eric@example.com") | 135 | owner = self.factory.makePerson(email="eric@example.com") |
152 | 144 | other = self.factory.makePerson(email="other@example.com") | 136 | other = self.factory.makePerson(email="other@example.com") |
153 | 145 | branch = self.factory.makeAnyBranch( | 137 | branch = self.factory.makeAnyBranch( |
156 | 146 | branch_type=BranchType.MIRRORED, | 138 | branch_type=BranchType.MIRRORED, owner=owner, |
155 | 147 | owner=owner, | ||
157 | 148 | url="http://private.example.com/bzr-mysql/mysql-5.0") | 139 | url="http://private.example.com/bzr-mysql/mysql-5.0") |
158 | 149 | # Now log in the other person. | 140 | # Now log in the other person. |
159 | 150 | login('other@example.com') | 141 | login('other@example.com') |
162 | 151 | view = BranchView(branch, LaunchpadTestRequest()) | 142 | view = create_initialized_view(branch, '+index') |
161 | 152 | view.initialize() | ||
163 | 153 | self.assertEqual(view.user, other) | 143 | self.assertEqual(view.user, other) |
166 | 154 | self.assertEqual( | 144 | self.assertEqual("<private server>", view.mirror_location) |
165 | 155 | "<private server>", view.mirror_location) | ||
167 | 156 | 145 | ||
168 | 157 | 146 | ||
169 | 158 | class TestBranchView(BrowserTestCase): | 147 | class TestBranchView(BrowserTestCase): |
170 | 159 | 148 | ||
171 | 160 | layer = DatabaseFunctionalLayer | 149 | layer = DatabaseFunctionalLayer |
172 | 161 | 150 | ||
173 | 162 | def setUp(self): | ||
174 | 163 | super(TestBranchView, self).setUp() | ||
175 | 164 | self.request = LaunchpadTestRequest() | ||
176 | 165 | |||
177 | 166 | def testMirrorStatusMessageIsTruncated(self): | 151 | def testMirrorStatusMessageIsTruncated(self): |
178 | 167 | """mirror_status_message is truncated if the text is overly long.""" | 152 | """mirror_status_message is truncated if the text is overly long.""" |
179 | 168 | branch = self.factory.makeBranch(branch_type=BranchType.MIRRORED) | 153 | branch = self.factory.makeBranch(branch_type=BranchType.MIRRORED) |
180 | 169 | branch.mirrorFailed( | 154 | branch.mirrorFailed( |
181 | 170 | "on quick brown fox the dog jumps to" * | 155 | "on quick brown fox the dog jumps to" * |
182 | 171 | BranchMirrorStatusView.MAXIMUM_STATUS_MESSAGE_LENGTH) | 156 | BranchMirrorStatusView.MAXIMUM_STATUS_MESSAGE_LENGTH) |
184 | 172 | branch_view = BranchMirrorStatusView(branch, self.request) | 157 | branch_view = create_view(branch, '+mirror-status') |
185 | 173 | self.assertEqual( | 158 | self.assertEqual( |
186 | 174 | truncate_text(branch.mirror_status_message, | 159 | truncate_text(branch.mirror_status_message, |
187 | 175 | branch_view.MAXIMUM_STATUS_MESSAGE_LENGTH) + ' ...', | 160 | branch_view.MAXIMUM_STATUS_MESSAGE_LENGTH) + ' ...', |
188 | @@ -179,7 +164,7 @@ | |||
189 | 179 | """mirror_status_message on the view is the same as on the branch.""" | 164 | """mirror_status_message on the view is the same as on the branch.""" |
190 | 180 | branch = self.factory.makeBranch(branch_type=BranchType.MIRRORED) | 165 | branch = self.factory.makeBranch(branch_type=BranchType.MIRRORED) |
191 | 181 | branch.mirrorFailed("This is a short error message.") | 166 | branch.mirrorFailed("This is a short error message.") |
193 | 182 | branch_view = BranchMirrorStatusView(branch, self.request) | 167 | branch_view = create_view(branch, '+mirror-status') |
194 | 183 | self.assertTrue( | 168 | self.assertTrue( |
195 | 184 | len(branch.mirror_status_message) | 169 | len(branch.mirror_status_message) |
196 | 185 | <= branch_view.MAXIMUM_STATUS_MESSAGE_LENGTH, | 170 | <= branch_view.MAXIMUM_STATUS_MESSAGE_LENGTH, |
197 | @@ -194,18 +179,16 @@ | |||
198 | 194 | def testShowMergeLinksOnManyBranchProject(self): | 179 | def testShowMergeLinksOnManyBranchProject(self): |
199 | 195 | # The merge links are shown on projects that have multiple branches. | 180 | # The merge links are shown on projects that have multiple branches. |
200 | 196 | product = self.factory.makeProduct(name='super-awesome-project') | 181 | product = self.factory.makeProduct(name='super-awesome-project') |
202 | 197 | branch1 = self.factory.makeAnyBranch(product=product) | 182 | branch = self.factory.makeAnyBranch(product=product) |
203 | 198 | self.factory.makeAnyBranch(product=product) | 183 | self.factory.makeAnyBranch(product=product) |
206 | 199 | view = BranchView(branch1, self.request) | 184 | view = create_initialized_view(branch, '+index') |
205 | 200 | view.initialize() | ||
207 | 201 | self.assertTrue(view.show_merge_links) | 185 | self.assertTrue(view.show_merge_links) |
208 | 202 | 186 | ||
209 | 203 | def testShowMergeLinksOnJunkBranch(self): | 187 | def testShowMergeLinksOnJunkBranch(self): |
210 | 204 | # The merge links are not shown on junk branches because they do not | 188 | # The merge links are not shown on junk branches because they do not |
211 | 205 | # support merge proposals. | 189 | # support merge proposals. |
212 | 206 | junk_branch = self.factory.makeBranch(product=None) | 190 | junk_branch = self.factory.makeBranch(product=None) |
215 | 207 | view = BranchView(junk_branch, self.request) | 191 | view = create_initialized_view(junk_branch, '+index') |
214 | 208 | view.initialize() | ||
216 | 209 | self.assertFalse(view.show_merge_links) | 192 | self.assertFalse(view.show_merge_links) |
217 | 210 | 193 | ||
218 | 211 | def testShowMergeLinksOnSingleBranchProject(self): | 194 | def testShowMergeLinksOnSingleBranchProject(self): |
219 | @@ -213,17 +196,14 @@ | |||
220 | 213 | # only has one branch because it's pointless to propose it for merging | 196 | # only has one branch because it's pointless to propose it for merging |
221 | 214 | # if there's nothing to merge into. | 197 | # if there's nothing to merge into. |
222 | 215 | branch = self.factory.makeAnyBranch() | 198 | branch = self.factory.makeAnyBranch() |
225 | 216 | view = BranchView(branch, self.request) | 199 | view = create_initialized_view(branch, '+index') |
224 | 217 | view.initialize() | ||
226 | 218 | self.assertFalse(view.show_merge_links) | 200 | self.assertFalse(view.show_merge_links) |
227 | 219 | 201 | ||
228 | 220 | def testNoProductSeriesPushingTranslations(self): | 202 | def testNoProductSeriesPushingTranslations(self): |
229 | 221 | # By default, a branch view shows no product series pushing | 203 | # By default, a branch view shows no product series pushing |
230 | 222 | # translations to the branch. | 204 | # translations to the branch. |
231 | 223 | branch = self.factory.makeBranch() | 205 | branch = self.factory.makeBranch() |
235 | 224 | 206 | view = create_initialized_view(branch, '+index') | |
233 | 225 | view = BranchView(branch, self.request) | ||
234 | 226 | view.initialize() | ||
236 | 227 | self.assertEqual(list(view.translations_sources()), []) | 207 | self.assertEqual(list(view.translations_sources()), []) |
237 | 228 | 208 | ||
238 | 229 | def testProductSeriesPushingTranslations(self): | 209 | def testProductSeriesPushingTranslations(self): |
239 | @@ -233,16 +213,13 @@ | |||
240 | 233 | trunk = product.getSeries('trunk') | 213 | trunk = product.getSeries('trunk') |
241 | 234 | branch = self.factory.makeBranch(owner=product.owner) | 214 | branch = self.factory.makeBranch(owner=product.owner) |
242 | 235 | removeSecurityProxy(trunk).translations_branch = branch | 215 | removeSecurityProxy(trunk).translations_branch = branch |
246 | 236 | 216 | view = create_initialized_view(branch, '+index') | |
244 | 237 | view = BranchView(branch, self.request) | ||
245 | 238 | view.initialize() | ||
247 | 239 | self.assertEqual(list(view.translations_sources()), [trunk]) | 217 | self.assertEqual(list(view.translations_sources()), [trunk]) |
248 | 240 | 218 | ||
249 | 241 | def test_is_empty_directory(self): | 219 | def test_is_empty_directory(self): |
250 | 242 | # Branches are considered empty until they get a control format. | 220 | # Branches are considered empty until they get a control format. |
251 | 243 | branch = self.factory.makeBranch() | 221 | branch = self.factory.makeBranch() |
254 | 244 | view = BranchView(branch, self.request) | 222 | view = create_initialized_view(branch, '+index') |
253 | 245 | view.initialize() | ||
255 | 246 | self.assertTrue(view.is_empty_directory) | 223 | self.assertTrue(view.is_empty_directory) |
256 | 247 | with person_logged_in(branch.owner): | 224 | with person_logged_in(branch.owner): |
257 | 248 | # Make it look as though the branch has been pushed. | 225 | # Make it look as though the branch has been pushed. |
258 | @@ -541,6 +518,24 @@ | |||
259 | 541 | browser = self.getUserBrowser(url, user=user) | 518 | browser = self.getUserBrowser(url, user=user) |
260 | 542 | self.assertIn(product_name, browser.contents) | 519 | self.assertIn(product_name, browser.contents) |
261 | 543 | 520 | ||
262 | 521 | def test_query_count_landing_candidates(self): | ||
263 | 522 | product = self.factory.makeProduct() | ||
264 | 523 | branch = self.factory.makeBranch(product=product) | ||
265 | 524 | for i in range(10): | ||
266 | 525 | self.factory.makeBranchMergeProposal(target_branch=branch) | ||
267 | 526 | stacked = self.factory.makeBranch(product=product) | ||
268 | 527 | source = self.factory.makeBranch(stacked_on=stacked, product=product) | ||
269 | 528 | prereq = self.factory.makeBranch(product=product) | ||
270 | 529 | self.factory.makeBranchMergeProposal( | ||
271 | 530 | source_branch=source, target_branch=branch, | ||
272 | 531 | prerequisite_branch=prereq) | ||
273 | 532 | Store.of(branch).flush() | ||
274 | 533 | Store.of(branch).invalidate() | ||
275 | 534 | view = create_view(branch, '+index') | ||
276 | 535 | with StormStatementRecorder() as recorder: | ||
277 | 536 | view.landing_candidates | ||
278 | 537 | self.assertThat(recorder, HasQueryCount(Equals(5))) | ||
279 | 538 | |||
280 | 544 | 539 | ||
281 | 545 | class TestBranchViewPrivateArtifacts(BrowserTestCase): | 540 | class TestBranchViewPrivateArtifacts(BrowserTestCase): |
282 | 546 | """ Tests that branches with private team artifacts can be viewed. | 541 | """ Tests that branches with private team artifacts can be viewed. |
283 | @@ -733,28 +728,23 @@ | |||
284 | 733 | # the branch. | 728 | # the branch. |
285 | 734 | branch = self.factory.makeAnyBranch() | 729 | branch = self.factory.makeAnyBranch() |
286 | 735 | self.assertIs(None, branch.reviewer) | 730 | self.assertIs(None, branch.reviewer) |
291 | 736 | view = BranchReviewerEditView(branch, LaunchpadTestRequest()) | 731 | view = create_view(branch, '+reviewer') |
292 | 737 | self.assertEqual( | 732 | self.assertEqual(branch.owner, view.initial_values['reviewer']) |
289 | 738 | branch.owner, | ||
290 | 739 | view.initial_values['reviewer']) | ||
293 | 740 | 733 | ||
294 | 741 | def test_initial_reviewer_set(self): | 734 | def test_initial_reviewer_set(self): |
295 | 742 | # If the reviewer has been set, it is shown as the initial value. | 735 | # If the reviewer has been set, it is shown as the initial value. |
296 | 743 | branch = self.factory.makeAnyBranch() | 736 | branch = self.factory.makeAnyBranch() |
297 | 744 | login_person(branch.owner) | 737 | login_person(branch.owner) |
298 | 745 | branch.reviewer = self.factory.makePerson() | 738 | branch.reviewer = self.factory.makePerson() |
303 | 746 | view = BranchReviewerEditView(branch, LaunchpadTestRequest()) | 739 | view = create_view(branch, '+reviewer') |
304 | 747 | self.assertEqual( | 740 | self.assertEqual(branch.reviewer, view.initial_values['reviewer']) |
301 | 748 | branch.reviewer, | ||
302 | 749 | view.initial_values['reviewer']) | ||
305 | 750 | 741 | ||
306 | 751 | def test_set_reviewer(self): | 742 | def test_set_reviewer(self): |
307 | 752 | # Test setting the reviewer. | 743 | # Test setting the reviewer. |
308 | 753 | branch = self.factory.makeAnyBranch() | 744 | branch = self.factory.makeAnyBranch() |
309 | 754 | reviewer = self.factory.makePerson() | 745 | reviewer = self.factory.makePerson() |
310 | 755 | login_person(branch.owner) | 746 | login_person(branch.owner) |
313 | 756 | view = BranchReviewerEditView(branch, LaunchpadTestRequest()) | 747 | view = create_initialized_view(branch, '+reviewer') |
312 | 757 | view.initialize() | ||
314 | 758 | view.change_action.success({'reviewer': reviewer}) | 748 | view.change_action.success({'reviewer': reviewer}) |
315 | 759 | self.assertEqual(reviewer, branch.reviewer) | 749 | self.assertEqual(reviewer, branch.reviewer) |
316 | 760 | # Last modified has been updated. | 750 | # Last modified has been updated. |
317 | @@ -767,8 +757,7 @@ | |||
318 | 767 | branch = self.factory.makeAnyBranch() | 757 | branch = self.factory.makeAnyBranch() |
319 | 768 | login_person(branch.owner) | 758 | login_person(branch.owner) |
320 | 769 | branch.reviewer = self.factory.makePerson() | 759 | branch.reviewer = self.factory.makePerson() |
323 | 770 | view = BranchReviewerEditView(branch, LaunchpadTestRequest()) | 760 | view = create_initialized_view(branch, '+reviewer') |
322 | 771 | view.initialize() | ||
324 | 772 | view.change_action.success({'reviewer': branch.owner}) | 761 | view.change_action.success({'reviewer': branch.owner}) |
325 | 773 | self.assertIs(None, branch.reviewer) | 762 | self.assertIs(None, branch.reviewer) |
326 | 774 | # Last modified has been updated. | 763 | # Last modified has been updated. |
327 | @@ -781,8 +770,7 @@ | |||
328 | 781 | # modified is not updated. | 770 | # modified is not updated. |
329 | 782 | modified_date = datetime(2007, 1, 1, tzinfo=pytz.UTC) | 771 | modified_date = datetime(2007, 1, 1, tzinfo=pytz.UTC) |
330 | 783 | branch = self.factory.makeAnyBranch(date_created=modified_date) | 772 | branch = self.factory.makeAnyBranch(date_created=modified_date) |
333 | 784 | view = BranchReviewerEditView(branch, LaunchpadTestRequest()) | 773 | view = create_initialized_view(branch, '+reviewer') |
332 | 785 | view.initialize() | ||
334 | 786 | view.change_action.success({'reviewer': branch.owner}) | 774 | view.change_action.success({'reviewer': branch.owner}) |
335 | 787 | self.assertIs(None, branch.reviewer) | 775 | self.assertIs(None, branch.reviewer) |
336 | 788 | # Last modified has not been updated. | 776 | # Last modified has not been updated. |
337 | @@ -803,8 +791,8 @@ | |||
338 | 803 | # the development focus branch. | 791 | # the development focus branch. |
339 | 804 | login_person(product.owner) | 792 | login_person(product.owner) |
340 | 805 | product.development_focus.branch = branch | 793 | product.development_focus.branch = branch |
343 | 806 | view = PersonOwnedBranchesView(branch.owner, LaunchpadTestRequest()) | 794 | view = create_initialized_view( |
344 | 807 | view.initialize() | 795 | branch.owner, '+ownedbranches', rootsite='code') |
345 | 808 | navigator = view.branches() | 796 | navigator = view.branches() |
346 | 809 | [decorated_branch] = navigator.branches | 797 | [decorated_branch] = navigator.branches |
347 | 810 | self.assertEqual("lp://dev/fooix", decorated_branch.bzr_identity) | 798 | self.assertEqual("lp://dev/fooix", decorated_branch.bzr_identity) |
348 | @@ -815,15 +803,12 @@ | |||
349 | 815 | 803 | ||
350 | 816 | layer = DatabaseFunctionalLayer | 804 | layer = DatabaseFunctionalLayer |
351 | 817 | 805 | ||
352 | 818 | def setUp(self): | ||
353 | 819 | TestCaseWithFactory.setUp(self) | ||
354 | 820 | |||
355 | 821 | def test_public_target(self): | 806 | def test_public_target(self): |
356 | 822 | # If the user can see the target, then there are merges, and the | 807 | # If the user can see the target, then there are merges, and the |
357 | 823 | # landing_target is available for the template rendering. | 808 | # landing_target is available for the template rendering. |
358 | 824 | bmp = self.factory.makeBranchMergeProposal() | 809 | bmp = self.factory.makeBranchMergeProposal() |
359 | 825 | branch = bmp.source_branch | 810 | branch = bmp.source_branch |
361 | 826 | view = BranchView(branch, LaunchpadTestRequest()) | 811 | view = create_view(branch, '+index') |
362 | 827 | self.assertFalse(view.no_merges) | 812 | self.assertFalse(view.no_merges) |
363 | 828 | [target] = view.landing_targets | 813 | [target] = view.landing_targets |
364 | 829 | # Check the ids as the target is a DecoratedMergeProposal. | 814 | # Check the ids as the target is a DecoratedMergeProposal. |
365 | @@ -835,7 +820,7 @@ | |||
366 | 835 | branch = bmp.source_branch | 820 | branch = bmp.source_branch |
367 | 836 | removeSecurityProxy(bmp.target_branch).information_type = ( | 821 | removeSecurityProxy(bmp.target_branch).information_type = ( |
368 | 837 | InformationType.USERDATA) | 822 | InformationType.USERDATA) |
370 | 838 | view = BranchView(branch, LaunchpadTestRequest()) | 823 | view = create_view(branch, '+index') |
371 | 839 | self.assertTrue(view.no_merges) | 824 | self.assertTrue(view.no_merges) |
372 | 840 | self.assertEqual([], view.landing_targets) | 825 | self.assertEqual([], view.landing_targets) |
373 | 841 | 826 | ||
374 | @@ -844,7 +829,7 @@ | |||
375 | 844 | # landing_candidate is available for the template rendering. | 829 | # landing_candidate is available for the template rendering. |
376 | 845 | bmp = self.factory.makeBranchMergeProposal() | 830 | bmp = self.factory.makeBranchMergeProposal() |
377 | 846 | branch = bmp.target_branch | 831 | branch = bmp.target_branch |
379 | 847 | view = BranchView(branch, LaunchpadTestRequest()) | 832 | view = create_view(branch, '+index') |
380 | 848 | self.assertFalse(view.no_merges) | 833 | self.assertFalse(view.no_merges) |
381 | 849 | [candidate] = view.landing_candidates | 834 | [candidate] = view.landing_candidates |
382 | 850 | # Check the ids as the target is a DecoratedMergeProposal. | 835 | # Check the ids as the target is a DecoratedMergeProposal. |
383 | @@ -857,7 +842,7 @@ | |||
384 | 857 | branch = bmp.target_branch | 842 | branch = bmp.target_branch |
385 | 858 | removeSecurityProxy(bmp.source_branch).information_type = ( | 843 | removeSecurityProxy(bmp.source_branch).information_type = ( |
386 | 859 | InformationType.USERDATA) | 844 | InformationType.USERDATA) |
388 | 860 | view = BranchView(branch, LaunchpadTestRequest()) | 845 | view = create_view(branch, '+index') |
389 | 861 | self.assertTrue(view.no_merges) | 846 | self.assertTrue(view.no_merges) |
390 | 862 | self.assertEqual([], view.landing_candidates) | 847 | self.assertEqual([], view.landing_candidates) |
391 | 863 | 848 | ||
392 | @@ -866,7 +851,7 @@ | |||
393 | 866 | # there are merges. | 851 | # there are merges. |
394 | 867 | branch = self.factory.makeProductBranch() | 852 | branch = self.factory.makeProductBranch() |
395 | 868 | bmp = self.factory.makeBranchMergeProposal(prerequisite_branch=branch) | 853 | bmp = self.factory.makeBranchMergeProposal(prerequisite_branch=branch) |
397 | 869 | view = BranchView(branch, LaunchpadTestRequest()) | 854 | view = create_view(branch, '+index') |
398 | 870 | self.assertFalse(view.no_merges) | 855 | self.assertFalse(view.no_merges) |
399 | 871 | [proposal] = view.dependent_branches | 856 | [proposal] = view.dependent_branches |
400 | 872 | self.assertEqual(bmp, proposal) | 857 | self.assertEqual(bmp, proposal) |
401 | @@ -878,7 +863,7 @@ | |||
402 | 878 | bmp = self.factory.makeBranchMergeProposal(prerequisite_branch=branch) | 863 | bmp = self.factory.makeBranchMergeProposal(prerequisite_branch=branch) |
403 | 879 | removeSecurityProxy(bmp.source_branch).information_type = ( | 864 | removeSecurityProxy(bmp.source_branch).information_type = ( |
404 | 880 | InformationType.USERDATA) | 865 | InformationType.USERDATA) |
406 | 881 | view = BranchView(branch, LaunchpadTestRequest()) | 866 | view = create_view(branch, '+index') |
407 | 882 | self.assertTrue(view.no_merges) | 867 | self.assertTrue(view.no_merges) |
408 | 883 | self.assertEqual([], view.dependent_branches) | 868 | self.assertEqual([], view.dependent_branches) |
409 | 884 | 869 | ||
410 | @@ -1009,8 +994,7 @@ | |||
411 | 1009 | browser.getControl("Change Branch").click() | 994 | browser.getControl("Change Branch").click() |
412 | 1010 | self.assertThat( | 995 | self.assertThat( |
413 | 1011 | browser.contents, | 996 | browser.contents, |
416 | 1012 | Contains( | 997 | Contains('Public branches are not allowed for target Commercial.')) |
415 | 1013 | 'Public branches are not allowed for target Commercial.')) | ||
417 | 1014 | with person_logged_in(owner): | 998 | with person_logged_in(owner): |
418 | 1015 | self.assertEquals(initial_target, branch.target.context) | 999 | self.assertEquals(initial_target, branch.target.context) |
419 | 1016 | 1000 | ||
420 | @@ -1026,8 +1010,7 @@ | |||
421 | 1026 | browser.getControl("Private", index=1).click() | 1010 | browser.getControl("Private", index=1).click() |
422 | 1027 | browser.getControl("Change Branch").click() | 1011 | browser.getControl("Change Branch").click() |
423 | 1028 | with person_logged_in(person): | 1012 | with person_logged_in(person): |
426 | 1029 | self.assertEqual( | 1013 | self.assertEqual(InformationType.USERDATA, branch.information_type) |
425 | 1030 | InformationType.USERDATA, branch.information_type) | ||
427 | 1031 | 1014 | ||
428 | 1032 | def test_can_not_change_privacy_of_stacked_on_private(self): | 1015 | def test_can_not_change_privacy_of_stacked_on_private(self): |
429 | 1033 | # The privacy field is not shown if the branch is stacked on a | 1016 | # The privacy field is not shown if the branch is stacked on a |
430 | @@ -1042,8 +1025,7 @@ | |||
431 | 1042 | with person_logged_in(owner): | 1025 | with person_logged_in(owner): |
432 | 1043 | browser = self.getUserBrowser( | 1026 | browser = self.getUserBrowser( |
433 | 1044 | canonical_url(branch) + '/+edit', user=owner) | 1027 | canonical_url(branch) + '/+edit', user=owner) |
436 | 1045 | self.assertRaises( | 1028 | self.assertRaises(LookupError, browser.getControl, "Information Type") |
435 | 1046 | LookupError, browser.getControl, "Information Type") | ||
437 | 1047 | 1029 | ||
438 | 1048 | def test_edit_view_ajax_render(self): | 1030 | def test_edit_view_ajax_render(self): |
439 | 1049 | # An information type change request is processed as expected when an | 1031 | # An information type change request is processed as expected when an |
440 | @@ -1058,11 +1040,10 @@ | |||
441 | 1058 | 'field.information_type': 'PUBLICSECURITY'}, | 1040 | 'field.information_type': 'PUBLICSECURITY'}, |
442 | 1059 | **extra) | 1041 | **extra) |
443 | 1060 | with person_logged_in(person): | 1042 | with person_logged_in(person): |
445 | 1061 | view = create_view( | 1043 | view = create_initialized_view( |
446 | 1062 | branch, name='+edit-information-type', | 1044 | branch, name='+edit-information-type', |
447 | 1063 | request=request, principal=person) | 1045 | request=request, principal=person) |
448 | 1064 | request.traversed_objects = [person, branch.product, branch, view] | 1046 | request.traversed_objects = [person, branch.product, branch, view] |
449 | 1065 | view.initialize() | ||
450 | 1066 | result = view.render() | 1047 | result = view.render() |
451 | 1067 | self.assertEqual('', result) | 1048 | self.assertEqual('', result) |
452 | 1068 | self.assertEqual( | 1049 | self.assertEqual( |
453 | @@ -1088,10 +1069,8 @@ | |||
454 | 1088 | branch = self.factory.makeBranch( | 1069 | branch = self.factory.makeBranch( |
455 | 1089 | information_type=InformationType.PUBLIC) | 1070 | information_type=InformationType.PUBLIC) |
456 | 1090 | self.assertShownTypes( | 1071 | self.assertShownTypes( |
461 | 1091 | [InformationType.PUBLIC, | 1072 | [InformationType.PUBLIC, InformationType.PUBLICSECURITY, |
462 | 1092 | InformationType.PUBLICSECURITY, | 1073 | InformationType.PRIVATESECURITY, InformationType.USERDATA], |
459 | 1093 | InformationType.PRIVATESECURITY, | ||
460 | 1094 | InformationType.USERDATA], | ||
463 | 1095 | branch) | 1074 | branch) |
464 | 1096 | 1075 | ||
465 | 1097 | def test_branch_with_disallowed_type(self): | 1076 | def test_branch_with_disallowed_type(self): |
466 | @@ -1103,12 +1082,9 @@ | |||
467 | 1103 | branch = self.factory.makeBranch( | 1082 | branch = self.factory.makeBranch( |
468 | 1104 | product=product, information_type=InformationType.PROPRIETARY) | 1083 | product=product, information_type=InformationType.PROPRIETARY) |
469 | 1105 | self.assertShownTypes( | 1084 | self.assertShownTypes( |
476 | 1106 | [InformationType.PUBLIC, | 1085 | [InformationType.PUBLIC, InformationType.PUBLICSECURITY, |
477 | 1107 | InformationType.PUBLICSECURITY, | 1086 | InformationType.PRIVATESECURITY, InformationType.USERDATA, |
478 | 1108 | InformationType.PRIVATESECURITY, | 1087 | InformationType.PROPRIETARY], branch) |
473 | 1109 | InformationType.USERDATA, | ||
474 | 1110 | InformationType.PROPRIETARY], | ||
475 | 1111 | branch) | ||
479 | 1112 | 1088 | ||
480 | 1113 | def test_stacked_on_private(self): | 1089 | def test_stacked_on_private(self): |
481 | 1114 | # A branch stacked on a private branch has its choices limited | 1090 | # A branch stacked on a private branch has its choices limited |
482 | 1115 | 1091 | ||
483 | === modified file 'lib/lp/code/configure.zcml' | |||
484 | --- lib/lp/code/configure.zcml 2013-01-22 02:06:41 +0000 | |||
485 | +++ lib/lp/code/configure.zcml 2013-02-25 05:26:21 +0000 | |||
486 | @@ -1,4 +1,4 @@ | |||
488 | 1 | <!-- Copyright 2009-2011 Canonical Ltd. This software is licensed under the | 1 | <!-- Copyright 2009-2013 Canonical Ltd. This software is licensed under the |
489 | 2 | GNU Affero General Public License version 3 (see the file LICENSE). | 2 | GNU Affero General Public License version 3 (see the file LICENSE). |
490 | 3 | --> | 3 | --> |
491 | 4 | 4 | ||
492 | @@ -223,8 +223,10 @@ | |||
493 | 223 | id | 223 | id |
494 | 224 | registrant | 224 | registrant |
495 | 225 | source_branch | 225 | source_branch |
496 | 226 | source_branchID | ||
497 | 226 | target_branch | 227 | target_branch |
498 | 227 | prerequisite_branch | 228 | prerequisite_branch |
499 | 229 | prerequisite_branchID | ||
500 | 228 | description | 230 | description |
501 | 229 | whiteboard | 231 | whiteboard |
502 | 230 | queue_status | 232 | queue_status |