Merge lp:~stevenk/launchpad/filter-spec-lists into lp:launchpad
- filter-spec-lists
- Merge into devel
Proposed by
Steve Kowalik
Status: | Merged |
---|---|
Merged at revision: | 16505 |
Proposed branch: | lp:~stevenk/launchpad/filter-spec-lists |
Merge into: | lp:launchpad |
Diff against target: |
368 lines (+103/-41) 11 files modified
lib/lp/bugs/browser/bug.py (+5/-1) lib/lp/bugs/interfaces/bug.py (+4/-2) lib/lp/bugs/model/bug.py (+14/-5) lib/lp/bugs/model/tests/test_bugtask.py (+33/-10) lib/lp/bugs/templates/bug-portlet-specs.pt (+2/-2) lib/lp/code/browser/branch.py (+6/-2) lib/lp/code/browser/branchmergeproposal.py (+6/-3) lib/lp/code/interfaces/branch.py (+4/-1) lib/lp/code/model/branch.py (+22/-8) lib/lp/code/model/tests/test_branch.py (+5/-5) lib/lp/code/templates/branch-macros.pt (+2/-2) |
To merge this branch: | bzr merge lp:~stevenk/launchpad/filter-spec-lists |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
William Grant | code | Approve | |
Review via email: mp+149748@code.launchpad.net |
Commit message
Description of the change
Change IBug.specifications so that it returns a resultset of the linked specifications that the user can view.
Add a new method, IBranch.
Clean up some whitespace that caught my eye.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/lp/bugs/browser/bug.py' | |||
2 | --- lib/lp/bugs/browser/bug.py 2012-09-28 01:25:36 +0000 | |||
3 | +++ lib/lp/bugs/browser/bug.py 2013-02-21 07:22:22 +0000 | |||
4 | @@ -1,4 +1,4 @@ | |||
6 | 1 | # Copyright 2009-2012 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2009-2013 Canonical Ltd. This software is licensed under the |
7 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
8 | 3 | 3 | ||
9 | 4 | """IBug related view classes.""" | 4 | """IBug related view classes.""" |
10 | @@ -536,6 +536,10 @@ | |||
11 | 536 | """ | 536 | """ |
12 | 537 | return getUtility(ILaunchBag).bugtask | 537 | return getUtility(ILaunchBag).bugtask |
13 | 538 | 538 | ||
14 | 539 | @property | ||
15 | 540 | def specifications(self): | ||
16 | 541 | return self.context.getSpecifications(self.user) | ||
17 | 542 | |||
18 | 539 | 543 | ||
19 | 540 | class BugInformationTypePortletView(InformationTypePortletMixin, | 544 | class BugInformationTypePortletView(InformationTypePortletMixin, |
20 | 541 | LaunchpadView): | 545 | LaunchpadView): |
21 | 542 | 546 | ||
22 | === modified file 'lib/lp/bugs/interfaces/bug.py' | |||
23 | --- lib/lp/bugs/interfaces/bug.py 2013-02-06 04:22:43 +0000 | |||
24 | +++ lib/lp/bugs/interfaces/bug.py 2013-02-21 07:22:22 +0000 | |||
25 | @@ -1,4 +1,4 @@ | |||
27 | 1 | # Copyright 2009-2012 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2009-2013 Canonical Ltd. This software is licensed under the |
28 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
29 | 3 | 3 | ||
30 | 4 | """Interfaces related to bugs.""" | 4 | """Interfaces related to bugs.""" |
31 | @@ -313,7 +313,6 @@ | |||
32 | 313 | initial_message = Attribute( | 313 | initial_message = Attribute( |
33 | 314 | "The message that was specified when creating the bug") | 314 | "The message that was specified when creating the bug") |
34 | 315 | questions = Attribute("List of questions related to this bug.") | 315 | questions = Attribute("List of questions related to this bug.") |
35 | 316 | specifications = Attribute("List of related specifications.") | ||
36 | 317 | tags = exported(List( | 316 | tags = exported(List( |
37 | 318 | title=_("Tags"), | 317 | title=_("Tags"), |
38 | 319 | description=_("Space-separated keywords for classifying " | 318 | description=_("Space-separated keywords for classifying " |
39 | @@ -383,6 +382,9 @@ | |||
40 | 383 | value_type=Reference(schema=IMessage)), | 382 | value_type=Reference(schema=IMessage)), |
41 | 384 | exported_as='messages')) | 383 | exported_as='messages')) |
42 | 385 | 384 | ||
43 | 385 | def getSpecifications(user): | ||
44 | 386 | """List of related specifications that the user can view.""" | ||
45 | 387 | |||
46 | 386 | def _indexed_messages(include_content=False, include_parents=False): | 388 | def _indexed_messages(include_content=False, include_parents=False): |
47 | 387 | """Low level query for getting bug messages. | 389 | """Low level query for getting bug messages. |
48 | 388 | 390 | ||
49 | 389 | 391 | ||
50 | === modified file 'lib/lp/bugs/model/bug.py' | |||
51 | --- lib/lp/bugs/model/bug.py 2013-02-06 04:56:33 +0000 | |||
52 | +++ lib/lp/bugs/model/bug.py 2013-02-21 07:22:22 +0000 | |||
53 | @@ -98,6 +98,11 @@ | |||
54 | 98 | from lp.app.interfaces.services import IService | 98 | from lp.app.interfaces.services import IService |
55 | 99 | from lp.app.model.launchpad import InformationTypeMixin | 99 | from lp.app.model.launchpad import InformationTypeMixin |
56 | 100 | from lp.app.validators import LaunchpadValidationError | 100 | from lp.app.validators import LaunchpadValidationError |
57 | 101 | from lp.blueprints.model.specification import Specification | ||
58 | 102 | from lp.blueprints.model.specificationbug import SpecificationBug | ||
59 | 103 | from lp.blueprints.model.specificationsearch import ( | ||
60 | 104 | get_specification_privacy_filter, | ||
61 | 105 | ) | ||
62 | 101 | from lp.bugs.adapters.bug import convert_to_information_type | 106 | from lp.bugs.adapters.bug import convert_to_information_type |
63 | 102 | from lp.bugs.adapters.bugchange import ( | 107 | from lp.bugs.adapters.bugchange import ( |
64 | 103 | BranchLinkedToBug, | 108 | BranchLinkedToBug, |
65 | @@ -360,11 +365,7 @@ | |||
66 | 360 | cves = SQLRelatedJoin('Cve', intermediateTable='BugCve', | 365 | cves = SQLRelatedJoin('Cve', intermediateTable='BugCve', |
67 | 361 | orderBy='sequence', joinColumn='bug', otherColumn='cve') | 366 | orderBy='sequence', joinColumn='bug', otherColumn='cve') |
68 | 362 | cve_links = SQLMultipleJoin('BugCve', joinColumn='bug', orderBy='id') | 367 | cve_links = SQLMultipleJoin('BugCve', joinColumn='bug', orderBy='id') |
74 | 363 | duplicates = SQLMultipleJoin( | 368 | duplicates = SQLMultipleJoin('Bug', joinColumn='duplicateof', orderBy='id') |
70 | 364 | 'Bug', joinColumn='duplicateof', orderBy='id') | ||
71 | 365 | specifications = SQLRelatedJoin('Specification', joinColumn='bug', | ||
72 | 366 | otherColumn='specification', intermediateTable='SpecificationBug', | ||
73 | 367 | orderBy='-datecreated') | ||
75 | 368 | questions = SQLRelatedJoin('Question', joinColumn='bug', | 369 | questions = SQLRelatedJoin('Question', joinColumn='bug', |
76 | 369 | otherColumn='question', intermediateTable='QuestionBug', | 370 | otherColumn='question', intermediateTable='QuestionBug', |
77 | 370 | orderBy='-datecreated') | 371 | orderBy='-datecreated') |
78 | @@ -379,6 +380,14 @@ | |||
79 | 379 | heat_last_updated = UtcDateTimeCol(default=None) | 380 | heat_last_updated = UtcDateTimeCol(default=None) |
80 | 380 | latest_patch_uploaded = UtcDateTimeCol(default=None) | 381 | latest_patch_uploaded = UtcDateTimeCol(default=None) |
81 | 381 | 382 | ||
82 | 383 | def getSpecifications(self, user): | ||
83 | 384 | """See `IBug`.""" | ||
84 | 385 | return IStore(SpecificationBug).find( | ||
85 | 386 | Specification, | ||
86 | 387 | SpecificationBug.bugID == self.id, | ||
87 | 388 | SpecificationBug.specificationID == Specification.id, | ||
88 | 389 | *get_specification_privacy_filter(user)) | ||
89 | 390 | |||
90 | 382 | @property | 391 | @property |
91 | 383 | def security_related(self): | 392 | def security_related(self): |
92 | 384 | return self.information_type in SECURITY_INFORMATION_TYPES | 393 | return self.information_type in SECURITY_INFORMATION_TYPES |
93 | 385 | 394 | ||
94 | === modified file 'lib/lp/bugs/model/tests/test_bugtask.py' | |||
95 | --- lib/lp/bugs/model/tests/test_bugtask.py 2012-10-18 14:43:24 +0000 | |||
96 | +++ lib/lp/bugs/model/tests/test_bugtask.py 2013-02-21 07:22:22 +0000 | |||
97 | @@ -1,4 +1,4 @@ | |||
99 | 1 | # Copyright 2009-2012 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2009-2013 Canonical Ltd. This software is licensed under the |
100 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
101 | 3 | 3 | ||
102 | 4 | __metaclass__ = type | 4 | __metaclass__ = type |
103 | @@ -528,7 +528,7 @@ | |||
104 | 528 | ]) | 528 | ]) |
105 | 529 | 529 | ||
106 | 530 | 530 | ||
108 | 531 | class TestBugTaskPrivacy(TestCase): | 531 | class TestBugTaskPrivacy(TestCaseWithFactory): |
109 | 532 | """Verify that the bug is either private or public. | 532 | """Verify that the bug is either private or public. |
110 | 533 | 533 | ||
111 | 534 | XXX: rharding 2012-05-14 bug=999298: These tests are ported from doctests | 534 | XXX: rharding 2012-05-14 bug=999298: These tests are ported from doctests |
112 | @@ -553,14 +553,15 @@ | |||
113 | 553 | ubuntu_team = getUtility(IPersonSet).getByEmail('support@ubuntu.com') | 553 | ubuntu_team = getUtility(IPersonSet).getByEmail('support@ubuntu.com') |
114 | 554 | bug_upstream_firefox_crashes.bug.subscribe(ubuntu_team, ubuntu_team) | 554 | bug_upstream_firefox_crashes.bug.subscribe(ubuntu_team, ubuntu_team) |
115 | 555 | 555 | ||
124 | 556 | old_state = Snapshot(bug_upstream_firefox_crashes.bug, | 556 | old_state = Snapshot( |
125 | 557 | providing=IBug) | 557 | bug_upstream_firefox_crashes.bug, providing=IBug) |
126 | 558 | self.assertTrue(bug_upstream_firefox_crashes.bug.setPrivate(True, | 558 | self.assertTrue( |
127 | 559 | foobar)) | 559 | bug_upstream_firefox_crashes.bug.setPrivate(True, foobar)) |
128 | 560 | 560 | ||
129 | 561 | bug_set_private = ObjectModifiedEvent(bug_upstream_firefox_crashes.bug, | 561 | bug_set_private = ObjectModifiedEvent( |
130 | 562 | old_state, | 562 | bug_upstream_firefox_crashes.bug, old_state, |
131 | 563 | ["id", "title", "private"]) | 563 | ["id", "title", "private"]) |
132 | 564 | |||
133 | 564 | notify(bug_set_private) | 565 | notify(bug_set_private) |
134 | 565 | flush_database_updates() | 566 | flush_database_updates() |
135 | 566 | 567 | ||
136 | @@ -671,6 +672,28 @@ | |||
137 | 671 | bug_upstream_firefox_crashes.transitionToStatus( | 672 | bug_upstream_firefox_crashes.transitionToStatus( |
138 | 672 | BugTaskStatus.NEW, getUtility(ILaunchBag).user) | 673 | BugTaskStatus.NEW, getUtility(ILaunchBag).user) |
139 | 673 | 674 | ||
140 | 675 | def _createBugAndSpecification(self): | ||
141 | 676 | bug = self.factory.makeBug() | ||
142 | 677 | spec = self.factory.makeSpecification( | ||
143 | 678 | information_type=InformationType.PROPRIETARY) | ||
144 | 679 | with person_logged_in(spec.product.owner): | ||
145 | 680 | spec.linkBug(bug) | ||
146 | 681 | return spec, bug | ||
147 | 682 | |||
148 | 683 | def test_bug_specifications_is_filtered_for_anonymous(self): | ||
149 | 684 | spec, bug = self._createBugAndSpecification() | ||
150 | 685 | self.assertContentEqual([], bug.getSpecifications(None)) | ||
151 | 686 | |||
152 | 687 | def test_bug_specifications_is_filtered_for_unknown_user(self): | ||
153 | 688 | spec, bug = self._createBugAndSpecification() | ||
154 | 689 | self.assertContentEqual( | ||
155 | 690 | [], bug.getSpecifications(self.factory.makePerson())) | ||
156 | 691 | |||
157 | 692 | def test_bug_specifications_for_authorised_user(self): | ||
158 | 693 | spec, bug = self._createBugAndSpecification() | ||
159 | 694 | self.assertContentEqual( | ||
160 | 695 | [spec], bug.getSpecifications(spec.product.owner)) | ||
161 | 696 | |||
162 | 674 | 697 | ||
163 | 675 | class TestBugTaskDelta(TestCaseWithFactory): | 698 | class TestBugTaskDelta(TestCaseWithFactory): |
164 | 676 | 699 | ||
165 | 677 | 700 | ||
166 | === modified file 'lib/lp/bugs/templates/bug-portlet-specs.pt' | |||
167 | --- lib/lp/bugs/templates/bug-portlet-specs.pt 2009-10-29 21:39:12 +0000 | |||
168 | +++ lib/lp/bugs/templates/bug-portlet-specs.pt 2013-02-21 07:22:22 +0000 | |||
169 | @@ -3,10 +3,10 @@ | |||
170 | 3 | xmlns:metal="http://xml.zope.org/namespaces/metal" | 3 | xmlns:metal="http://xml.zope.org/namespaces/metal" |
171 | 4 | xmlns:i18n="http://xml.zope.org/namespaces/i18n" | 4 | xmlns:i18n="http://xml.zope.org/namespaces/i18n" |
172 | 5 | class="portlet vertical" id="portlet-blueprints" | 5 | class="portlet vertical" id="portlet-blueprints" |
174 | 6 | tal:condition="context/specifications"> | 6 | tal:condition="view/specifications"> |
175 | 7 | <h2>Related blueprints</h2> | 7 | <h2>Related blueprints</h2> |
176 | 8 | <ul> | 8 | <ul> |
178 | 9 | <li tal:repeat="spec context/specifications" | 9 | <li tal:repeat="spec view/specifications" |
179 | 10 | tal:content="structure spec/fmt:link" /> | 10 | tal:content="structure spec/fmt:link" /> |
180 | 11 | </ul> | 11 | </ul> |
181 | 12 | </div> | 12 | </div> |
182 | 13 | 13 | ||
183 | === modified file 'lib/lp/code/browser/branch.py' | |||
184 | --- lib/lp/code/browser/branch.py 2012-12-12 04:59:52 +0000 | |||
185 | +++ lib/lp/code/browser/branch.py 2013-02-21 07:22:22 +0000 | |||
186 | @@ -1,4 +1,4 @@ | |||
188 | 1 | # Copyright 2009-2012 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2009-2013 Canonical Ltd. This software is licensed under the |
189 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
190 | 3 | 3 | ||
191 | 4 | """Branch views.""" | 4 | """Branch views.""" |
192 | @@ -354,7 +354,7 @@ | |||
193 | 354 | return Link('+linkbug', text, icon='add') | 354 | return Link('+linkbug', text, icon='add') |
194 | 355 | 355 | ||
195 | 356 | def link_blueprint(self): | 356 | def link_blueprint(self): |
197 | 357 | if self.context.spec_links: | 357 | if list(self.context.getSpecificationLinks(self.user)): |
198 | 358 | text = 'Link to another blueprint' | 358 | text = 'Link to another blueprint' |
199 | 359 | else: | 359 | else: |
200 | 360 | text = 'Link to a blueprint' | 360 | text = 'Link to a blueprint' |
201 | @@ -689,6 +689,10 @@ | |||
202 | 689 | self.context.branch, IBranch['lifecycle_status'], | 689 | self.context.branch, IBranch['lifecycle_status'], |
203 | 690 | header='Change status to', css_class_prefix='branchstatus') | 690 | header='Change status to', css_class_prefix='branchstatus') |
204 | 691 | 691 | ||
205 | 692 | @property | ||
206 | 693 | def spec_links(self): | ||
207 | 694 | return self.context.getSpecificationLinks(self.user) | ||
208 | 695 | |||
209 | 692 | 696 | ||
210 | 693 | class BranchInProductView(BranchView): | 697 | class BranchInProductView(BranchView): |
211 | 694 | 698 | ||
212 | 695 | 699 | ||
213 | === modified file 'lib/lp/code/browser/branchmergeproposal.py' | |||
214 | --- lib/lp/code/browser/branchmergeproposal.py 2013-01-07 02:40:55 +0000 | |||
215 | +++ lib/lp/code/browser/branchmergeproposal.py 2013-02-21 07:22:22 +0000 | |||
216 | @@ -1,4 +1,4 @@ | |||
218 | 1 | # Copyright 2009-2012 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2009-2013 Canonical Ltd. This software is licensed under the |
219 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
220 | 3 | 3 | ||
221 | 4 | """Views, navigation and actions for BranchMergeProposals.""" | 4 | """Views, navigation and actions for BranchMergeProposals.""" |
222 | @@ -719,8 +719,11 @@ | |||
223 | 719 | def has_bug_or_spec(self): | 719 | def has_bug_or_spec(self): |
224 | 720 | """Return whether or not the merge proposal has a linked bug or spec. | 720 | """Return whether or not the merge proposal has a linked bug or spec. |
225 | 721 | """ | 721 | """ |
228 | 722 | branch = self.context.source_branch | 722 | return self.linked_bugtasks or self.spec_links |
229 | 723 | return self.linked_bugtasks or branch.spec_links | 723 | |
230 | 724 | @property | ||
231 | 725 | def spec_links(self): | ||
232 | 726 | return self.context.source_branch.getSpecificationLinks(self.user) | ||
233 | 724 | 727 | ||
234 | 725 | @cachedproperty | 728 | @cachedproperty |
235 | 726 | def linked_bugtasks(self): | 729 | def linked_bugtasks(self): |
236 | 727 | 730 | ||
237 | === modified file 'lib/lp/code/interfaces/branch.py' | |||
238 | --- lib/lp/code/interfaces/branch.py 2013-01-16 06:41:43 +0000 | |||
239 | +++ lib/lp/code/interfaces/branch.py 2013-02-21 07:22:22 +0000 | |||
240 | @@ -1,4 +1,4 @@ | |||
242 | 1 | # Copyright 2009-2012 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2009-2013 Canonical Ltd. This software is licensed under the |
243 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
244 | 3 | 3 | ||
245 | 4 | """Branch interfaces.""" | 4 | """Branch interfaces.""" |
246 | @@ -482,6 +482,9 @@ | |||
247 | 482 | value_type=Reference(Interface)), # Really ISpecificationBranch | 482 | value_type=Reference(Interface)), # Really ISpecificationBranch |
248 | 483 | as_of="beta") | 483 | as_of="beta") |
249 | 484 | 484 | ||
250 | 485 | def getSpecificationLinks(user): | ||
251 | 486 | """Fetch the `ISpecificationBranch`'s that the user can view.""" | ||
252 | 487 | |||
253 | 485 | @call_with(registrant=REQUEST_USER) | 488 | @call_with(registrant=REQUEST_USER) |
254 | 486 | @operation_parameters( | 489 | @operation_parameters( |
255 | 487 | spec=Reference(schema=Interface)) # Really ISpecification | 490 | spec=Reference(schema=Interface)) # Really ISpecification |
256 | 488 | 491 | ||
257 | === modified file 'lib/lp/code/model/branch.py' | |||
258 | --- lib/lp/code/model/branch.py 2013-02-14 05:36:37 +0000 | |||
259 | +++ lib/lp/code/model/branch.py 2013-02-21 07:22:22 +0000 | |||
260 | @@ -1,4 +1,4 @@ | |||
262 | 1 | # Copyright 2009-2012 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2009-2013 Canonical Ltd. This software is licensed under the |
263 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
264 | 3 | 3 | ||
265 | 4 | __metaclass__ = type | 4 | __metaclass__ = type |
266 | @@ -66,6 +66,11 @@ | |||
267 | 66 | IPrivacy, | 66 | IPrivacy, |
268 | 67 | ) | 67 | ) |
269 | 68 | from lp.app.interfaces.services import IService | 68 | from lp.app.interfaces.services import IService |
270 | 69 | from lp.blueprints.model.specification import Specification | ||
271 | 70 | from lp.blueprints.model.specificationbranch import SpecificationBranch | ||
272 | 71 | from lp.blueprints.model.specificationsearch import ( | ||
273 | 72 | get_specification_privacy_filter, | ||
274 | 73 | ) | ||
275 | 69 | from lp.bugs.interfaces.bugtask import IBugTaskSet | 74 | from lp.bugs.interfaces.bugtask import IBugTaskSet |
276 | 70 | from lp.bugs.interfaces.bugtaskfilter import filter_bugtasks_by_context | 75 | from lp.bugs.interfaces.bugtaskfilter import filter_bugtasks_by_context |
277 | 71 | from lp.bugs.interfaces.bugtasksearch import BugTaskSearchParams | 76 | from lp.bugs.interfaces.bugtasksearch import BugTaskSearchParams |
278 | @@ -438,9 +443,20 @@ | |||
279 | 438 | """See `IBranch`.""" | 443 | """See `IBranch`.""" |
280 | 439 | return bug.unlinkBranch(self, user) | 444 | return bug.unlinkBranch(self, user) |
281 | 440 | 445 | ||
285 | 441 | spec_links = SQLMultipleJoin('SpecificationBranch', | 446 | spec_links = SQLMultipleJoin( |
286 | 442 | joinColumn='branch', | 447 | 'SpecificationBranch', joinColumn='branch', orderBy='id') |
287 | 443 | orderBy='id') | 448 | |
288 | 449 | def getSpecificationLinks(self, user): | ||
289 | 450 | """See `IBranch`.""" | ||
290 | 451 | tables = [ | ||
291 | 452 | SpecificationBranch, | ||
292 | 453 | Join( | ||
293 | 454 | Specification, | ||
294 | 455 | SpecificationBranch.specificationID == Specification.id)] | ||
295 | 456 | return Store.of(self).using(*tables).find( | ||
296 | 457 | SpecificationBranch, | ||
297 | 458 | SpecificationBranch.branchID == self.id, | ||
298 | 459 | *get_specification_privacy_filter(user)) | ||
299 | 444 | 460 | ||
300 | 445 | def linkSpecification(self, spec, registrant): | 461 | def linkSpecification(self, spec, registrant): |
301 | 446 | """See `IBranch`.""" | 462 | """See `IBranch`.""" |
302 | @@ -459,8 +475,7 @@ | |||
303 | 459 | @property | 475 | @property |
304 | 460 | def active_landing_targets(self): | 476 | def active_landing_targets(self): |
305 | 461 | """Merge proposals not in final states where this branch is source.""" | 477 | """Merge proposals not in final states where this branch is source.""" |
308 | 462 | store = Store.of(self) | 478 | return Store.of(self).find( |
307 | 463 | return store.find( | ||
309 | 464 | BranchMergeProposal, BranchMergeProposal.source_branch == self, | 479 | BranchMergeProposal, BranchMergeProposal.source_branch == self, |
310 | 465 | Not(BranchMergeProposal.queue_status.is_in( | 480 | Not(BranchMergeProposal.queue_status.is_in( |
311 | 466 | BRANCH_MERGE_PROPOSAL_FINAL_STATES))) | 481 | BRANCH_MERGE_PROPOSAL_FINAL_STATES))) |
312 | @@ -615,8 +630,7 @@ | |||
313 | 615 | 630 | ||
314 | 616 | def getStackedBranches(self): | 631 | def getStackedBranches(self): |
315 | 617 | """See `IBranch`.""" | 632 | """See `IBranch`.""" |
318 | 618 | store = Store.of(self) | 633 | return Store.of(self).find(Branch, Branch.stacked_on == self) |
317 | 619 | return store.find(Branch, Branch.stacked_on == self) | ||
319 | 620 | 634 | ||
320 | 621 | def getStackedOnBranches(self): | 635 | def getStackedOnBranches(self): |
321 | 622 | """See `IBranch`.""" | 636 | """See `IBranch`.""" |
322 | 623 | 637 | ||
323 | === modified file 'lib/lp/code/model/tests/test_branch.py' | |||
324 | --- lib/lp/code/model/tests/test_branch.py 2013-01-07 02:40:55 +0000 | |||
325 | +++ lib/lp/code/model/tests/test_branch.py 2013-02-21 07:22:22 +0000 | |||
326 | @@ -1,4 +1,4 @@ | |||
328 | 1 | # Copyright 2009-2012 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2009-2013 Canonical Ltd. This software is licensed under the |
329 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
330 | 3 | 3 | ||
331 | 4 | """Tests for Branches.""" | 4 | """Tests for Branches.""" |
332 | @@ -1573,10 +1573,10 @@ | |||
333 | 1573 | spec2.linkBranch(self.branch, self.branch.owner) | 1573 | spec2.linkBranch(self.branch, self.branch.owner) |
334 | 1574 | spec2_branch_id = self.branch.spec_links[1].id | 1574 | spec2_branch_id = self.branch.spec_links[1].id |
335 | 1575 | self.branch.destroySelf(break_references=True) | 1575 | self.branch.destroySelf(break_references=True) |
340 | 1576 | self.assertRaises(SQLObjectNotFound, SpecificationBranch.get, | 1576 | self.assertRaises( |
341 | 1577 | spec1_branch_id) | 1577 | SQLObjectNotFound, SpecificationBranch.get, spec1_branch_id) |
342 | 1578 | self.assertRaises(SQLObjectNotFound, SpecificationBranch.get, | 1578 | self.assertRaises( |
343 | 1579 | spec2_branch_id) | 1579 | SQLObjectNotFound, SpecificationBranch.get, spec2_branch_id) |
344 | 1580 | 1580 | ||
345 | 1581 | def test_branchWithSeriesRequirements(self): | 1581 | def test_branchWithSeriesRequirements(self): |
346 | 1582 | """Deletion requirements for a series' branch are right.""" | 1582 | """Deletion requirements for a series' branch are right.""" |
347 | 1583 | 1583 | ||
348 | === modified file 'lib/lp/code/templates/branch-macros.pt' | |||
349 | --- lib/lp/code/templates/branch-macros.pt 2012-08-07 07:07:02 +0000 | |||
350 | +++ lib/lp/code/templates/branch-macros.pt 2013-02-21 07:22:22 +0000 | |||
351 | @@ -76,7 +76,7 @@ | |||
352 | 76 | <metal:branch-link use-macro="branch/@@+macros/bug-branch-links"/> | 76 | <metal:branch-link use-macro="branch/@@+macros/bug-branch-links"/> |
353 | 77 | </tal:branch-link> | 77 | </tal:branch-link> |
354 | 78 | 78 | ||
356 | 79 | <div tal:repeat="spec_link mergeproposal/source_branch/spec_links"> | 79 | <div tal:repeat="spec_link view/spec_links"> |
357 | 80 | <img src="/@@/blueprint" | 80 | <img src="/@@/blueprint" |
358 | 81 | tal:replace="structure spec_link/specification/image:icon" /> | 81 | tal:replace="structure spec_link/specification/image:icon" /> |
359 | 82 | <a tal:attributes="href spec_link/specification/fmt:url:blueprints" | 82 | <a tal:attributes="href spec_link/specification/fmt:url:blueprints" |
360 | @@ -140,7 +140,7 @@ | |||
361 | 140 | show_edit - show the edit form | 140 | show_edit - show the edit form |
362 | 141 | </tal:comment> | 141 | </tal:comment> |
363 | 142 | 142 | ||
365 | 143 | <tal:spec-tasks repeat="spec_branch branch/spec_links"> | 143 | <tal:spec-tasks repeat="spec_branch view/spec_links"> |
366 | 144 | <div tal:define="has_edit_permission spec_branch/required:launchpad.AnyPerson; | 144 | <div tal:define="has_edit_permission spec_branch/required:launchpad.AnyPerson; |
367 | 145 | show_edit show_edit|nothing; | 145 | show_edit show_edit|nothing; |
368 | 146 | show_edit python: show_edit and has_edit_permission; | 146 | show_edit python: show_edit and has_edit_permission; |
I wouldn't use an explicit join in getSpecifications (particularly since you have the join condition and where clause around the wrong way), but otherwise fine.