launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #05112
[Merge] lp:~wgrant/launchpad/bug-860920 into lp:launchpad
William Grant has proposed merging lp:~wgrant/launchpad/bug-860920 into lp:launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #860920 in Launchpad itself: "reassigning bugs between packages in a single distribution clears the milestone"
https://bugs.launchpad.net/launchpad/+bug/860920
For more details, see:
https://code.launchpad.net/~wgrant/launchpad/bug-860920/+merge/77271
This branch fixes bug #860920, preserving bug task milestones when transitioning between targets within a pillar (eg. changing the package name of a distribution task).
I added a new IBugTarget['pillar'], added it to the various implementations, and altered the milestone unsetting code to match the pillars instead of the targets themselves.
--
https://code.launchpad.net/~wgrant/launchpad/bug-860920/+merge/77271
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/bug-860920 into lp:launchpad.
=== modified file 'lib/lp/bugs/browser/bugtask.py'
--- lib/lp/bugs/browser/bugtask.py 2011-09-26 06:30:07 +0000
+++ lib/lp/bugs/browser/bugtask.py 2011-09-28 03:43:50 +0000
@@ -1570,7 +1570,8 @@
milestone_ignored = False
missing = object()
new_target = new_values.pop("target", missing)
- if new_target is not missing and bugtask.target != new_target:
+ if (new_target is not missing and
+ bugtask.target.pillar != new_target.pillar):
# 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
=== modified file 'lib/lp/bugs/interfaces/bugtarget.py'
--- lib/lp/bugs/interfaces/bugtarget.py 2011-07-29 05:33:02 +0000
+++ lib/lp/bugs/interfaces/bugtarget.py 2011-09-28 03:43:50 +0000
@@ -296,6 +296,8 @@
bugtargetdisplayname = Attribute("A display name for this bug target")
bugtargetname = Attribute("The target as shown in mail notifications.")
+ pillar = Attribute("The pillar containing this target.")
+
bug_reporting_guidelines = exported(
Text(
title=(
=== modified file 'lib/lp/bugs/model/bugtask.py'
--- lib/lp/bugs/model/bugtask.py 2011-09-26 02:06:25 +0000
+++ lib/lp/bugs/model/bugtask.py 2011-09-28 03:43:50 +0000
@@ -563,14 +563,7 @@
@property
def pillar(self):
"""See `IBugTask`."""
- if self.product is not None:
- return self.product
- elif self.productseries is not None:
- return self.productseries.product
- elif self.distribution is not None:
- return self.distribution
- else:
- return self.distroseries.distribution
+ return self.target.pillar
@property
def other_affected_pillars(self):
@@ -1120,10 +1113,8 @@
# are product tasks).
distros = set()
for potential_target in (target, self.target):
- if IDistribution.providedBy(potential_target):
- distros.add(potential_target)
- elif IDistributionSourcePackage.providedBy(potential_target):
- distros.add(potential_target.distribution)
+ if IDistribution.providedBy(potential_target.pillar):
+ distros.add(potential_target.pillar)
else:
distros.add(None)
if len(distros) > 1:
@@ -1159,7 +1150,7 @@
target_before_change = self.target
if (self.milestone is not None and
- self.milestone.target != target):
+ self.milestone.target != target.pillar):
# If the milestone for this bugtask is set, we
# have to make sure that it's a milestone of the
# current target, or reset it to None
=== modified file 'lib/lp/bugs/model/tests/test_bugtask.py'
--- lib/lp/bugs/model/tests/test_bugtask.py 2011-09-12 20:27:32 +0000
+++ lib/lp/bugs/model/tests/test_bugtask.py 2011-09-28 03:43:50 +0000
@@ -1913,6 +1913,18 @@
task.transitionToTarget, self.factory.makeSourcePackage())
self.assertEqual(milestone, task.milestone)
+ def test_milestone_preserved_within_a_pillar(self):
+ # Milestones are pillar-global, so transitions between packages
+ # don't unset them.
+ sp = self.factory.makeSourcePackage(publish=True)
+ dsp = sp.distribution_sourcepackage
+ task = self.factory.makeBugTask(target=dsp.distribution)
+ with person_logged_in(task.owner):
+ task.milestone = milestone = self.factory.makeMilestone(
+ distribution=dsp.distribution)
+ task.transitionToTarget(dsp)
+ self.assertEqual(milestone, task.milestone)
+
def test_targetnamecache_updated(self):
new_product = self.factory.makeProduct()
task = self.factory.makeBugTask()
=== modified file 'lib/lp/bugs/tests/test_bugtarget2.py'
--- lib/lp/bugs/tests/test_bugtarget2.py 2011-07-29 06:53:06 +0000
+++ lib/lp/bugs/tests/test_bugtarget2.py 2011-09-28 03:43:50 +0000
@@ -41,6 +41,9 @@
super(TestDistribution, self).setUp()
self.bugtarget = self.factory.makeDistribution()
+ def test_pillar(self):
+ self.assertEqual(self.bugtarget, self.bugtarget.pillar)
+
class TestDistroSeries(BugTargetBugFilingDuplicateSearchAlwaysOn,
TestCaseWithFactory):
@@ -57,6 +60,9 @@
self.assertEqual(
self.bugtarget.distribution, self.bugtarget.bugtarget_parent)
+ def test_pillar(self):
+ self.assertEqual(self.bugtarget.distribution, self.bugtarget.pillar)
+
class TestProjectGroup(BugTargetBugFilingDuplicateSearchAlwaysOn,
TestCaseWithFactory):
@@ -96,6 +102,9 @@
self.bugtarget = self.factory.makeProduct(
bug_supervisor=self.bug_supervisor)
+ def test_pillar(self):
+ self.assertEqual(self.bugtarget, self.bugtarget.pillar)
+
class TestDistributionSourcePackage(BugTargetBugFilingDuplicateSearchSettable,
TestCaseWithFactory):
@@ -111,6 +120,9 @@
self.bugtarget = self.factory.makeDistributionSourcePackage(
distribution=distribution)
+ def test_pillar(self):
+ self.assertEqual(self.bugtarget.distribution, self.bugtarget.pillar)
+
class BugTargetBugFilingDuplicateSearchInherited:
"""A base class for tests of bug targets where the dupe search policy
@@ -148,6 +160,9 @@
self.assertEqual(
self.bugtarget.product, self.bugtarget.bugtarget_parent)
+ def test_pillar(self):
+ self.assertEqual(self.bugtarget.product, self.bugtarget.pillar)
+
class TestSourcePackage(BugTargetBugFilingDuplicateSearchInherited,
TestCaseWithFactory):
@@ -170,3 +185,7 @@
self.assertEqual(
self.bugtarget.distribution_sourcepackage,
self.bugtarget.bugtarget_parent)
+
+ def test_pillar(self):
+ self.assertEqual(
+ self.bugtarget.distroseries.distribution, self.bugtarget.pillar)
=== modified file 'lib/lp/registry/configure.zcml'
--- lib/lp/registry/configure.zcml 2011-09-20 16:59:39 +0000
+++ lib/lp/registry/configure.zcml 2011-09-28 03:43:50 +0000
@@ -459,6 +459,7 @@
<class
class="lp.registry.model.distributionsourcepackage.DistributionSourcePackage">
<allow interface="lp.bugs.interfaces.bugsummary.IBugSummaryDimension"/>
+ <allow interface="lp.bugs.interfaces.bugtarget.IBugTarget"/>
<allow
interface="lp.bugs.interfaces.bugtarget.IHasBugHeat"/>
<allow
@@ -470,15 +471,8 @@
__getitem__
__ne__
_getOfficialTagClause
- all_bugtasks
bug_count
- bug_reported_acknowledgement
- bug_reporting_guidelines
- bugtargetdisplayname
- bugtargetname
bugtasks
- closed_bugtasks
- critical_bugtasks
current_publishing_records
currentrelease
delete
@@ -486,7 +480,6 @@
displayname
distribution
distro
- enable_bugfiling_duplicate_search
findRelatedArchivePublications
findRelatedArchives
getMergeProposals
@@ -495,27 +488,17 @@
getUsedBugTagsWithOpenCounts
getVersion
get_distroseries_packages
- has_bugtasks
- high_bugtasks
- inprogress_bugtasks
latest_overall_publication
name
- new_bugtasks
official_bug_tags
- open_bugtasks
publishing_history
releases
- searchTasks
sourcepackagename
subscribers
summary
title
total_bug_heat
- unassigned_bugtasks
upstream_product"/>
- <require
- permission="launchpad.AnyPerson"
- attributes="createBug"/>
<!-- IStructuralSubscriptionTarget -->
=== modified file 'lib/lp/registry/model/distribution.py'
--- lib/lp/registry/model/distribution.py 2011-08-29 00:13:22 +0000
+++ lib/lp/registry/model/distribution.py 2011-09-28 03:43:50 +0000
@@ -279,6 +279,11 @@
alsoProvides(self, IDerivativeDistribution)
@property
+ def pillar(self):
+ """See `IBugTarget`."""
+ return self
+
+ @property
def pillar_category(self):
"""See `IPillar`."""
return "Distribution"
=== modified file 'lib/lp/registry/model/distributionsourcepackage.py'
--- lib/lp/registry/model/distributionsourcepackage.py 2011-09-20 16:59:39 +0000
+++ lib/lp/registry/model/distributionsourcepackage.py 2011-09-28 03:43:50 +0000
@@ -472,6 +472,11 @@
"""See `IDistributionSourcePackage`."""
return not self.__eq__(other)
+ @property
+ def pillar(self):
+ """See `IBugTarget`."""
+ return self.distribution
+
def getBugSummaryContextWhereClause(self):
"""See `BugTargetBase`."""
# Circular fail.
=== modified file 'lib/lp/registry/model/distroseries.py'
--- lib/lp/registry/model/distroseries.py 2011-09-10 00:16:56 +0000
+++ lib/lp/registry/model/distroseries.py 2011-09-28 03:43:50 +0000
@@ -265,6 +265,11 @@
intermediateTable='SectionSelection')
@property
+ def pillar(self):
+ """See `IBugTarget`."""
+ return self.distribution
+
+ @property
def named_version(self):
return '%s (%s)' % (self.displayname, self.version)
=== modified file 'lib/lp/registry/model/product.py'
--- lib/lp/registry/model/product.py 2011-09-13 05:23:16 +0000
+++ lib/lp/registry/model/product.py 2011-09-28 03:43:50 +0000
@@ -386,6 +386,11 @@
date_next_suggest_packaging = UtcDateTimeCol(default=None)
@property
+ def pillar(self):
+ """See `IBugTarget`."""
+ return self
+
+ @property
def pillar_category(self):
"""See `IPillar`."""
return "Project"
=== modified file 'lib/lp/registry/model/productseries.py'
--- lib/lp/registry/model/productseries.py 2011-07-29 06:53:06 +0000
+++ lib/lp/registry/model/productseries.py 2011-09-28 03:43:50 +0000
@@ -170,6 +170,11 @@
orderBy=['-id'])
@property
+ def pillar(self):
+ """See `IBugTarget`."""
+ return self.product
+
+ @property
def answers_usage(self):
"""See `IServiceUsage.`"""
return self.product.answers_usage
=== modified file 'lib/lp/registry/model/sourcepackage.py'
--- lib/lp/registry/model/sourcepackage.py 2011-09-19 22:43:14 +0000
+++ lib/lp/registry/model/sourcepackage.py 2011-09-28 03:43:50 +0000
@@ -542,6 +542,11 @@
"future. For now, you probably meant to file the bug on the "
"distro-wide (i.e. not series-specific) source package.")
+ @property
+ def pillar(self):
+ """See `IBugTarget`."""
+ return self.distroseries.distribution
+
def getBugSummaryContextWhereClause(self):
"""See BugTargetBase."""
# Circular fail.