~launchpad-pqm/launchpad/devel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
= Editing Bug Tasks =

A bugtask's status, assignee, package name, milestone, etc., can be
modified on its +editstatus page.


== Edit the Status ==

Let's start simple and edit the status of a bug task logged in as Sample
Person:

    >>> from zope.component import getMultiAdapter
    >>> from lp.services.webapp.servers import LaunchpadTestRequest
    >>> from lp.bugs.interfaces.bug import IBugSet
    >>> login('test@canonical.com')
    >>> bug_nine = getUtility(IBugSet).get(9)
    >>> ubuntu_thunderbird_task = bug_nine.bugtasks[1]
    >>> ubuntu_thunderbird_task.status.title
    'Confirmed'

    >>> edit_form = {
    ...    'ubuntu_thunderbird.actions.save': 'Save Changes',
    ...    'ubuntu_thunderbird.status': 'In Progress',
    ...    'ubuntu_thunderbird.importance':
    ...        ubuntu_thunderbird_task.importance.title,
    ...    'ubuntu_thunderbird.ubuntu_thunderbird.assignee.option':
    ...        'ubuntu_thunderbird.assignee.assign_to_nobody'}
    >>> request = LaunchpadTestRequest(method='POST', form=edit_form)
    >>> edit_view = getMultiAdapter(
    ...     (ubuntu_thunderbird_task, request), name='+editstatus')
    >>> edit_view.initialize()
    >>> ubuntu_thunderbird_task.status.title
    'In Progress'


== Edit the Package ==

When editing the package of a distribution task, the user may enter
either a binary or a source package name. We only deal with bugs on
source packages, though, so if a binary name is entered, it gets mapped
to the correct source package. For example, the binary package
linux-2.6.12 is built from the source package linux-source-2.6.15, so
if linux-2.6.12 is entered in the package field, the bugtask will be
assigned to linux-source-2.6.15 instead.


    >>> ubuntu_thunderbird = ubuntu_thunderbird_task.target
    >>> edit_form['ubuntu_thunderbird.target'] = 'package'
    >>> edit_form['ubuntu_thunderbird.target.distribution'] = 'ubuntu'
    >>> edit_form['ubuntu_thunderbird.target.package'] = u'linux-2.6.12'
    >>> request = LaunchpadTestRequest(method='POST', form=edit_form)
    >>> edit_view = getMultiAdapter(
    ...     (ubuntu_thunderbird_task, request), name='+editstatus')
    >>> edit_view.initialize()
    >>> ubuntu_thunderbird_task.sourcepackagename.name
    u'linux-source-2.6.15'

A notification was added informing the user that the binary package was
changed to the corresponding source package.

    >>> for notification in edit_view.request.response.notifications:
    ...     print notification.message
    'linux-2.6.12' is a binary package. This bug has been assigned to
    its source package 'linux-source-2.6.15' instead.

    >>> # The sampledata is bad -- the original thunderbird task should
    >>> # not exist, as there is no publication. Create one so we can
    >>> # set it back.
    >>> ignored = factory.makeSourcePackagePublishingHistory(
    ...     distroseries=
    ...         ubuntu_thunderbird_task.target.distribution.currentseries,
    ...     sourcepackagename='thunderbird')
    >>> ubuntu_thunderbird_task.transitionToTarget(ubuntu_thunderbird)

