Merge lp:~wgrant/launchpad/delete-nullbugtask into lp:launchpad
- delete-nullbugtask
- Merge into devel
Proposed by
William Grant
Status: | Superseded | ||||
---|---|---|---|---|---|
Proposed branch: | lp:~wgrant/launchpad/delete-nullbugtask | ||||
Merge into: | lp:launchpad | ||||
Diff against target: |
815 lines (+48/-399) 13 files modified
lib/lp/bugs/browser/bugnomination.py (+1/-9) lib/lp/bugs/browser/bugtask.py (+6/-130) lib/lp/bugs/browser/configure.zcml (+21/-43) lib/lp/bugs/browser/tests/bug-views.txt (+2/-2) lib/lp/bugs/browser/tests/bugtask-edit-views.txt (+13/-13) lib/lp/bugs/configure.zcml (+0/-13) lib/lp/bugs/doc/bugtask.txt (+1/-77) lib/lp/bugs/doc/displaying-bugs-and-tasks.txt (+0/-17) lib/lp/bugs/interfaces/bug.py (+0/-5) lib/lp/bugs/interfaces/bugtask.py (+0/-11) lib/lp/bugs/model/bug.py (+0/-11) lib/lp/bugs/model/bugtask.py (+4/-67) lib/lp/bugs/templates/bugtask-index.pt (+0/-1) |
||||
To merge this branch: | bzr merge lp:~wgrant/launchpad/delete-nullbugtask | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Launchpad code reviewers | Pending | ||
Review via email: mp+53367@code.launchpad.net |
Commit message
Remove NullBugTask.
Description of the change
This branch removes NullBugTask's final callsite, using determine_target in validate_
With that gone, NullBugTask and its tests have also been deleted.
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/bugnomination.py' | |||
2 | --- lib/lp/bugs/browser/bugnomination.py 2011-02-02 15:43:31 +0000 | |||
3 | +++ lib/lp/bugs/browser/bugnomination.py 2011-03-15 04:26:27 +0000 | |||
4 | @@ -15,10 +15,7 @@ | |||
5 | 15 | 15 | ||
6 | 16 | import pytz | 16 | import pytz |
7 | 17 | from zope.component import getUtility | 17 | from zope.component import getUtility |
12 | 18 | from zope.publisher.interfaces import ( | 18 | from zope.publisher.interfaces import implements |
9 | 19 | implements, | ||
10 | 20 | NotFound, | ||
11 | 21 | ) | ||
13 | 22 | 19 | ||
14 | 23 | from canonical.launchpad import _ | 20 | from canonical.launchpad import _ |
15 | 24 | from canonical.launchpad.webapp import ( | 21 | from canonical.launchpad.webapp import ( |
16 | @@ -41,7 +38,6 @@ | |||
17 | 41 | IBugNomination, | 38 | IBugNomination, |
18 | 42 | IBugNominationForm, | 39 | IBugNominationForm, |
19 | 43 | ) | 40 | ) |
20 | 44 | from lp.bugs.interfaces.bugtask import INullBugTask | ||
21 | 45 | from lp.bugs.interfaces.cve import ICveSet | 41 | from lp.bugs.interfaces.cve import ICveSet |
22 | 46 | 42 | ||
23 | 47 | 43 | ||
24 | @@ -65,10 +61,6 @@ | |||
25 | 65 | LaunchpadFormView.__init__(self, context, request) | 61 | LaunchpadFormView.__init__(self, context, request) |
26 | 66 | 62 | ||
27 | 67 | def initialize(self): | 63 | def initialize(self): |
28 | 68 | if INullBugTask.providedBy(self.current_bugtask): | ||
29 | 69 | # It shouldn't be possible to nominate a bug that hasn't | ||
30 | 70 | # been reported yet. | ||
31 | 71 | raise NotFound(self.current_bugtask, '+nominate', self.request) | ||
32 | 72 | LaunchpadFormView.initialize(self) | 64 | LaunchpadFormView.initialize(self) |
33 | 73 | # Update the submit label based on the user's permission. | 65 | # Update the submit label based on the user's permission. |
34 | 74 | submit_action = self.__class__.actions.byname['actions.submit'] | 66 | submit_action = self.__class__.actions.byname['actions.submit'] |
35 | 75 | 67 | ||
36 | === modified file 'lib/lp/bugs/browser/bugtask.py' | |||
37 | --- lib/lp/bugs/browser/bugtask.py 2011-03-10 16:15:57 +0000 | |||
38 | +++ lib/lp/bugs/browser/bugtask.py 2011-03-15 04:26:27 +0000 | |||
39 | @@ -236,7 +236,6 @@ | |||
40 | 236 | IDistroSeriesBugTask, | 236 | IDistroSeriesBugTask, |
41 | 237 | IFrontPageBugTaskSearch, | 237 | IFrontPageBugTaskSearch, |
42 | 238 | INominationsReviewTableBatchNavigator, | 238 | INominationsReviewTableBatchNavigator, |
43 | 239 | INullBugTask, | ||
44 | 240 | IPersonBugTaskSearch, | 239 | IPersonBugTaskSearch, |
45 | 241 | IProductSeriesBugTask, | 240 | IProductSeriesBugTask, |
46 | 242 | IRemoveQuestionFromBugTaskForm, | 241 | IRemoveQuestionFromBugTaskForm, |
47 | @@ -490,7 +489,7 @@ | |||
48 | 490 | """Return the IBugTask for this name in this context. | 489 | """Return the IBugTask for this name in this context. |
49 | 491 | 490 | ||
50 | 492 | If the bug has been reported, but not in this specific context, a | 491 | If the bug has been reported, but not in this specific context, a |
52 | 493 | NullBugTask will be returned. | 492 | redirect to the default context will be returned. |
53 | 494 | 493 | ||
54 | 495 | Raises NotFoundError if no bug with the given name is found. | 494 | Raises NotFoundError if no bug with the given name is found. |
55 | 496 | 495 | ||
56 | @@ -514,59 +513,15 @@ | |||
57 | 514 | # Security proxy this object on the way out. | 513 | # Security proxy this object on the way out. |
58 | 515 | return getUtility(IBugTaskSet).get(bugtask.id) | 514 | return getUtility(IBugTaskSet).get(bugtask.id) |
59 | 516 | 515 | ||
85 | 517 | # If we've come this far, it means that no actual task exists in this | 516 | # If we've come this far, there's no task for the requested |
86 | 518 | # context, so we'll return a null bug task. This makes it possible to, | 517 | # context. Redirect to one that exists. |
87 | 519 | # for example, return a bug page for a context in which the bug hasn't | 518 | return self.redirectSubTree(canonical_url(bug.default_bugtask)) |
63 | 520 | # yet been reported. | ||
64 | 521 | if IProduct.providedBy(context): | ||
65 | 522 | null_bugtask = bug.getNullBugTask(product=context) | ||
66 | 523 | elif IProductSeries.providedBy(context): | ||
67 | 524 | null_bugtask = bug.getNullBugTask(productseries=context) | ||
68 | 525 | elif IDistribution.providedBy(context): | ||
69 | 526 | null_bugtask = bug.getNullBugTask(distribution=context) | ||
70 | 527 | elif IDistributionSourcePackage.providedBy(context): | ||
71 | 528 | null_bugtask = bug.getNullBugTask( | ||
72 | 529 | distribution=context.distribution, | ||
73 | 530 | sourcepackagename=context.sourcepackagename) | ||
74 | 531 | elif IDistroSeries.providedBy(context): | ||
75 | 532 | null_bugtask = bug.getNullBugTask(distroseries=context) | ||
76 | 533 | elif ISourcePackage.providedBy(context): | ||
77 | 534 | null_bugtask = bug.getNullBugTask( | ||
78 | 535 | distroseries=context.distroseries, | ||
79 | 536 | sourcepackagename=context.sourcepackagename) | ||
80 | 537 | else: | ||
81 | 538 | raise TypeError( | ||
82 | 539 | "Unknown context type for bug task: %s" % repr(context)) | ||
83 | 540 | |||
84 | 541 | return null_bugtask | ||
88 | 542 | 519 | ||
89 | 543 | 520 | ||
90 | 544 | class BugTaskNavigation(Navigation): | 521 | class BugTaskNavigation(Navigation): |
91 | 545 | """Navigation for the `IBugTask`.""" | 522 | """Navigation for the `IBugTask`.""" |
92 | 546 | usedfor = IBugTask | 523 | usedfor = IBugTask |
93 | 547 | 524 | ||
94 | 548 | def traverse(self, name): | ||
95 | 549 | """Traverse the `IBugTask`.""" | ||
96 | 550 | # Are we traversing to the view or edit status page of the | ||
97 | 551 | # bugtask? If so, and the task actually exists, return the | ||
98 | 552 | # appropriate page. If the task doesn't yet exist (i.e. it's a | ||
99 | 553 | # NullBugTask), then return a 404. In other words, the URL: | ||
100 | 554 | # | ||
101 | 555 | # /products/foo/+bug/1/+viewstatus | ||
102 | 556 | # | ||
103 | 557 | # will return the +viewstatus page if bug 1 has actually been | ||
104 | 558 | # reported in "foo". If bug 1 has not yet been reported in "foo", | ||
105 | 559 | # a 404 will be returned. | ||
106 | 560 | if name not in ("+viewstatus", "+editstatus"): | ||
107 | 561 | # You're going in the wrong direction. | ||
108 | 562 | return None | ||
109 | 563 | if INullBugTask.providedBy(self.context): | ||
110 | 564 | # The bug has not been reported in this context. | ||
111 | 565 | return None | ||
112 | 566 | # Yes! The bug has been reported in this context. | ||
113 | 567 | return getMultiAdapter((self.context, self.request), | ||
114 | 568 | name=(name + "-page")) | ||
115 | 569 | |||
116 | 570 | @stepthrough('attachments') | 525 | @stepthrough('attachments') |
117 | 571 | def traverse_attachments(self, name): | 526 | def traverse_attachments(self, name): |
118 | 572 | """traverse to an attachment by id.""" | 527 | """traverse to an attachment by id.""" |
119 | @@ -655,13 +610,8 @@ | |||
120 | 655 | 610 | ||
121 | 656 | @property | 611 | @property |
122 | 657 | def page_title(self): | 612 | def page_title(self): |
130 | 658 | bugtask = self.context | 613 | heading = 'Bug #%s in %s' % ( |
131 | 659 | if INullBugTask.providedBy(bugtask): | 614 | self.context.bug.id, self.context.bugtargetdisplayname) |
125 | 660 | heading = 'Bug #%s is not in %s' % ( | ||
126 | 661 | bugtask.bug.id, bugtask.bugtargetdisplayname) | ||
127 | 662 | else: | ||
128 | 663 | heading = 'Bug #%s in %s' % ( | ||
129 | 664 | bugtask.bug.id, bugtask.bugtargetdisplayname) | ||
132 | 665 | return smartquote('%s: "%s"') % (heading, self.context.bug.title) | 615 | return smartquote('%s: "%s"') % (heading, self.context.bug.title) |
133 | 666 | 616 | ||
134 | 667 | @property | 617 | @property |
135 | @@ -698,12 +648,6 @@ | |||
136 | 698 | # See render() for how this flag is used. | 648 | # See render() for how this flag is used. |
137 | 699 | self._redirecting_to_bug_list = False | 649 | self._redirecting_to_bug_list = False |
138 | 700 | 650 | ||
139 | 701 | # If the bug is not reported in this context, redirect | ||
140 | 702 | # to the default bug task. | ||
141 | 703 | if not self.isReportedInContext(): | ||
142 | 704 | self.request.response.redirect( | ||
143 | 705 | canonical_url(self.context.bug.default_bugtask)) | ||
144 | 706 | |||
145 | 707 | self.bug_title_edit_widget = TextLineEditorWidget( | 651 | self.bug_title_edit_widget = TextLineEditorWidget( |
146 | 708 | bug, IBug['title'], "Edit this summary", 'h1', | 652 | bug, IBug['title'], "Edit this summary", 'h1', |
147 | 709 | edit_url=canonical_url(self.context, view_name='+edit')) | 653 | edit_url=canonical_url(self.context, view_name='+edit')) |
148 | @@ -741,69 +685,6 @@ | |||
149 | 741 | series.bugtargetdisplayname) | 685 | series.bugtargetdisplayname) |
150 | 742 | self.request.response.redirect(canonical_url(self.context)) | 686 | self.request.response.redirect(canonical_url(self.context)) |
151 | 743 | 687 | ||
152 | 744 | def reportBugInContext(self): | ||
153 | 745 | """Report the bug affects the current context.""" | ||
154 | 746 | fake_task = self.context | ||
155 | 747 | if self.request.form.get("reportbug"): | ||
156 | 748 | if self.isReportedInContext(): | ||
157 | 749 | self.notices.append( | ||
158 | 750 | "The bug is already reported in this context.") | ||
159 | 751 | return | ||
160 | 752 | # The user has requested that the bug be reported in this | ||
161 | 753 | # context. | ||
162 | 754 | if IUpstreamBugTask.providedBy(fake_task): | ||
163 | 755 | # Create a real upstream task in this context. | ||
164 | 756 | real_task = fake_task.bug.addTask( | ||
165 | 757 | getUtility(ILaunchBag).user, fake_task.product) | ||
166 | 758 | elif IDistroBugTask.providedBy(fake_task): | ||
167 | 759 | # Create a real distro bug task in this context. | ||
168 | 760 | real_task = fake_task.bug.addTask( | ||
169 | 761 | getUtility(ILaunchBag).user, fake_task.target) | ||
170 | 762 | elif IDistroSeriesBugTask.providedBy(fake_task): | ||
171 | 763 | self._nominateBug(fake_task.distroseries) | ||
172 | 764 | return | ||
173 | 765 | elif IProductSeriesBugTask.providedBy(fake_task): | ||
174 | 766 | self._nominateBug(fake_task.productseries) | ||
175 | 767 | return | ||
176 | 768 | else: | ||
177 | 769 | raise TypeError( | ||
178 | 770 | "Unknown bug task type: %s" % repr(fake_task)) | ||
179 | 771 | |||
180 | 772 | self.context = real_task | ||
181 | 773 | |||
182 | 774 | # Add an appropriate feedback message | ||
183 | 775 | self.notices.append("Thank you for your bug report.") | ||
184 | 776 | |||
185 | 777 | def isReportedInContext(self): | ||
186 | 778 | """Is the bug reported in this context? Returns True or False. | ||
187 | 779 | |||
188 | 780 | It considers a nominated bug to be reported. | ||
189 | 781 | |||
190 | 782 | This is particularly useful for views that may render a | ||
191 | 783 | NullBugTask. | ||
192 | 784 | """ | ||
193 | 785 | if self.context.id is not None: | ||
194 | 786 | # Fast path for real bugtasks: they have a DB id. | ||
195 | 787 | return True | ||
196 | 788 | params = BugTaskSearchParams(user=self.user, bug=self.context.bug) | ||
197 | 789 | matching_bugtasks = self.context.target.searchTasks(params) | ||
198 | 790 | if self.context.productseries is not None: | ||
199 | 791 | nomination_target = self.context.productseries | ||
200 | 792 | elif self.context.distroseries is not None: | ||
201 | 793 | nomination_target = self.context.distroseries | ||
202 | 794 | else: | ||
203 | 795 | nomination_target = None | ||
204 | 796 | if nomination_target is not None: | ||
205 | 797 | try: | ||
206 | 798 | nomination = self.context.bug.getNominationFor( | ||
207 | 799 | nomination_target) | ||
208 | 800 | except NotFoundError: | ||
209 | 801 | nomination = None | ||
210 | 802 | else: | ||
211 | 803 | nomination = None | ||
212 | 804 | |||
213 | 805 | return nomination is not None or matching_bugtasks.count() > 0 | ||
214 | 806 | |||
215 | 807 | def isSeriesTargetableContext(self): | 688 | def isSeriesTargetableContext(self): |
216 | 808 | """Is the context something that supports Series targeting? | 689 | """Is the context something that supports Series targeting? |
217 | 809 | 690 | ||
218 | @@ -1744,17 +1625,12 @@ | |||
219 | 1744 | The assignee is included. | 1625 | The assignee is included. |
220 | 1745 | """ | 1626 | """ |
221 | 1746 | bugtask = self.context | 1627 | bugtask = self.context |
222 | 1747 | |||
223 | 1748 | if INullBugTask.providedBy(bugtask): | ||
224 | 1749 | return u"Not reported in %s" % bugtask.bugtargetname | ||
225 | 1750 | |||
226 | 1751 | assignee = bugtask.assignee | 1628 | assignee = bugtask.assignee |
227 | 1752 | status = bugtask.status | 1629 | status = bugtask.status |
228 | 1753 | status_title = status.title.capitalize() | 1630 | status_title = status.title.capitalize() |
229 | 1754 | 1631 | ||
230 | 1755 | if not assignee: | 1632 | if not assignee: |
231 | 1756 | return status_title + ' (unassigned)' | 1633 | return status_title + ' (unassigned)' |
232 | 1757 | |||
233 | 1758 | assignee_html = PersonFormatterAPI(assignee).link('+assignedbugs') | 1634 | assignee_html = PersonFormatterAPI(assignee).link('+assignedbugs') |
234 | 1759 | 1635 | ||
235 | 1760 | if status in (BugTaskStatus.INVALID, | 1636 | if status in (BugTaskStatus.INVALID, |
236 | 1761 | 1637 | ||
237 | === modified file 'lib/lp/bugs/browser/configure.zcml' | |||
238 | --- lib/lp/bugs/browser/configure.zcml 2011-03-11 21:31:10 +0000 | |||
239 | +++ lib/lp/bugs/browser/configure.zcml 2011-03-15 04:26:27 +0000 | |||
240 | @@ -637,35 +637,27 @@ | |||
241 | 637 | class="lp.bugs.browser.bugalsoaffects.BugAlsoAffectsDistroMetaView" | 637 | class="lp.bugs.browser.bugalsoaffects.BugAlsoAffectsDistroMetaView" |
242 | 638 | permission="launchpad.AnyPerson"/> | 638 | permission="launchpad.AnyPerson"/> |
243 | 639 | <browser:page | 639 | <browser:page |
273 | 640 | name="+editstatus-page" | 640 | name="+edit-form" |
274 | 641 | for="lp.bugs.interfaces.bugtask.IUpstreamBugTask" | 641 | for="lp.bugs.interfaces.bugtask.IUpstreamBugTask" |
275 | 642 | class="lp.bugs.browser.bugtask.BugTaskEditView" | 642 | class="lp.bugs.browser.bugtask.BugTaskEditView" |
276 | 643 | permission="launchpad.Edit" | 643 | permission="launchpad.Edit" |
277 | 644 | template="../templates/bugtask-edit.pt"> | 644 | template="../templates/bugtask-edit-form.pt"> |
278 | 645 | </browser:page> | 645 | </browser:page> |
279 | 646 | <browser:page | 646 | <browser:page |
280 | 647 | name="+edit-form" | 647 | name="+edit-form" |
281 | 648 | for="lp.bugs.interfaces.bugtask.IUpstreamBugTask" | 648 | for="lp.bugs.interfaces.bugtask.IProductSeriesBugTask" |
282 | 649 | class="lp.bugs.browser.bugtask.BugTaskEditView" | 649 | class="lp.bugs.browser.bugtask.BugTaskEditView" |
283 | 650 | permission="launchpad.Edit" | 650 | permission="launchpad.Edit" |
284 | 651 | template="../templates/bugtask-edit-form.pt"> | 651 | template="../templates/bugtask-edit-form.pt"> |
285 | 652 | </browser:page> | 652 | </browser:page> |
286 | 653 | <browser:page | 653 | <browser:page |
287 | 654 | name="+editstatus-page" | 654 | name="+editstatus" |
288 | 655 | for="lp.bugs.interfaces.bugtask.IProductSeriesBugTask" | 655 | for="lp.bugs.interfaces.bugtask.IBugTask" |
289 | 656 | class="lp.bugs.browser.bugtask.BugTaskEditView" | 656 | class="lp.bugs.browser.bugtask.BugTaskEditView" |
290 | 657 | permission="launchpad.Edit" | 657 | permission="launchpad.Edit" |
291 | 658 | template="../templates/bugtask-edit.pt"> | 658 | template="../templates/bugtask-edit.pt"/> |
292 | 659 | </browser:page> | 659 | <browser:page |
293 | 660 | <browser:page | 660 | name="+viewstatus" |
265 | 661 | name="+edit-form" | ||
266 | 662 | for="lp.bugs.interfaces.bugtask.IProductSeriesBugTask" | ||
267 | 663 | class="lp.bugs.browser.bugtask.BugTaskEditView" | ||
268 | 664 | permission="launchpad.Edit" | ||
269 | 665 | template="../templates/bugtask-edit-form.pt"> | ||
270 | 666 | </browser:page> | ||
271 | 667 | <browser:page | ||
272 | 668 | name="+viewstatus-page" | ||
294 | 669 | for="lp.bugs.interfaces.bugtask.IBugTask" | 661 | for="lp.bugs.interfaces.bugtask.IBugTask" |
295 | 670 | class="lp.bugs.browser.bugtask.BugTaskStatusView" | 662 | class="lp.bugs.browser.bugtask.BugTaskStatusView" |
296 | 671 | permission="launchpad.View" | 663 | permission="launchpad.View" |
297 | @@ -680,13 +672,6 @@ | |||
298 | 680 | for="lp.bugs.interfaces.bugtask.IDistroBugTask" | 672 | for="lp.bugs.interfaces.bugtask.IDistroBugTask" |
299 | 681 | name="+index"/> | 673 | name="+index"/> |
300 | 682 | <browser:page | 674 | <browser:page |
301 | 683 | name="+editstatus-page" | ||
302 | 684 | for="lp.bugs.interfaces.bugtask.IDistroBugTask" | ||
303 | 685 | class="lp.bugs.browser.bugtask.BugTaskEditView" | ||
304 | 686 | permission="launchpad.Edit" | ||
305 | 687 | template="../templates/bugtask-edit.pt"> | ||
306 | 688 | </browser:page> | ||
307 | 689 | <browser:page | ||
308 | 690 | name="+edit-form" | 675 | name="+edit-form" |
309 | 691 | for="lp.bugs.interfaces.bugtask.IDistroBugTask" | 676 | for="lp.bugs.interfaces.bugtask.IDistroBugTask" |
310 | 692 | class="lp.bugs.browser.bugtask.BugTaskEditView" | 677 | class="lp.bugs.browser.bugtask.BugTaskEditView" |
311 | @@ -697,13 +682,6 @@ | |||
312 | 697 | for="lp.bugs.interfaces.bugtask.IDistroSeriesBugTask" | 682 | for="lp.bugs.interfaces.bugtask.IDistroSeriesBugTask" |
313 | 698 | name="+index"/> | 683 | name="+index"/> |
314 | 699 | <browser:page | 684 | <browser:page |
315 | 700 | name="+editstatus-page" | ||
316 | 701 | for="lp.bugs.interfaces.bugtask.IDistroSeriesBugTask" | ||
317 | 702 | class="lp.bugs.browser.bugtask.BugTaskEditView" | ||
318 | 703 | permission="launchpad.Edit" | ||
319 | 704 | template="../templates/bugtask-edit.pt"> | ||
320 | 705 | </browser:page> | ||
321 | 706 | <browser:page | ||
322 | 707 | name="+edit-form" | 685 | name="+edit-form" |
323 | 708 | for="lp.bugs.interfaces.bugtask.IDistroSeriesBugTask" | 686 | for="lp.bugs.interfaces.bugtask.IDistroSeriesBugTask" |
324 | 709 | class="lp.bugs.browser.bugtask.BugTaskEditView" | 687 | class="lp.bugs.browser.bugtask.BugTaskEditView" |
325 | 710 | 688 | ||
326 | === modified file 'lib/lp/bugs/browser/tests/bug-views.txt' | |||
327 | --- lib/lp/bugs/browser/tests/bug-views.txt 2011-02-15 09:31:20 +0000 | |||
328 | +++ lib/lp/bugs/browser/tests/bug-views.txt 2011-03-15 04:26:27 +0000 | |||
329 | @@ -777,7 +777,7 @@ | |||
330 | 777 | ... 'testproduct.actions.save': 'Save Changes', | 777 | ... 'testproduct.actions.save': 'Save Changes', |
331 | 778 | ... }) | 778 | ... }) |
332 | 779 | >>> view = getMultiAdapter( | 779 | >>> view = getMultiAdapter( |
334 | 780 | ... (bug.bugtasks[0], request), name="+editstatus-page") | 780 | ... (bug.bugtasks[0], request), name="+editstatus") |
335 | 781 | >>> view.initialize() | 781 | >>> view.initialize() |
336 | 782 | 782 | ||
337 | 783 | >>> view = getMultiAdapter( | 783 | >>> view = getMultiAdapter( |
338 | @@ -833,7 +833,7 @@ | |||
339 | 833 | ... 'testproduct.actions.save': 'Save Changes', | 833 | ... 'testproduct.actions.save': 'Save Changes', |
340 | 834 | ... }) | 834 | ... }) |
341 | 835 | >>> view = getMultiAdapter( | 835 | >>> view = getMultiAdapter( |
343 | 836 | ... (bug.bugtasks[0], request), name="+editstatus-page") | 836 | ... (bug.bugtasks[0], request), name="+editstatus") |
344 | 837 | >>> view.initialize() | 837 | >>> view.initialize() |
345 | 838 | 838 | ||
346 | 839 | >>> view = getMultiAdapter( | 839 | >>> view = getMultiAdapter( |
347 | 840 | 840 | ||
348 | === modified file 'lib/lp/bugs/browser/tests/bugtask-edit-views.txt' | |||
349 | --- lib/lp/bugs/browser/tests/bugtask-edit-views.txt 2010-10-18 22:24:59 +0000 | |||
350 | +++ lib/lp/bugs/browser/tests/bugtask-edit-views.txt 2011-03-15 04:26:27 +0000 | |||
351 | @@ -29,7 +29,7 @@ | |||
352 | 29 | ... ubuntu_thunderbird_task.sourcepackagename.name} | 29 | ... ubuntu_thunderbird_task.sourcepackagename.name} |
353 | 30 | >>> request = LaunchpadTestRequest(method='POST', form=edit_form) | 30 | >>> request = LaunchpadTestRequest(method='POST', form=edit_form) |
354 | 31 | >>> edit_view = getMultiAdapter( | 31 | >>> edit_view = getMultiAdapter( |
356 | 32 | ... (ubuntu_thunderbird_task, request), name='+editstatus-page') | 32 | ... (ubuntu_thunderbird_task, request), name='+editstatus') |
357 | 33 | >>> edit_view.initialize() | 33 | >>> edit_view.initialize() |
358 | 34 | >>> ubuntu_thunderbird_task.status.title | 34 | >>> ubuntu_thunderbird_task.status.title |
359 | 35 | 'In Progress' | 35 | 'In Progress' |
360 | @@ -50,7 +50,7 @@ | |||
361 | 50 | >>> edit_form['ubuntu_thunderbird.sourcepackagename'] = u'linux-2.6.12' | 50 | >>> edit_form['ubuntu_thunderbird.sourcepackagename'] = u'linux-2.6.12' |
362 | 51 | >>> request = LaunchpadTestRequest(method='POST', form=edit_form) | 51 | >>> request = LaunchpadTestRequest(method='POST', form=edit_form) |
363 | 52 | >>> edit_view = getMultiAdapter( | 52 | >>> edit_view = getMultiAdapter( |
365 | 53 | ... (ubuntu_thunderbird_task, request), name='+editstatus-page') | 53 | ... (ubuntu_thunderbird_task, request), name='+editstatus') |
366 | 54 | >>> edit_view.initialize() | 54 | >>> edit_view.initialize() |
367 | 55 | >>> ubuntu_thunderbird_task.sourcepackagename.name | 55 | >>> ubuntu_thunderbird_task.sourcepackagename.name |
368 | 56 | u'linux-source-2.6.15' | 56 | u'linux-source-2.6.15' |
369 | @@ -73,7 +73,7 @@ | |||
370 | 73 | >>> edit_form['ubuntu_thunderbird.sourcepackagename'] = u'no-such-package' | 73 | >>> edit_form['ubuntu_thunderbird.sourcepackagename'] = u'no-such-package' |
371 | 74 | >>> request = LaunchpadTestRequest(form=edit_form, method='POST') | 74 | >>> request = LaunchpadTestRequest(form=edit_form, method='POST') |
372 | 75 | >>> edit_view = getMultiAdapter( | 75 | >>> edit_view = getMultiAdapter( |
374 | 76 | ... (ubuntu_thunderbird_task, request), name='+editstatus-page') | 76 | ... (ubuntu_thunderbird_task, request), name='+editstatus') |
375 | 77 | >>> edit_view.initialize() | 77 | >>> edit_view.initialize() |
376 | 78 | >>> for error in edit_view.errors: | 78 | >>> for error in edit_view.errors: |
377 | 79 | ... print error | 79 | ... print error |
378 | @@ -112,7 +112,7 @@ | |||
379 | 112 | ... } | 112 | ... } |
380 | 113 | >>> request = LaunchpadTestRequest(form=edit_form, method='POST') | 113 | >>> request = LaunchpadTestRequest(form=edit_form, method='POST') |
381 | 114 | >>> edit_view = getMultiAdapter( | 114 | >>> edit_view = getMultiAdapter( |
383 | 115 | ... (ubuntu_task, request), name='+editstatus-page') | 115 | ... (ubuntu_task, request), name='+editstatus') |
384 | 116 | >>> edit_view.initialize() | 116 | >>> edit_view.initialize() |
385 | 117 | >>> for error in edit_view.errors: | 117 | >>> for error in edit_view.errors: |
386 | 118 | ... print error | 118 | ... print error |
387 | @@ -144,7 +144,7 @@ | |||
388 | 144 | ... } | 144 | ... } |
389 | 145 | >>> request = LaunchpadTestRequest(form=edit_form, method='POST') | 145 | >>> request = LaunchpadTestRequest(form=edit_form, method='POST') |
390 | 146 | >>> edit_view = getMultiAdapter( | 146 | >>> edit_view = getMultiAdapter( |
392 | 147 | ... (ubuntu_grumpy_task, request), name='+editstatus-page') | 147 | ... (ubuntu_grumpy_task, request), name='+editstatus') |
393 | 148 | >>> edit_view.initialize() | 148 | >>> edit_view.initialize() |
394 | 149 | >>> for error in edit_view.errors: | 149 | >>> for error in edit_view.errors: |
395 | 150 | ... print error | 150 | ... print error |
396 | @@ -155,7 +155,7 @@ | |||
397 | 155 | 155 | ||
398 | 156 | == Edit the Product == | 156 | == Edit the Product == |
399 | 157 | 157 | ||
401 | 158 | +editstatus-page allows a bug to be retargeted to another product. | 158 | +editstatus allows a bug to be retargeted to another product. |
402 | 159 | 159 | ||
403 | 160 | >>> bug_seven = getUtility(IBugSet).get(7) | 160 | >>> bug_seven = getUtility(IBugSet).get(7) |
404 | 161 | >>> product_task = bug_seven.bugtasks[0] | 161 | >>> product_task = bug_seven.bugtasks[0] |
405 | @@ -173,7 +173,7 @@ | |||
406 | 173 | ... } | 173 | ... } |
407 | 174 | >>> request = LaunchpadTestRequest(form=edit_form, method='POST') | 174 | >>> request = LaunchpadTestRequest(form=edit_form, method='POST') |
408 | 175 | >>> edit_view = getMultiAdapter( | 175 | >>> edit_view = getMultiAdapter( |
410 | 176 | ... (product_task, request), name='+editstatus-page') | 176 | ... (product_task, request), name='+editstatus') |
411 | 177 | >>> edit_view.initialize() | 177 | >>> edit_view.initialize() |
412 | 178 | >>> [str(error) for error in edit_view.errors] | 178 | >>> [str(error) for error in edit_view.errors] |
413 | 179 | [] | 179 | [] |
414 | @@ -193,7 +193,7 @@ | |||
415 | 193 | ... } | 193 | ... } |
416 | 194 | >>> request = LaunchpadTestRequest(form=edit_form, method='POST') | 194 | >>> request = LaunchpadTestRequest(form=edit_form, method='POST') |
417 | 195 | >>> edit_view = getMultiAdapter( | 195 | >>> edit_view = getMultiAdapter( |
419 | 196 | ... (product_task, request), name='+editstatus-page') | 196 | ... (product_task, request), name='+editstatus') |
420 | 197 | >>> edit_view.initialize() | 197 | >>> edit_view.initialize() |
421 | 198 | >>> for error in edit_view.errors: | 198 | >>> for error in edit_view.errors: |
422 | 199 | ... print error | 199 | ... print error |
423 | @@ -235,7 +235,7 @@ | |||
424 | 235 | ... 'thunderbird.importance': 'Critical', | 235 | ... 'thunderbird.importance': 'Critical', |
425 | 236 | ... 'thunderbird.bugwatch': '6'}) | 236 | ... 'thunderbird.bugwatch': '6'}) |
426 | 237 | >>> edit_view = getMultiAdapter( | 237 | >>> edit_view = getMultiAdapter( |
428 | 238 | ... (thunderbird_task, request), name='+editstatus-page') | 238 | ... (thunderbird_task, request), name='+editstatus') |
429 | 239 | >>> edit_view.initialize() | 239 | >>> edit_view.initialize() |
430 | 240 | >>> thunderbird_task.bugwatch == bugzilla_watch | 240 | >>> thunderbird_task.bugwatch == bugzilla_watch |
431 | 241 | True | 241 | True |
432 | @@ -251,7 +251,7 @@ | |||
433 | 251 | ... 'thunderbird.actions.save': 'Save Changes', | 251 | ... 'thunderbird.actions.save': 'Save Changes', |
434 | 252 | ... 'thunderbird.bugwatch-empty-marker': '1'}) | 252 | ... 'thunderbird.bugwatch-empty-marker': '1'}) |
435 | 253 | >>> edit_view = getMultiAdapter( | 253 | >>> edit_view = getMultiAdapter( |
437 | 254 | ... (thunderbird_task, request), name='+editstatus-page') | 254 | ... (thunderbird_task, request), name='+editstatus') |
438 | 255 | >>> edit_view.initialize() | 255 | >>> edit_view.initialize() |
439 | 256 | >>> thunderbird_task.bugwatch is None | 256 | >>> thunderbird_task.bugwatch is None |
440 | 257 | True | 257 | True |
441 | @@ -280,7 +280,7 @@ | |||
442 | 280 | >>> request = LaunchpadTestRequest() | 280 | >>> request = LaunchpadTestRequest() |
443 | 281 | >>> ubuntu_task = getUtility(IBugTaskSet).get(17) | 281 | >>> ubuntu_task = getUtility(IBugTaskSet).get(17) |
444 | 282 | >>> bugtask_edit_view = getMultiAdapter( | 282 | >>> bugtask_edit_view = getMultiAdapter( |
446 | 283 | ... (ubuntu_task, request), name="+editstatus-page") | 283 | ... (ubuntu_task, request), name="+editstatus") |
447 | 284 | >>> bugtask_edit_view.initialize() | 284 | >>> bugtask_edit_view.initialize() |
448 | 285 | 285 | ||
449 | 286 | >>> IInputWidget.providedBy(bugtask_edit_view.widgets['milestone']) | 286 | >>> IInputWidget.providedBy(bugtask_edit_view.widgets['milestone']) |
450 | @@ -293,7 +293,7 @@ | |||
451 | 293 | >>> login("no-priv@canonical.com") | 293 | >>> login("no-priv@canonical.com") |
452 | 294 | 294 | ||
453 | 295 | >>> bugtask_edit_view = getMultiAdapter( | 295 | >>> bugtask_edit_view = getMultiAdapter( |
455 | 296 | ... (ubuntu_task, request), name="+editstatus-page") | 296 | ... (ubuntu_task, request), name="+editstatus") |
456 | 297 | >>> bugtask_edit_view.initialize() | 297 | >>> bugtask_edit_view.initialize() |
457 | 298 | 298 | ||
458 | 299 | >>> isinstance(bugtask_edit_view.widgets['milestone'], ItemDisplayWidget) | 299 | >>> isinstance(bugtask_edit_view.widgets['milestone'], ItemDisplayWidget) |
459 | @@ -312,7 +312,7 @@ | |||
460 | 312 | Unlike before, no-priv can now edit the milestone. | 312 | Unlike before, no-priv can now edit the milestone. |
461 | 313 | 313 | ||
462 | 314 | >>> bugtask_edit_view = getMultiAdapter( | 314 | >>> bugtask_edit_view = getMultiAdapter( |
464 | 315 | ... (ubuntu_task, request), name="+editstatus-page") | 315 | ... (ubuntu_task, request), name="+editstatus") |
465 | 316 | >>> bugtask_edit_view.initialize() | 316 | >>> bugtask_edit_view.initialize() |
466 | 317 | 317 | ||
467 | 318 | >>> IInputWidget.providedBy(bugtask_edit_view.widgets['milestone']) | 318 | >>> IInputWidget.providedBy(bugtask_edit_view.widgets['milestone']) |
468 | 319 | 319 | ||
469 | === modified file 'lib/lp/bugs/configure.zcml' | |||
470 | --- lib/lp/bugs/configure.zcml 2011-03-08 01:56:34 +0000 | |||
471 | +++ lib/lp/bugs/configure.zcml 2011-03-15 04:26:27 +0000 | |||
472 | @@ -302,18 +302,6 @@ | |||
473 | 302 | factory="lp.bugs.browser.bugcomment.BugCommentBreadcrumb" | 302 | factory="lp.bugs.browser.bugcomment.BugCommentBreadcrumb" |
474 | 303 | permission="zope.Public"/> | 303 | permission="zope.Public"/> |
475 | 304 | 304 | ||
476 | 305 | <!-- NullBugTask --> | ||
477 | 306 | |||
478 | 307 | <class | ||
479 | 308 | class="lp.bugs.model.bugtask.NullBugTask"> | ||
480 | 309 | <require | ||
481 | 310 | permission="launchpad.View" | ||
482 | 311 | interface="lp.bugs.interfaces.bugtask.IBugTask"/> | ||
483 | 312 | <require | ||
484 | 313 | permission="launchpad.Edit" | ||
485 | 314 | set_schema="lp.bugs.interfaces.bugtask.IBugTask"/> | ||
486 | 315 | </class> | ||
487 | 316 | |||
488 | 317 | <!-- BugTaskSearchParams --> | 305 | <!-- BugTaskSearchParams --> |
489 | 318 | <class | 306 | <class |
490 | 319 | class="lp.bugs.interfaces.bugtask.BugTaskSearchParams"> | 307 | class="lp.bugs.interfaces.bugtask.BugTaskSearchParams"> |
491 | @@ -691,7 +679,6 @@ | |||
492 | 691 | getDirectSubscribers | 679 | getDirectSubscribers |
493 | 692 | getDirectSubscriptions | 680 | getDirectSubscriptions |
494 | 693 | getIndirectSubscribers | 681 | getIndirectSubscribers |
495 | 694 | getNullBugTask | ||
496 | 695 | is_complete | 682 | is_complete |
497 | 696 | official_tags | 683 | official_tags |
498 | 697 | who_made_private | 684 | who_made_private |
499 | 698 | 685 | ||
500 | === modified file 'lib/lp/bugs/doc/bugtask.txt' | |||
501 | --- lib/lp/bugs/doc/bugtask.txt 2011-02-14 11:04:09 +0000 | |||
502 | +++ lib/lp/bugs/doc/bugtask.txt 2011-03-15 04:26:27 +0000 | |||
503 | @@ -732,83 +732,6 @@ | |||
504 | 732 | False | 732 | False |
505 | 733 | 733 | ||
506 | 734 | 734 | ||
507 | 735 | == Null Bug Tasks == | ||
508 | 736 | |||
509 | 737 | Sometimes we need to be able to render a page for a bug in a context, | ||
510 | 738 | when the bug hasn't actually been filed yet in that context. For cases | ||
511 | 739 | like these, use the NullBugTask object. | ||
512 | 740 | |||
513 | 741 | |||
514 | 742 | >>> from lp.bugs.interfaces.bugtask import INullBugTask | ||
515 | 743 | >>> netapplet = productset.get(11) | ||
516 | 744 | >>> null_bugtask = bug_one.getNullBugTask(product=netapplet) | ||
517 | 745 | >>> verifyObject(INullBugTask, null_bugtask) | ||
518 | 746 | True | ||
519 | 747 | >>> IUpstreamBugTask.providedBy(null_bugtask) | ||
520 | 748 | True | ||
521 | 749 | |||
522 | 750 | >>> null_bugtask.id is None | ||
523 | 751 | True | ||
524 | 752 | >>> null_bugtask.title | ||
525 | 753 | u'Bug #1 is not in NetApplet: "Firefox does not support SVG"' | ||
526 | 754 | >>> null_bugtask.product is netapplet | ||
527 | 755 | True | ||
528 | 756 | >>> null_bugtask.bug == bug_one | ||
529 | 757 | True | ||
530 | 758 | >>> null_bugtask.datecreated is None | ||
531 | 759 | True | ||
532 | 760 | >>> null_bugtask.date_assigned is None | ||
533 | 761 | True | ||
534 | 762 | >>> null_bugtask.age is None | ||
535 | 763 | True | ||
536 | 764 | >>> null_bugtask.status is None | ||
537 | 765 | True | ||
538 | 766 | >>> null_bugtask.sourcepackagename is None | ||
539 | 767 | True | ||
540 | 768 | >>> null_bugtask.distribution is None | ||
541 | 769 | True | ||
542 | 770 | >>> null_bugtask.distroseries is None | ||
543 | 771 | True | ||
544 | 772 | >>> null_bugtask.milestone is None | ||
545 | 773 | True | ||
546 | 774 | >>> null_bugtask.importance is None | ||
547 | 775 | True | ||
548 | 776 | >>> null_bugtask.assignee is None | ||
549 | 777 | True | ||
550 | 778 | >>> null_bugtask.bugwatch is None | ||
551 | 779 | True | ||
552 | 780 | >>> null_bugtask.owner is None | ||
553 | 781 | True | ||
554 | 782 | >>> null_bugtask.target == netapplet | ||
555 | 783 | True | ||
556 | 784 | >>> null_bugtask.bugtargetname | ||
557 | 785 | u'netapplet' | ||
558 | 786 | >>> expected_related_task_ids = [ | ||
559 | 787 | ... task.id for task in null_bugtask.related_tasks] | ||
560 | 788 | >>> actual_related_task_ids = [task.id for task in bug_one.bugtasks] | ||
561 | 789 | >>> expected_related_task_ids.sort() | ||
562 | 790 | >>> actual_related_task_ids.sort() | ||
563 | 791 | >>> expected_related_task_ids == actual_related_task_ids | ||
564 | 792 | True | ||
565 | 793 | |||
566 | 794 | >>> null_bugtask.conjoined_slave is None | ||
567 | 795 | True | ||
568 | 796 | >>> null_bugtask.conjoined_master is None | ||
569 | 797 | True | ||
570 | 798 | |||
571 | 799 | The astute reader will have noticed that NullBugTask automatically | ||
572 | 800 | "marked" itself as providing the correct IBugTask interface. Let's see | ||
573 | 801 | two more examples: | ||
574 | 802 | |||
575 | 803 | >>> ubuntu_null_bugtask = bug_one.getNullBugTask(distribution=ubuntu) | ||
576 | 804 | >>> IDistroBugTask.providedBy(ubuntu_null_bugtask) | ||
577 | 805 | True | ||
578 | 806 | |||
579 | 807 | >>> warty_null_bugtask = bug_one.getNullBugTask(distroseries=warty) | ||
580 | 808 | >>> IDistroSeriesBugTask.providedBy(warty_null_bugtask) | ||
581 | 809 | True | ||
582 | 810 | |||
583 | 811 | |||
584 | 812 | = Bug Privacy = | 735 | = Bug Privacy = |
585 | 813 | 736 | ||
586 | 814 | A bug is either private or public. Private bugs are only visible (e.g. in search | 737 | A bug is either private or public. Private bugs are only visible (e.g. in search |
587 | @@ -1080,6 +1003,7 @@ | |||
588 | 1080 | the latter is not exposed in `IBugTask`, so the `bugtargetdisplayname` | 1003 | the latter is not exposed in `IBugTask`, so the `bugtargetdisplayname` |
589 | 1081 | is used here. | 1004 | is used here. |
590 | 1082 | 1005 | ||
591 | 1006 | >>> netapplet = productset.get(11) | ||
592 | 1083 | >>> upstream_task = bugtaskset.createTask( | 1007 | >>> upstream_task = bugtaskset.createTask( |
593 | 1084 | ... bug=bug_one, product=netapplet, owner=mark, | 1008 | ... bug=bug_one, product=netapplet, owner=mark, |
594 | 1085 | ... status=STATUS_NEW, importance=IMPORTANCE_MEDIUM) | 1009 | ... status=STATUS_NEW, importance=IMPORTANCE_MEDIUM) |
595 | 1086 | 1010 | ||
596 | === modified file 'lib/lp/bugs/doc/displaying-bugs-and-tasks.txt' | |||
597 | --- lib/lp/bugs/doc/displaying-bugs-and-tasks.txt 2010-11-01 15:46:48 +0000 | |||
598 | +++ lib/lp/bugs/doc/displaying-bugs-and-tasks.txt 2011-03-15 04:26:27 +0000 | |||
599 | @@ -150,17 +150,6 @@ | |||
600 | 150 | >>> render_bugtask_status(test_task) | 150 | >>> render_bugtask_status(test_task) |
601 | 151 | u'Fix released, assigned to ...Foo Bar...' | 151 | u'Fix released, assigned to ...Foo Bar...' |
602 | 152 | 152 | ||
603 | 153 | This code also works for null bug tasks: | ||
604 | 154 | |||
605 | 155 | >>> from lp.bugs.model.bug import Bug | ||
606 | 156 | >>> from lp.bugs.model.bugtask import NullBugTask | ||
607 | 157 | >>> from lp.registry.model.product import Product | ||
608 | 158 | >>> bug_one = Bug.get(1) | ||
609 | 159 | >>> netapplet = Product.selectOneBy(name="netapplet") | ||
610 | 160 | >>> null_bugtask = NullBugTask(bug=bug_one, product=netapplet) | ||
611 | 161 | >>> render_bugtask_status(null_bugtask) | ||
612 | 162 | u'Not reported in netapplet' | ||
613 | 163 | |||
614 | 164 | Lastly, some cleanup: | 153 | Lastly, some cleanup: |
615 | 165 | 154 | ||
616 | 166 | >>> test_task.transitionToStatus( | 155 | >>> test_task.transitionToStatus( |
617 | @@ -206,9 +195,3 @@ | |||
618 | 206 | 195 | ||
619 | 207 | >>> related_task.transitionToStatus( | 196 | >>> related_task.transitionToStatus( |
620 | 208 | ... ORIGINAL_STATUS, getUtility(ILaunchBag).user) | 197 | ... ORIGINAL_STATUS, getUtility(ILaunchBag).user) |
621 | 209 | |||
622 | 210 | Null tasks are also supported: | ||
623 | 211 | |||
624 | 212 | >>> render_bugtask_status_elsewhere(null_bugtask) | ||
625 | 213 | 'filed in 3 other places' | ||
626 | 214 | |||
627 | 215 | 198 | ||
628 | === modified file 'lib/lp/bugs/interfaces/bug.py' | |||
629 | --- lib/lp/bugs/interfaces/bug.py 2011-03-08 01:56:34 +0000 | |||
630 | +++ lib/lp/bugs/interfaces/bug.py 2011-03-15 04:26:27 +0000 | |||
631 | @@ -721,11 +721,6 @@ | |||
632 | 721 | returned rows. The step parameter in each slice is ignored. | 721 | returned rows. The step parameter in each slice is ignored. |
633 | 722 | """ | 722 | """ |
634 | 723 | 723 | ||
635 | 724 | def getNullBugTask(product=None, productseries=None, | ||
636 | 725 | sourcepackagename=None, distribution=None, | ||
637 | 726 | distroseries=None): | ||
638 | 727 | """Create an INullBugTask and return it for the given parameters.""" | ||
639 | 728 | |||
640 | 729 | @operation_parameters( | 724 | @operation_parameters( |
641 | 730 | target=Reference(schema=Interface, title=_('Target'))) | 725 | target=Reference(schema=Interface, title=_('Target'))) |
642 | 731 | @call_with(owner=REQUEST_USER) | 726 | @call_with(owner=REQUEST_USER) |
643 | 732 | 727 | ||
644 | === modified file 'lib/lp/bugs/interfaces/bugtask.py' | |||
645 | --- lib/lp/bugs/interfaces/bugtask.py 2011-03-07 21:05:12 +0000 | |||
646 | +++ lib/lp/bugs/interfaces/bugtask.py 2011-03-15 04:26:27 +0000 | |||
647 | @@ -30,7 +30,6 @@ | |||
648 | 30 | 'IDistroSeriesBugTask', | 30 | 'IDistroSeriesBugTask', |
649 | 31 | 'IFrontPageBugTaskSearch', | 31 | 'IFrontPageBugTaskSearch', |
650 | 32 | 'INominationsReviewTableBatchNavigator', | 32 | 'INominationsReviewTableBatchNavigator', |
651 | 33 | 'INullBugTask', | ||
652 | 34 | 'IPersonBugTaskSearch', | 33 | 'IPersonBugTaskSearch', |
653 | 35 | 'IProductSeriesBugTask', | 34 | 'IProductSeriesBugTask', |
654 | 36 | 'IRemoveQuestionFromBugTaskForm', | 35 | 'IRemoveQuestionFromBugTaskForm', |
655 | @@ -839,16 +838,6 @@ | |||
656 | 839 | IBugWatch['bugtasks'].value_type.schema = IBugTask | 838 | IBugWatch['bugtasks'].value_type.schema = IBugTask |
657 | 840 | 839 | ||
658 | 841 | 840 | ||
659 | 842 | class INullBugTask(IBugTask): | ||
660 | 843 | """A marker interface for an IBugTask that doesn't exist in a context. | ||
661 | 844 | |||
662 | 845 | An INullBugTask is useful when wanting to view a bug in a context | ||
663 | 846 | where that bug hasn't yet been reported. This might happen, for | ||
664 | 847 | example, when searching to see if a bug you want to report has | ||
665 | 848 | already been filed and finding matching reports that don't yet | ||
666 | 849 | have tasks reported in your context. | ||
667 | 850 | """ | ||
668 | 851 | |||
669 | 852 | UPSTREAM_STATUS_VOCABULARY = SimpleVocabulary( | 841 | UPSTREAM_STATUS_VOCABULARY = SimpleVocabulary( |
670 | 853 | [SimpleTerm( | 842 | [SimpleTerm( |
671 | 854 | "pending_bugwatch", | 843 | "pending_bugwatch", |
672 | 855 | 844 | ||
673 | === modified file 'lib/lp/bugs/model/bug.py' | |||
674 | --- lib/lp/bugs/model/bug.py 2011-03-08 01:56:34 +0000 | |||
675 | +++ lib/lp/bugs/model/bug.py 2011-03-15 04:26:27 +0000 | |||
676 | @@ -168,7 +168,6 @@ | |||
677 | 168 | BugTask, | 168 | BugTask, |
678 | 169 | bugtask_sort_key, | 169 | bugtask_sort_key, |
679 | 170 | get_bug_privacy_filter, | 170 | get_bug_privacy_filter, |
680 | 171 | NullBugTask, | ||
681 | 172 | ) | 171 | ) |
682 | 173 | from lp.bugs.model.bugwatch import BugWatch | 172 | from lp.bugs.model.bugwatch import BugWatch |
683 | 174 | from lp.bugs.model.structuralsubscription import ( | 173 | from lp.bugs.model.structuralsubscription import ( |
684 | @@ -1429,16 +1428,6 @@ | |||
685 | 1429 | need_validity=True)) | 1428 | need_validity=True)) |
686 | 1430 | return DecoratedResultSet(result, pre_iter_hook=eager_load_owners) | 1429 | return DecoratedResultSet(result, pre_iter_hook=eager_load_owners) |
687 | 1431 | 1430 | ||
688 | 1432 | def getNullBugTask(self, product=None, productseries=None, | ||
689 | 1433 | sourcepackagename=None, distribution=None, | ||
690 | 1434 | distroseries=None): | ||
691 | 1435 | """See `IBug`.""" | ||
692 | 1436 | return NullBugTask(bug=self, product=product, | ||
693 | 1437 | productseries=productseries, | ||
694 | 1438 | sourcepackagename=sourcepackagename, | ||
695 | 1439 | distribution=distribution, | ||
696 | 1440 | distroseries=distroseries) | ||
697 | 1441 | |||
698 | 1442 | def addNomination(self, owner, target): | 1431 | def addNomination(self, owner, target): |
699 | 1443 | """See `IBug`.""" | 1432 | """See `IBug`.""" |
700 | 1444 | if not self.canBeNominatedFor(target): | 1433 | if not self.canBeNominatedFor(target): |
701 | 1445 | 1434 | ||
702 | === modified file 'lib/lp/bugs/model/bugtask.py' | |||
703 | --- lib/lp/bugs/model/bugtask.py 2011-03-11 03:06:43 +0000 | |||
704 | +++ lib/lp/bugs/model/bugtask.py 2011-03-15 04:26:27 +0000 | |||
705 | @@ -13,7 +13,6 @@ | |||
706 | 13 | 'BugTaskMixin', | 13 | 'BugTaskMixin', |
707 | 14 | 'BugTask', | 14 | 'BugTask', |
708 | 15 | 'BugTaskSet', | 15 | 'BugTaskSet', |
709 | 16 | 'NullBugTask', | ||
710 | 17 | 'bugtask_sort_key', | 16 | 'bugtask_sort_key', |
711 | 18 | 'determine_target', | 17 | 'determine_target', |
712 | 19 | 'get_bug_privacy_filter', | 18 | 'get_bug_privacy_filter', |
713 | @@ -119,7 +118,6 @@ | |||
714 | 119 | IDistroSeriesBugTask, | 118 | IDistroSeriesBugTask, |
715 | 120 | IllegalRelatedBugTasksParams, | 119 | IllegalRelatedBugTasksParams, |
716 | 121 | IllegalTarget, | 120 | IllegalTarget, |
717 | 122 | INullBugTask, | ||
718 | 123 | IProductSeriesBugTask, | 121 | IProductSeriesBugTask, |
719 | 124 | IUpstreamBugTask, | 122 | IUpstreamBugTask, |
720 | 125 | RESOLVED_BUGTASK_STATUSES, | 123 | RESOLVED_BUGTASK_STATUSES, |
721 | @@ -374,68 +372,6 @@ | |||
722 | 374 | return sorted(result, key=pillar_sort_key) | 372 | return sorted(result, key=pillar_sort_key) |
723 | 375 | 373 | ||
724 | 376 | 374 | ||
725 | 377 | class NullBugTask(BugTaskMixin): | ||
726 | 378 | """A null object for IBugTask. | ||
727 | 379 | |||
728 | 380 | This class is used, for example, to be able to render a URL like: | ||
729 | 381 | |||
730 | 382 | /products/evolution/+bug/5 | ||
731 | 383 | |||
732 | 384 | when bug #5 isn't yet reported in evolution. | ||
733 | 385 | """ | ||
734 | 386 | implements(INullBugTask) | ||
735 | 387 | |||
736 | 388 | def __init__(self, bug, product=None, productseries=None, | ||
737 | 389 | sourcepackagename=None, distribution=None, | ||
738 | 390 | distroseries=None): | ||
739 | 391 | """Initialize a NullBugTask.""" | ||
740 | 392 | self.id = None | ||
741 | 393 | self.bug = bug | ||
742 | 394 | self.product = product | ||
743 | 395 | self.productseries = productseries | ||
744 | 396 | self.sourcepackagename = sourcepackagename | ||
745 | 397 | self.distribution = distribution | ||
746 | 398 | self.distroseries = distroseries | ||
747 | 399 | |||
748 | 400 | # Mark the task with the correct interface, depending on its | ||
749 | 401 | # context. | ||
750 | 402 | if self.product: | ||
751 | 403 | alsoProvides(self, IUpstreamBugTask) | ||
752 | 404 | elif self.distribution: | ||
753 | 405 | alsoProvides(self, IDistroBugTask) | ||
754 | 406 | elif self.distroseries: | ||
755 | 407 | alsoProvides(self, IDistroSeriesBugTask) | ||
756 | 408 | elif self.productseries: | ||
757 | 409 | alsoProvides(self, IProductSeriesBugTask) | ||
758 | 410 | else: | ||
759 | 411 | raise AssertionError('Unknown NullBugTask: %r.' % self) | ||
760 | 412 | |||
761 | 413 | # Make us provide the interface by setting all required attributes | ||
762 | 414 | # to None, and define the methods as raising NotImplementedError. | ||
763 | 415 | # The attributes are set to None because it doesn't make | ||
764 | 416 | # sense for these attributes to have a value when there is no | ||
765 | 417 | # real task there. (In fact, it may make sense for these | ||
766 | 418 | # values to be non-null, but I haven't yet found a use case | ||
767 | 419 | # for it, and I don't think there's any point on designing for | ||
768 | 420 | # that until we've encountered one.) | ||
769 | 421 | def this_is_a_null_bugtask_method(*args, **kwargs): | ||
770 | 422 | raise NotImplementedError | ||
771 | 423 | |||
772 | 424 | for name, spec in INullBugTask.namesAndDescriptions(True): | ||
773 | 425 | if not hasattr(self, name): | ||
774 | 426 | if IMethod.providedBy(spec): | ||
775 | 427 | value = this_is_a_null_bugtask_method | ||
776 | 428 | else: | ||
777 | 429 | value = None | ||
778 | 430 | setattr(self, name, value) | ||
779 | 431 | |||
780 | 432 | @property | ||
781 | 433 | def title(self): | ||
782 | 434 | """See `IBugTask`.""" | ||
783 | 435 | return 'Bug #%s is not in %s: "%s"' % ( | ||
784 | 436 | self.bug.id, self.bugtargetdisplayname, self.bug.title) | ||
785 | 437 | |||
786 | 438 | |||
787 | 439 | def BugTaskToBugAdapter(bugtask): | 375 | def BugTaskToBugAdapter(bugtask): |
788 | 440 | """Adapt an IBugTask to an IBug.""" | 376 | """Adapt an IBugTask to an IBug.""" |
789 | 441 | return bugtask.bug | 377 | return bugtask.bug |
790 | @@ -467,9 +403,10 @@ | |||
791 | 467 | else: | 403 | else: |
792 | 468 | target_params[attr[:-2]] = getUtility(utility_iface).get(value) | 404 | target_params[attr[:-2]] = getUtility(utility_iface).get(value) |
793 | 469 | 405 | ||
797 | 470 | # Use a NullBugTask to determine the new target. | 406 | # Update the target name cache with the potential new target. The |
798 | 471 | nulltask = NullBugTask(self.bug, **target_params) | 407 | # attribute changes haven't been made yet, so we need to calculate the |
799 | 472 | self.updateTargetNameCache(nulltask.target) | 408 | # target manually. |
800 | 409 | self.updateTargetNameCache(determine_target(**target_params)) | ||
801 | 473 | 410 | ||
802 | 474 | return value | 411 | return value |
803 | 475 | 412 | ||
804 | 476 | 413 | ||
805 | === modified file 'lib/lp/bugs/templates/bugtask-index.pt' | |||
806 | --- lib/lp/bugs/templates/bugtask-index.pt 2011-02-25 22:09:46 +0000 | |||
807 | +++ lib/lp/bugs/templates/bugtask-index.pt 2011-03-15 04:26:27 +0000 | |||
808 | @@ -72,7 +72,6 @@ | |||
809 | 72 | <div id="tags-autocomplete"> | 72 | <div id="tags-autocomplete"> |
810 | 73 | <div id="tags-autocomplete-content"></div> | 73 | <div id="tags-autocomplete-content"></div> |
811 | 74 | </div> | 74 | </div> |
812 | 75 | <tal:block condition="view/reportBugInContext" /> | ||
813 | 76 | 75 | ||
814 | 77 | <p class="informational message" | 76 | <p class="informational message" |
815 | 78 | tal:condition="view/notices" | 77 | tal:condition="view/notices" |