launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #04566
[Merge] lp:~wgrant/launchpad/launchpadtargetwidget-on-bugtask into lp:launchpad
William Grant has proposed merging lp:~wgrant/launchpad/launchpadtargetwidget-on-bugtask into lp:launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #80902 in Launchpad itself: "Can't target bug report from project to distribution, or vice versa"
https://bugs.launchpad.net/launchpad/+bug/80902
Bug #253508 in Launchpad itself: ""The bug supervisor for <some object> has been subscribed to this bug" is misleading, incomplete, and/or a lie"
https://bugs.launchpad.net/launchpad/+bug/253508
For more details, see:
https://code.launchpad.net/~wgrant/launchpad/launchpadtargetwidget-on-bugtask/+merge/71156
This branch changes BugTaskEditView to use LaunchpadTargetWidget where possible, allowing free retargeting between products and distributions and distribution source packages. The widget is used on all non-series tasks.
ProductSeries tasks are not retargetable, so they have no target widget. DistroSeries and SourcePackage tasks have the old BugTaskSourcePackageNameWidget, as only their sourcepackagename can be changed. validate() maps that into an IBugTarget. I removed the feature flag override from the sourcepackagename widget, as it's highly experimental and doesn't really work, and we're not quite sure what's happening with it.
Now that validate() and updateContextFromData() deal with IBugTargets rather than the various bits of the target key, they can push most of their validation and updating into the model. validateTransitionToTarget() and transitionToTarget() now handle all the messy target logic.
I've removed a pointless and erroneous sourcepackagename-change-specific "The bug supervisor for %s has been subscribed to this bug." notification, fixing bug #253508.
Lots of tests are updated to use LaunchpadTargetWidget, and three new ones have been added for SourcePackage retargeting.
--
https://code.launchpad.net/~wgrant/launchpad/launchpadtargetwidget-on-bugtask/+merge/71156
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/launchpadtargetwidget-on-bugtask into lp:launchpad.
=== modified file 'lib/lp/bugs/browser/bugtask.py'
--- lib/lp/bugs/browser/bugtask.py 2011-08-10 16:18:04 +0000
+++ lib/lp/bugs/browser/bugtask.py 2011-08-11 06:53:12 +0000
@@ -182,6 +182,7 @@
IServiceUsage,
)
from lp.app.widgets.itemswidgets import LabeledMultiCheckBoxWidget
+from lp.app.widgets.launchpadtarget import LaunchpadTargetWidget
from lp.app.widgets.project import ProjectScopeWidget
from lp.bugs.browser.bug import (
BugContextMenu,
@@ -245,7 +246,6 @@
from lp.bugs.interfaces.bugwatch import BugWatchActivityStatus
from lp.bugs.interfaces.cve import ICveSet
from lp.bugs.interfaces.malone import IMaloneApplication
-from lp.bugs.model.bugtask import validate_target
from lp.registry.interfaces.distribution import (
IDistribution,
IDistributionSet,
@@ -267,7 +267,6 @@
from lp.registry.interfaces.sourcepackage import ISourcePackage
from lp.registry.model.personroles import PersonRoles
from lp.registry.vocabularies import MilestoneVocabulary
-from lp.services.features import getFeatureFlag
from lp.services.fields import PersonChoice
from lp.services.propertycache import cachedproperty
@@ -1130,8 +1129,8 @@
# depending on the current context and the permissions of the user viewing
# the form.
default_field_names = ['assignee', 'bugwatch', 'importance', 'milestone',
- 'product', 'sourcepackagename', 'status',
- 'statusexplanation']
+ 'status', 'statusexplanation']
+ custom_widget('target', LaunchpadTargetWidget)
custom_widget('sourcepackagename', BugTaskSourcePackageNameWidget)
custom_widget('bugwatch', BugTaskBugWatchWidget)
custom_widget('assignee', BugTaskAssigneeWidget)
@@ -1144,6 +1143,19 @@
page_title = 'Edit status'
+ @property
+ def show_target_widget(self):
+ # Only non-series tasks can be retargetted.
+ return not ISeriesBugTarget.providedBy(self.context.target)
+
+ @property
+ def show_sourcepackagename_widget(self):
+ # SourcePackage tasks can have only their sourcepackagename changed.
+ # Conjoinment means we can't rely on editing the
+ # DistributionSourcePackage task for this :(
+ return (IDistroSeries.providedBy(self.context.target) or
+ ISourcePackage.providedBy(self.context.target))
+
@cachedproperty
def field_names(self):
"""Return the field names that can be edited by the user."""
@@ -1177,14 +1189,6 @@
editable_field_names.remove("importance")
else:
editable_field_names = set(('bugwatch', ))
- if not IProduct.providedBy(self.context.target):
- #XXX: Bjorn Tillenius 2006-03-01:
- # Should be possible to edit the product as well,
- # but that's harder due to complications with bug
- # watches. The new product might use Launchpad
- # officially, thus we need to handle that case.
- # Let's deal with that later.
- editable_field_names.add('sourcepackagename')
if self.context.bugwatch is None:
editable_field_names.update(('status', 'assignee'))
if ('importance' in self.default_field_names
@@ -1198,6 +1202,11 @@
and self.userCanEditImportance()):
editable_field_names.add('importance')
+ if self.show_target_widget:
+ editable_field_names.add('target')
+ elif self.show_sourcepackagename_widget:
+ editable_field_names.add('sourcepackagename')
+
# To help with caching, return an immutable object.
return frozenset(editable_field_names)
@@ -1242,6 +1251,11 @@
super(BugTaskEditView, self).setUpFields()
read_only_field_names = self._getReadOnlyFieldNames()
+ if 'target' in self.editable_field_names:
+ self.form_fields = self.form_fields.omit('target')
+ target_field = copy_field(IBugTask['target'], readonly=False)
+ self.form_fields += formlib.form.Fields(target_field)
+
# The status field is a special case because we alter the vocabulary
# it uses based on the permissions of the user viewing form.
if 'status' in self.editable_field_names:
@@ -1331,14 +1345,6 @@
self.form_fields['assignee'].custom_widget = CustomWidgetFactory(
BugTaskAssigneeWidget)
- if bool(getFeatureFlag('disclosure.dsp_picker.enabled')):
- # Replace the default field with a field that uses the better
- # vocabulary.
- self.form_fields = self.form_fields.omit('sourcepackagename')
- self.form_fields += formlib.form.Fields(Choice(
- __name__='sourcepackagename', title=_('SourcePackageName'),
- required=False, vocabulary='DistributionSourcePackage'))
-
def _getReadOnlyFieldNames(self):
"""Return the names of fields that will be rendered read only."""
if self.context.target_uses_malone:
@@ -1372,42 +1378,22 @@
return self.context.userCanEditImportance(self.user)
def validate(self, data):
- """See `LaunchpadFormView`."""
- bugtask = self.context
- if bugtask.distroseries is not None:
- distro = bugtask.distroseries.distribution
- else:
- distro = bugtask.distribution
- old_product = bugtask.product
-
- new_spn = data.get('sourcepackagename')
- if distro is not None and bugtask.sourcepackagename != new_spn:
- try:
- target = distro
- if new_spn is not None:
- target = distro.getSourcePackage(new_spn)
- validate_target(bugtask.bug, target)
- except IllegalTarget as e:
- # The field validator may have already set an error.
- # Don't clobber it.
- if not self.getFieldError('sourcepackagename'):
- self.setFieldError('sourcepackagename', e[0])
-
- new_product = data.get('product')
- if (old_product is None or old_product == new_product or
- bugtask.pillar.bug_tracking_usage != ServiceUsage.LAUNCHPAD):
- # Either the product wasn't changed, we're dealing with a #
- # distro task, or the bugtask's product doesn't use Launchpad,
- # which means the product can't be changed.
- return
-
- if new_product is None:
- self.setFieldError('product', 'Enter a project name')
- else:
- try:
- validate_target(bugtask.bug, new_product)
- except IllegalTarget as e:
- self.setFieldError('product', e[0])
+ if self.show_sourcepackagename_widget and 'sourcepackagename' in data:
+ data['target'] = self.context.distroseries
+ spn = data.get('sourcepackagename')
+ if spn:
+ data['target'] = data['target'].getSourcePackage(spn)
+ del data['sourcepackagename']
+ error_field = 'sourcepackagename'
+ else:
+ error_field = 'target'
+
+ new_target = data.get('target')
+ if new_target and new_target != self.context.target:
+ try:
+ self.context.validateTransitionToTarget(new_target)
+ except IllegalTarget as e:
+ self.setFieldError(error_field, e[0])
def updateContextFromData(self, data, context=None):
"""Updates the context object using the submitted form data.
@@ -1439,9 +1425,14 @@
# product, we'll clear out the milestone value, to avoid
# violating DB constraints that ensure an upstream task can't
# be assigned to a milestone on a different product.
+ # This is also done by transitionToTarget, but do it here so we
+ # can display notifications and remove the milestone from the
+ # submitted data.
milestone_cleared = None
milestone_ignored = False
- if bugtask.product and bugtask.product != new_values.get("product"):
+ missing = object()
+ new_target = new_values.pop("target", missing)
+ if new_target is not missing and bugtask.target != new_target:
# We clear the milestone value if one was already set. We ignore
# the milestone value if it was currently None, and the user tried
# to set a milestone value while also changing the product. This
@@ -1460,12 +1451,10 @@
# what it was!
data_to_apply.pop('milestone', None)
- # We special case setting assignee and status, because there's
- # a workflow associated with changes to these fields.
- if "assignee" in data_to_apply:
- del data_to_apply["assignee"]
- if "status" in data_to_apply:
- del data_to_apply["status"]
+ # We special case setting target, status and assignee, because
+ # there's a workflow associated with changes to these fields.
+ for manual_field in ('target', 'status', 'assignee'):
+ data_to_apply.pop(manual_field, None)
# We grab the comment_on_change field before we update bugtask so as
# to avoid problems accessing the field if the user has changed the
@@ -1476,6 +1465,16 @@
changed = formlib.form.applyChanges(
bugtask, self.form_fields, data_to_apply, self.adapters)
+ # Set the "changed" flag properly, just in case status and/or assignee
+ # happen to be the only values that changed. We explicitly verify that
+ # we got a new status and/or assignee, because the form is not always
+ # guaranteed to pass all the values. For example: bugtasks linked to a
+ # bug watch don't allow editing the form, and the value is missing
+ # from the form.
+ if new_target is not missing and bugtask.target != new_target:
+ changed = True
+ bugtask.transitionToTarget(new_target)
+
# Now that we've updated the bugtask we can add messages about
# milestone changes, if there were any.
if milestone_cleared:
@@ -1496,13 +1495,6 @@
subject=bugtask.bug.followup_subject(),
content=comment_on_change)
- # Set the "changed" flag properly, just in case status and/or assignee
- # happen to be the only values that changed. We explicitly verify that
- # we got a new status and/or assignee, because the form is not always
- # guaranteed to pass all the values. For example: bugtasks linked to a
- # bug watch don't allow editing the form, and the value is missing
- # from the form.
- missing = object()
new_status = new_values.pop("status", missing)
new_assignee = new_values.pop("assignee", missing)
if new_status is not missing and bugtask.status != new_status:
@@ -1583,15 +1575,20 @@
object_before_modification=bugtask_before_modification,
edited_fields=field_names))
- if bugtask.sourcepackagename is not None:
+ if (bugtask.sourcepackagename and (
+ self.widgets.get('target') or
+ self.widgets.get('sourcepackagename'))):
real_package_name = bugtask.sourcepackagename.name
# We get entered_package_name directly from the form here, since
# validating the sourcepackagename field mutates its value in to
# the one already in real_package_name, which makes our comparison
# of the two below useless.
- entered_package_name = self.request.form.get(
- self.widgets['sourcepackagename'].name)
+ if self.widgets.get('sourcepackagename'):
+ field_name = self.widgets['sourcepackagename'].name
+ else:
+ field_name = self.widgets['target'].package_widget.name
+ entered_package_name = self.request.form.get(field_name)
if real_package_name != entered_package_name:
# The user entered a binary package name which got
@@ -1603,14 +1600,6 @@
{'entered_package': entered_package_name,
'real_package': real_package_name})
- if (bugtask_before_modification.sourcepackagename !=
- bugtask.sourcepackagename):
- # The source package was changed, so tell the user that we've
- # subscribed the new bug supervisors.
- self.request.response.addNotification(
- "The bug supervisor for %s has been subscribed to this bug."
- % (bugtask.bugtargetdisplayname))
-
@action('Save Changes', name='save')
def save_action(self, action, data):
"""Update the bugtask with the form data."""
=== modified file 'lib/lp/bugs/browser/tests/bugtask-edit-views.txt'
--- lib/lp/bugs/browser/tests/bugtask-edit-views.txt 2011-07-27 08:04:46 +0000
+++ lib/lp/bugs/browser/tests/bugtask-edit-views.txt 2011-08-11 06:53:12 +0000
@@ -24,9 +24,7 @@
... 'ubuntu_thunderbird.importance':
... ubuntu_thunderbird_task.importance.title,
... 'ubuntu_thunderbird.ubuntu_thunderbird.assignee.option':
- ... 'ubuntu_thunderbird.assignee.assign_to_nobody',
- ... 'ubuntu_thunderbird.sourcepackagename':
- ... ubuntu_thunderbird_task.sourcepackagename.name}
+ ... 'ubuntu_thunderbird.assignee.assign_to_nobody'}
>>> request = LaunchpadTestRequest(method='POST', form=edit_form)
>>> edit_view = getMultiAdapter(
... (ubuntu_thunderbird_task, request), name='+editstatus')
@@ -47,7 +45,9 @@
>>> ubuntu_thunderbird = ubuntu_thunderbird_task.target
- >>> edit_form['ubuntu_thunderbird.sourcepackagename'] = u'linux-2.6.12'
+ >>> 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')
@@ -62,8 +62,6 @@
... 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 bug supervisor for linux-source-2.6.15 (Ubuntu) has been
- subscribed to this bug.
>>> # The sampledata is bad -- the original thunderbird task should
>>> # not exist, as there is no publication. Create one so we can
@@ -77,15 +75,16 @@
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.sourcepackagename'] = u'no-such-package'
+ >>> 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"Launchpad doesn't know of any source package named 'no-such-package'
- in Ubuntu.", None)
+ (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.
@@ -107,7 +106,8 @@
... product_task.importance.title,
... 'evolution.evolution.assignee.option':
... 'evolution.assignee.assign_to_nobody',
- ... 'evolution.product': 'firefox',
+ ... 'evolution.target': 'product',
+ ... 'evolution.target.product': 'firefox',
... }
>>> request = LaunchpadTestRequest(form=edit_form, method='POST')
>>> edit_view = getMultiAdapter(
@@ -127,7 +127,8 @@
... product_task.importance.title,
... 'firefox.firefox.assignee.option':
... 'firefox.assignee.assign_to_nobody',
- ... 'firefox.product': '',
+ ... 'firefox.target': 'product',
+ ... 'firefox.target.product': '',
... }
>>> request = LaunchpadTestRequest(form=edit_form, method='POST')
>>> edit_view = getMultiAdapter(
@@ -135,7 +136,7 @@
>>> edit_view.initialize()
>>> for error in edit_view.errors:
... print error
- Enter a project name
+ ('product', u'Project', RequiredMissing())
== Bug Watch Linkage ==
=== modified file 'lib/lp/bugs/browser/tests/test_bugtask.py'
--- lib/lp/bugs/browser/tests/test_bugtask.py 2011-08-03 05:00:46 +0000
+++ lib/lp/bugs/browser/tests/test_bugtask.py 2011-08-11 06:53:12 +0000
@@ -171,7 +171,8 @@
transaction.commit()
with person_logged_in(person):
form_data = {
- '%s.product' % product.name: product_2.name,
+ '%s.target' % product.name: 'product',
+ '%s.target.product' % product.name: product_2.name,
'%s.status' % product.name: BugTaskStatus.TRIAGED.title,
'%s.actions.save' % product.name: 'Save Changes',
}
@@ -722,7 +723,9 @@
'ubuntu_rabbit.importance': 'High',
'ubuntu_rabbit.assignee.option':
'ubuntu_rabbit.assignee.assign_to_nobody',
- 'ubuntu_rabbit.sourcepackagename': 'mouse',
+ 'ubuntu_rabbit.target': 'package',
+ 'ubuntu_rabbit.target.distribution': 'ubuntu',
+ 'ubuntu_rabbit.target.package': 'mouse',
}
view = create_initialized_view(
bug_task_2, name='+editstatus', form=form, principal=user)
@@ -755,7 +758,8 @@
form = {
'bunny.status': 'In Progress',
'bunny.assignee.option': 'bunny.assignee.assign_to_nobody',
- 'bunny.product': 'duck',
+ 'bunny.target': 'product',
+ 'bunny.target.product': 'duck',
'bunny.actions.save': 'Save Changes',
}
view = create_initialized_view(
@@ -777,7 +781,8 @@
form = {
'bunny.status': 'In Progress',
'bunny.assignee.option': 'bunny.assignee.assign_to_nobody',
- 'bunny.product': 'duck',
+ 'bunny.target': 'product',
+ 'bunny.target.product': 'duck',
'bunny.milestone': milestone_id,
'bunny.actions.save': 'Save Changes',
}
@@ -791,6 +796,74 @@
expected = ('The milestone setting was ignored')
self.assertTrue(notifications.pop().message.startswith(expected))
+ def createNameChangingViewForSourcePackageTask(bug_task, new_name):
+ login_person(bug_task.owner)
+ form_prefix = '%s_%s_%s' % (
+ bug_task.target.distroseries.distribution.name,
+ bug_task.target.distroseries.name,
+ bug_task.target.sourcepackagename.name)
+ form = {
+ form_prefix + '.sourcepackagename': new_name,
+ form_prefix + '.actions.save': 'Save Changes',
+ }
+ view = create_initialized_view(
+ bug_task, name='+editstatus', form=form)
+ return view
+
+ def test_retarget_sourcepackage(self):
+ # The sourcepackagename of a SourcePackage task can be changed.
+ ds = self.factory.makeDistroSeries()
+ sp1 = self.factory.makeSourcePackage(distroseries=ds, publish=True)
+ sp2 = self.factory.makeSourcePackage(distroseries=ds, publish=True)
+ bug_task = self.factory.makeBugTask(target=sp1)
+
+ view = self.createNameChangingViewForSourcePackageTask(
+ bug_task, sp2.sourcepackagename.name)
+ self.assertEqual([], view.errors)
+ self.assertEqual(sp2, bug_task.target)
+ notifications = view.request.response.notifications
+ self.assertEqual(0, len(notifications))
+
+ def test_retarget_sourcepackage_to_binary_name(self):
+ # The sourcepackagename of a SourcePackage task can be changed
+ # to a binarypackagename, which gets mapped back to the source.
+ ds = self.factory.makeDistroSeries()
+ das = self.factory.makeDistroArchSeries(distroseries=ds)
+ sp1 = self.factory.makeSourcePackage(distroseries=ds, publish=True)
+ # Now create a binary and its corresponding SourcePackage.
+ bp = self.factory.makeBinaryPackagePublishingHistory(
+ distroarchseries=das)
+ bpr = bp.binarypackagerelease
+ spn = bpr.build.source_package_release.sourcepackagename
+ sp2 = self.factory.makeSourcePackage(
+ distroseries=ds, sourcepackagename=spn, publish=True)
+ bug_task = self.factory.makeBugTask(target=sp1)
+
+ view = self.createNameChangingViewForSourcePackageTask(
+ bug_task, bpr.binarypackagename.name)
+ self.assertEqual([], view.errors)
+ self.assertEqual(sp2, bug_task.target)
+ notifications = view.request.response.notifications
+ self.assertEqual(1, len(notifications))
+ expected = (
+ "'%s' is a binary package. This bug has been assigned to its "
+ "source package '%s' instead."
+ % (bpr.binarypackagename.name, spn.name))
+ self.assertTrue(notifications.pop().message.startswith(expected))
+
+ def test_retarget_sourcepackage_to_distroseries(self):
+ # A SourcePackage task can be changed to a DistroSeries one.
+ ds = self.factory.makeDistroSeries()
+ sp = self.factory.makeSourcePackage(distroseries=ds, publish=True)
+ bug_task = self.factory.makeBugTask(target=sp)
+
+ view = self.createNameChangingViewForSourcePackageTask(
+ bug_task, '')
+ self.assertEqual([], view.errors)
+ self.assertEqual(ds, bug_task.target)
+ notifications = view.request.response.notifications
+ self.assertEqual(0, len(notifications))
+
class TestProjectGroupBugs(TestCaseWithFactory):
"""Test the bugs overview page for Project Groups."""
=== modified file 'lib/lp/bugs/stories/bug-also-affects/xx-bug-also-affects.txt'
--- lib/lp/bugs/stories/bug-also-affects/xx-bug-also-affects.txt 2011-07-25 22:27:37 +0000
+++ lib/lp/bugs/stories/bug-also-affects/xx-bug-also-affects.txt 2011-08-11 06:53:12 +0000
@@ -56,7 +56,8 @@
>>> browser.open(
... "http://localhost/ubuntu/+bug/6/+editstatus")
- >>> browser.getControl("Package").value = "mozilla-firefox"
+ >>> browser.getControl(name="ubuntu.target.package").value = (
+ ... "mozilla-firefox")
>>> browser.getControl("Save Changes").click()
>>> browser.open(
@@ -72,7 +73,8 @@
>>> browser.open(
... "http://localhost/ubuntu/+source/mozilla-firefox/+bug/6/"
... "+editstatus")
- >>> browser.getControl("Package").value = "evolution"
+ >>> browser.getControl(name="ubuntu_mozilla-firefox.target.package"
+ ... ).value = "evolution"
>>> browser.getControl("Save Changes").click()
>>> print get_feedback_messages(browser.contents)
[...There is 1 error in the data you entered...
@@ -126,7 +128,8 @@
>>> browser.url
'http://bugs.../ubuntu/+source/mozilla-firefox/+bug/1/+editstatus'
- >>> browser.getControl('Package').value = 'alsa-utils'
+ >>> browser.getControl(name="ubuntu_mozilla-firefox.target.package"
+ ... ).value = 'alsa-utils'
>>> browser.getControl('Save Changes').click()
>>> browser.url
'http://bugs.../ubuntu/+source/mozilla-firefox/+bug/1/+editstatus'
@@ -135,7 +138,8 @@
u'A fix for this bug has already been requested for alsa-utils in
Ubuntu']
- >>> browser.getControl('Package').value = 'pmount'
+ >>> browser.getControl(name="ubuntu_mozilla-firefox.target.package"
+ ... ).value = 'pmount'
>>> browser.getControl('Save Changes').click()
>>> browser.url
'http://bugs.launchpad.dev/ubuntu/+source/pmount/+bug/1'
@@ -382,7 +386,8 @@
>>> user_browser.getLink(url='evolution/+bug/3/+editstatus').click()
>>> user_browser.url
'http://bugs.launchpad.dev/evolution/+bug/3/+editstatus'
- >>> user_browser.getControl('Project').value = 'alsa-utils'
+ >>> user_browser.getControl(name='evolution.target.product').value = (
+ ... 'alsa-utils')
>>> user_browser.getControl('Save Changes').click()
>>> user_browser.url
'http://bugs.launchpad.dev/evolution/+bug/3/+editstatus'
=== modified file 'lib/lp/bugs/stories/bugs/xx-bug-activity.txt'
--- lib/lp/bugs/stories/bugs/xx-bug-activity.txt 2011-05-31 16:43:11 +0000
+++ lib/lp/bugs/stories/bugs/xx-bug-activity.txt 2011-08-11 06:53:12 +0000
@@ -291,7 +291,8 @@
... 'http://bugs.launchpad.dev/ubuntu/+source/mozilla-firefox/+bug/'
... '1/+editstatus')
>>> admin_browser.getControl(
- ... 'Package').value = 'linux-source-2.6.15'
+ ... name='ubuntu_mozilla-firefox.target.package'
+ ... ).value = 'linux-source-2.6.15'
>>> admin_browser.getControl("Save Changes").click()
>>> print_comments(admin_browser.contents)
Foo Bar (name16)
=== modified file 'lib/lp/bugs/stories/bugtask-management/xx-bug-privileged-statuses.txt'
--- lib/lp/bugs/stories/bugtask-management/xx-bug-privileged-statuses.txt 2010-06-16 17:31:50 +0000
+++ lib/lp/bugs/stories/bugtask-management/xx-bug-privileged-statuses.txt 2011-08-11 06:53:12 +0000
@@ -95,7 +95,8 @@
And a regular user can change other aspects of the bug:
- >>> package_control = user_browser.getControl('Package')
+ >>> package_control = user_browser.getControl(
+ ... name='ubuntu_mozilla-firefox.target.package')
>>> print package_control.value
mozilla-firefox
=== modified file 'lib/lp/bugs/stories/bugtask-management/xx-bugtask-edit-forms.txt'
--- lib/lp/bugs/stories/bugtask-management/xx-bugtask-edit-forms.txt 2010-07-12 16:32:31 +0000
+++ lib/lp/bugs/stories/bugtask-management/xx-bugtask-edit-forms.txt 2011-08-11 06:53:12 +0000
@@ -43,6 +43,9 @@
Filed here by: Sample Person
When: 2004-01-02
Assigned: 2005-01-02
+Target
+Distribution
+...
Project (Find…)
Status Importance Milestone
New... Low... (no value)...
=== modified file 'lib/lp/bugs/templates/bugtask-edit-form.pt'
--- lib/lp/bugs/templates/bugtask-edit-form.pt 2011-05-18 18:34:19 +0000
+++ lib/lp/bugs/templates/bugtask-edit-form.pt 2011-08-11 06:53:12 +0000
@@ -114,52 +114,45 @@
</tr>
</table>
<div class="field">
- <table>
- <tal:distrotask
- condition="python:context.distribution or context.distroseries"
- define="error python:view.getFieldError('sourcepackagename')"
- >
- <tr>
- <td>
- <label
- tal:attributes="for view/widgets/sourcepackagename/name"
- tal:content="view/widgets/sourcepackagename/label"
- >Source package name</label>
- </td>
- </tr>
- <tr tal:attributes="class python:error and 'error' or None">
- <td>
- <tal:widget content="structure view/widgets/sourcepackagename" />
- <div tal:condition="error"
- class="message"
- tal:content="error">An error in sourcepackagename widget.
- </div>
- </td>
- </tr>
- </tal:distrotask>
-
- <tal:upstreamtask
- condition="python:context.product"
- define="omit_required python:True;
- error python:view.getFieldError('product')">
- <tr>
- <td colspan="2">
- <label style="font-weight: bold"
- tal:attributes="for view/widgets/product/name"
- tal:content="view/widgets/product/label"
- >Upstream project</label>
- </td>
- </tr>
- <tr tal:attributes="class python:error and 'error' or None">
- <td colspan="2" style="white-space: nowrap">
- <tal:widget content="structure view/widgets/product" />
- <div tal:condition="error"
- class="message"
- tal:content="error">An error in product widget.
- </div>
- </td>
- </tr>
- </tal:upstreamtask>
+ <table tal:condition="view/show_target_widget">
+ <tr>
+ <td>
+ <label
+ tal:attributes="for view/widgets/target/name"
+ tal:content="view/widgets/target/label"
+ >Target</label>
+ </td>
+ </tr>
+ <tr tal:define="error python:view.getFieldError('target')"
+ tal:attributes="class python:error and 'error' or None">
+ <td>
+ <tal:widget content="structure view/widgets/target" />
+ <div tal:condition="error"
+ class="message"
+ tal:content="error">An error in target widget.
+ </div>
+ </td>
+ </tr>
+ </table>
+ <table tal:condition="view/show_sourcepackagename_widget">
+ <tr>
+ <td>
+ <label
+ tal:attributes="for view/widgets/sourcepackagename/name"
+ tal:content="view/widgets/sourcepackagename/label"
+ >Package</label>
+ </td>
+ </tr>
+ <tr tal:define="error python:view.getFieldError('sourcepackagename')"
+ tal:attributes="class python:error and 'error' or None">
+ <td>
+ <tal:widget content="structure view/widgets/sourcepackagename" />
+ <div tal:condition="error"
+ class="message"
+ tal:content="error">An error in sourcepackagename widget.
+ </div>
+ </td>
+ </tr>
</table>
<table>
<tr>
=== modified file 'lib/lp/registry/stories/product/xx-product-reassignment-and-milestones.txt'
--- lib/lp/registry/stories/product/xx-product-reassignment-and-milestones.txt 2009-05-12 20:28:19 +0000
+++ lib/lp/registry/stories/product/xx-product-reassignment-and-milestones.txt 2011-08-11 06:53:12 +0000
@@ -4,7 +4,7 @@
>>> browser = setupBrowser(auth="Basic foo.bar@xxxxxxxxxxxxx:test")
>>> browser.open("http://bugs.launchpad.dev/firefox/+bug/1/+editstatus")
- >>> browser.getControl("Project").value = "evolution"
+ >>> browser.getControl(name="firefox.target.product").value = "evolution"
>>> browser.getControl("Milestone").value = ["1"]
>>> browser.getControl("Save Changes").click()
@@ -16,7 +16,7 @@
(Revert the change we just made.)
>>> browser.open("http://bugs.launchpad.dev/evolution/+bug/1/+editstatus")
- >>> browser.getControl("Project").value = "firefox"
+ >>> browser.getControl(name="evolution.target.product").value = "firefox"
>>> browser.getControl("Save Changes").click()
(The "ignore" message doesn't appear when the user didn't set a
@@ -33,7 +33,7 @@
>>> browser.getControl("Save Changes").click()
>>> browser.open("http://localhost:9000/firefox/+bug/1/+editstatus")
- >>> browser.getControl("Project").value = "evolution"
+ >>> browser.getControl(name="firefox.target.product").value = "evolution"
>>> browser.getControl("Save Changes").click()
>>> for message in find_tags_by_class(browser.contents, 'message'):