If we try to change the source package to package name that doesn't
exist in Launchpad. we'll get an error message.

    >>> edit_form['ubuntu_thunderbird.target.package'] = u'no-such-package'
    >>> request = LaunchpadTestRequest(form=edit_form, method='POST')
    >>> edit_view = getMultiAdapter(
    ...     (ubuntu_thunderbird_task, request), name='+editstatus')
    >>> edit_view.initialize()
    >>> for error in edit_view.errors:
    ...     print error
    (u'ubuntu_thunderbird.target', u'Target',
     LaunchpadValidationError(u"There is no package name 'no-such-package'
     published in Ubuntu"))

An error is reported to the user when a bug is retargeted and there is
an existing task for the same target.

== Edit the Product ==

+editstatus allows a bug to be retargeted to another product.

    >>> login('test@canonical.com')
    >>> bug_seven = getUtility(IBugSet).get(7)
    >>> product_task = bug_seven.bugtasks[0]
    >>> product_task.bugtargetname
    u'evolution'

    >>> edit_form = {
    ...    'evolution.actions.save': 'Save Changes',
    ...    'evolution.status': product_task.status.title,
    ...    'evolution.importance':
    ...        product_task.importance.title,
    ...    'evolution.evolution.assignee.option':
    ...        'evolution.assignee.assign_to_nobody',
    ...    'evolution.target': 'product',
    ...    'evolution.target.product': 'firefox',
    ...     }
    >>> request = LaunchpadTestRequest(form=edit_form, method='POST')
    >>> edit_view = getMultiAdapter(
    ...     (product_task, request), name='+editstatus')
    >>> edit_view.initialize()
    >>> [str(error) for error in edit_view.errors]
    []
    >>> product_task.bugtargetname
    u'firefox'

If no product name is given, an error message is displayed.

    >>> edit_form = {
    ...    'firefox.actions.save': 'Save Changes',
    ...    'firefox.status': product_task.status.title,
    ...    'firefox.importance':
    ...        product_task.importance.title,
    ...    'firefox.firefox.assignee.option':
    ...        'firefox.assignee.assign_to_nobody',
    ...    'firefox.target': 'product',
    ...    'firefox.target.product': '',
    ...     }
    >>> request = LaunchpadTestRequest(form=edit_form, method='POST')
    >>> edit_view = getMultiAdapter(
    ...     (product_task, request), name='+editstatus')
    >>> edit_view.initialize()
    >>> for error in edit_view.errors:
    ...     print error
    ('product', u'Project', RequiredMissing())


== Bug Watch Linkage ==

Let's edit a bugtask which is linked to a remote bug. The most
important thing to edit is the bug watch, since it controls the status
information about the bug task. To show it how it works we remove the
link temporarily:

    >>> bug_nine = getUtility(IBugSet).get(9)
    >>> thunderbird_task = bug_nine.bugtasks[0]
    >>> bugzilla_watch = thunderbird_task.bugwatch
    >>> thunderbird_task.bugwatch = None

Now we simulate that the bug watch got updated:

    >>> from zope.security.proxy import removeSecurityProxy
    >>> removeSecurityProxy(bugzilla_watch).remotestatus = 'RESOLVED FIXED'

If we now link the bugtask to the bug watch, the bugtask's status will
be set to Unknown:

XXX: We really should update the status from the bug watch, but that's
     not trivial to do at the moment. I will fix this later.
     -- Bjorn Tillenius, 2006-03-01

    >>> from lp.bugs.interfaces.bugtask import BugTaskStatus
    >>> thunderbird_task.transitionToStatus(
    ...     BugTaskStatus.NEW, getUtility(ILaunchBag).user)
    >>> request = LaunchpadTestRequest(
    ...     method='POST',
    ...     form={
    ...         'thunderbird.actions.save': 'Save Changes',
    ...         'thunderbird.status': 'Confirmed',
    ...         'thunderbird.importance': 'Critical',
    ...         'thunderbird.bugwatch': '6'})
    >>> edit_view = getMultiAdapter(
    ...     (thunderbird_task, request), name='+editstatus')
    >>> edit_view.initialize()
    >>> thunderbird_task.bugwatch == bugzilla_watch
    True
    >>> thunderbird_task.status.title
    'Unknown'

If we unlink the bug watch, the bugtask's status and importance will be
set to their default values:

    >>> request = LaunchpadTestRequest(
    ...     method='POST',
    ...     form={
    ...         'thunderbird.actions.save': 'Save Changes',
    ...         'thunderbird.bugwatch-empty-marker': '1'})
    >>> edit_view = getMultiAdapter(
    ...     (thunderbird_task, request), name='+editstatus')
    >>> edit_view.initialize()
    >>> thunderbird_task.bugwatch is None
    True

    >>> from lp.bugs.interfaces.bugtask import IBugTask
    >>> thunderbird_task.status == IBugTask['status'].default
    True
    >>> thunderbird_task.importance == IBugTask['importance'].default
    True


== Milestone Editing Permissions ==

A milestone can be edited only by a user with launchpad.Edit permissions
on the distribution or product context. When the user has this
permission, the edit page renders an input widget, otherwise it renders
a display widget.

    >>> from zope.app.form.interfaces import IInputWidget
    >>> from lp.bugs.interfaces.bugtask import IBugTaskSet

The distribution owner gets an edit widget for the distribution task.

    >>> login("mark@example.com")

    >>> request = LaunchpadTestRequest()
    >>> ubuntu_task = getUtility(IBugTaskSet).get(17)
    >>> bugtask_edit_view = getMultiAdapter(
    ...     (ubuntu_task, request), name="+editstatus")
    >>> bugtask_edit_view.initialize()

    >>> IInputWidget.providedBy(bugtask_edit_view.widgets['milestone'])
    True

But an unprivileged user does not.

    >>> from zope.app.form.browser import ItemDisplayWidget

    >>> login("no-priv@canonical.com")

    >>> bugtask_edit_view = getMultiAdapter(
    ...     (ubuntu_task, request), name="+editstatus")
    >>> bugtask_edit_view.initialize()

    >>> isinstance(bugtask_edit_view.widgets['milestone'], ItemDisplayWidget)
    True

A bug supervisor can also change the milestone. Let's set no-priv as
Ubuntu's bug supervisor.

    >>> from lp.registry.interfaces.person import IPersonSet
    >>> from lp.registry.interfaces.distribution import IDistributionSet

    >>> login("foo.bar@canonical.com")
    >>> ubuntu = getUtility(IDistributionSet).getByName("ubuntu")
    >>> no_priv = getUtility(IPersonSet).getByName("no-priv")
    >>> ubuntu.setBugSupervisor(no_priv, no_priv)

Unlike before, no-priv can now edit the milestone.

    >>> bugtask_edit_view = getMultiAdapter(
    ...     (ubuntu_task, request), name="+editstatus")
    >>> bugtask_edit_view.initialize()

    >>> IInputWidget.providedBy(bugtask_edit_view.widgets['milestone'])
    True