Merge ~pappacena/launchpad:stormify-bugnomination into launchpad:master

Proposed by Thiago F. Pappacena
Status: Merged
Approved by: Thiago F. Pappacena
Approved revision: d1b4373243ed4d97cccd2e0e78b4f5fd09599821
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~pappacena/launchpad:stormify-bugnomination
Merge into: launchpad:master
Diff against target: 287 lines (+98/-48)
7 files modified
lib/lp/bugs/browser/bug.py (+1/-1)
lib/lp/bugs/browser/bugtask.py (+2/-2)
lib/lp/bugs/configure.zcml (+1/-1)
lib/lp/bugs/interfaces/bugnomination.py (+11/-2)
lib/lp/bugs/model/bug.py (+3/-11)
lib/lp/bugs/model/bugnomination.py (+79/-30)
lib/lp/bugs/model/bugtasksearch.py (+1/-1)
Reviewer Review Type Date Requested Status
Colin Watson (community) Approve
Review via email: mp+395021@code.launchpad.net

Commit message

Stormifying bug nomination

To post a comment you must log in.
Revision history for this message
Colin Watson (cjwatson) :
review: Approve
Revision history for this message
Thiago F. Pappacena (pappacena) wrote :

Pushed the requested changes.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/lib/lp/bugs/browser/bug.py b/lib/lp/bugs/browser/bug.py
index 61360c9..eedf9b4 100644
--- a/lib/lp/bugs/browser/bug.py
+++ b/lib/lp/bugs/browser/bug.py
@@ -193,7 +193,7 @@ class BugNavigation(Navigation):
193 """Traverse to a nomination by id."""193 """Traverse to a nomination by id."""
194 if nomination_id.isdigit():194 if nomination_id.isdigit():
195 try:195 try:
196 return getUtility(IBugNominationSet).get(nomination_id)196 return getUtility(IBugNominationSet).get(int(nomination_id))
197 except NotFoundError:197 except NotFoundError:
198 return None198 return None
199199
diff --git a/lib/lp/bugs/browser/bugtask.py b/lib/lp/bugs/browser/bugtask.py
index c6bc9d7..5aac3af 100644
--- a/lib/lp/bugs/browser/bugtask.py
+++ b/lib/lp/bugs/browser/bugtask.py
@@ -408,7 +408,7 @@ class BugTaskNavigation(Navigation):
408 """Traverse to a nomination by id."""408 """Traverse to a nomination by id."""
409 if not nomination_id.isdigit():409 if not nomination_id.isdigit():
410 return None410 return None
411 return getUtility(IBugNominationSet).get(nomination_id)411 return getUtility(IBugNominationSet).get(int(nomination_id))
412412
413 @redirection('references')413 @redirection('references')
414 def redirect_references(self):414 def redirect_references(self):
@@ -1973,7 +1973,7 @@ class BugTasksTableView(LaunchpadView):
1973 nominations = list(bug.getNominations())1973 nominations = list(bug.getNominations())
1974 # Eager load validity for all the persons we know of that will be1974 # Eager load validity for all the persons we know of that will be
1975 # displayed.1975 # displayed.
1976 ids = set(map(attrgetter('ownerID'), nominations))1976 ids = set(map(attrgetter('owner_id'), nominations))
1977 ids.discard(None)1977 ids.discard(None)
1978 if ids:1978 if ids:
1979 list(getUtility(IPersonSet).getPrecachedPersonsFromIDs(1979 list(getUtility(IPersonSet).getPrecachedPersonsFromIDs(
diff --git a/lib/lp/bugs/configure.zcml b/lib/lp/bugs/configure.zcml
index 3e4544b..3585d8d 100644
--- a/lib/lp/bugs/configure.zcml
+++ b/lib/lp/bugs/configure.zcml
@@ -802,7 +802,7 @@
802 productseries802 productseries
803 bug803 bug
804 owner804 owner
805 ownerID805 owner_id
806 decider806 decider
807 target807 target
808 status808 status
diff --git a/lib/lp/bugs/interfaces/bugnomination.py b/lib/lp/bugs/interfaces/bugnomination.py
index c8ab348..242225d 100644
--- a/lib/lp/bugs/interfaces/bugnomination.py
+++ b/lib/lp/bugs/interfaces/bugnomination.py
@@ -1,4 +1,4 @@
1# Copyright 2009-2011 Canonical Ltd. This software is licensed under the1# Copyright 2009-2020 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4"""Interfaces related to bug nomination."""4"""Interfaces related to bug nomination."""
@@ -127,7 +127,7 @@ class IBugNomination(IHasBug, IHasOwner):
127 owner = exported(PublicPersonChoice(127 owner = exported(PublicPersonChoice(
128 title=_('Submitter'), required=True, readonly=True,128 title=_('Submitter'), required=True, readonly=True,
129 vocabulary='ValidPersonOrTeam'))129 vocabulary='ValidPersonOrTeam'))
130 ownerID = Attribute('The db id of the owner.')130 owner_id = Attribute('The db id of the owner.')
131 decider = exported(PublicPersonChoice(131 decider = exported(PublicPersonChoice(
132 title=_('Decided By'), required=False, readonly=True,132 title=_('Decided By'), required=False, readonly=True,
133 vocabulary='ValidPersonOrTeam'))133 vocabulary='ValidPersonOrTeam'))
@@ -193,6 +193,15 @@ class IBugNominationSet(Interface):
193 nomination was not found.193 nomination was not found.
194 """194 """
195195
196 def getByBugTarget(bug, target):
197 """Get a nomination by the bug and target.
198
199 Returns an IBugNomination, or None if none is found.
200 """
201
202 def findByBug(bug):
203 """Returns the list of IBugNomination for the given bug."""
204
196205
197class IBugNominationForm(Interface):206class IBugNominationForm(Interface):
198 """The browser form for nominating bugs for series."""207 """The browser form for nominating bugs for series."""
diff --git a/lib/lp/bugs/model/bug.py b/lib/lp/bugs/model/bug.py
index 0ca6164..a9b177c 100644
--- a/lib/lp/bugs/model/bug.py
+++ b/lib/lp/bugs/model/bug.py
@@ -127,6 +127,7 @@ from lp.bugs.interfaces.bugattachment import (
127from lp.bugs.interfaces.bugmessage import IBugMessageSet127from lp.bugs.interfaces.bugmessage import IBugMessageSet
128from lp.bugs.interfaces.bugnomination import (128from lp.bugs.interfaces.bugnomination import (
129 BugNominationStatus,129 BugNominationStatus,
130 IBugNominationSet,
130 NominationError,131 NominationError,
131 NominationSeriesObsoleteError,132 NominationSeriesObsoleteError,
132 )133 )
@@ -1676,16 +1677,7 @@ class Bug(SQLBase, InformationTypeMixin):
16761677
1677 def getNominationFor(self, target):1678 def getNominationFor(self, target):
1678 """See `IBug`."""1679 """See `IBug`."""
1679 if IDistroSeries.providedBy(target):1680 nomination = getUtility(IBugNominationSet).getByBugTarget(self, target)
1680 filter_args = dict(distroseriesID=target.id)
1681 elif IProductSeries.providedBy(target):
1682 filter_args = dict(productseriesID=target.id)
1683 elif ISourcePackage.providedBy(target):
1684 filter_args = dict(distroseriesID=target.series.id)
1685 else:
1686 return None
1687
1688 nomination = BugNomination.selectOneBy(bugID=self.id, **filter_args)
16891681
1690 if nomination is None:1682 if nomination is None:
1691 raise NotFoundError(1683 raise NotFoundError(
@@ -1702,7 +1694,7 @@ class Bug(SQLBase, InformationTypeMixin):
1702 return nomination.target.bugtargetdisplayname.lower()1694 return nomination.target.bugtargetdisplayname.lower()
17031695
1704 if nominations is None:1696 if nominations is None:
1705 nominations = BugNomination.selectBy(bugID=self.id)1697 nominations = getUtility(IBugNominationSet).findByBug(self)
1706 if IProduct.providedBy(target):1698 if IProduct.providedBy(target):
1707 filtered_nominations = []1699 filtered_nominations = []
1708 for nomination in shortlist(nominations):1700 for nomination in shortlist(nominations):
diff --git a/lib/lp/bugs/model/bugnomination.py b/lib/lp/bugs/model/bugnomination.py
index 4c322cd..d44877a 100644
--- a/lib/lp/bugs/model/bugnomination.py
+++ b/lib/lp/bugs/model/bugnomination.py
@@ -1,4 +1,4 @@
1# Copyright 2009-2016 Canonical Ltd. This software is licensed under the1# Copyright 2009-2020 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4"""Database classes related to bug nomination.4"""Database classes related to bug nomination.
@@ -16,10 +16,11 @@ __all__ = [
16from datetime import datetime16from datetime import datetime
1717
18import pytz18import pytz
19from sqlobject import (19from storm.properties import (
20 ForeignKey,20 DateTime,
21 SQLObjectNotFound,21 Int,
22 )22 )
23from storm.references import Reference
23from zope.component import getUtility24from zope.component import getUtility
24from zope.interface import implementer25from zope.interface import implementer
2526
@@ -32,37 +33,61 @@ from lp.bugs.interfaces.bugnomination import (
32 IBugNominationSet,33 IBugNominationSet,
33 )34 )
34from lp.bugs.interfaces.bugtask import IBugTaskSet35from lp.bugs.interfaces.bugtask import IBugTaskSet
36from lp.registry.interfaces.distroseries import IDistroSeries
35from lp.registry.interfaces.person import validate_public_person37from lp.registry.interfaces.person import validate_public_person
38from lp.registry.interfaces.productseries import IProductSeries
39from lp.registry.interfaces.sourcepackage import ISourcePackage
36from lp.services.database.constants import UTC_NOW40from lp.services.database.constants import UTC_NOW
37from lp.services.database.datetimecol import UtcDateTimeCol41from lp.services.database.enumcol import DBEnum
38from lp.services.database.enumcol import EnumCol42from lp.services.database.interfaces import IStore
39from lp.services.database.sqlbase import SQLBase43from lp.services.database.stormbase import StormBase
40from lp.services.features import getFeatureFlag44from lp.services.features import getFeatureFlag
4145
4246
43@implementer(IBugNomination)47@implementer(IBugNomination)
44class BugNomination(SQLBase):48class BugNomination(StormBase):
45 _table = "BugNomination"49
4650 __storm_table__ = "BugNomination"
47 owner = ForeignKey(51
48 dbName='owner', foreignKey='Person',52 id = Int(primary=True)
49 storm_validator=validate_public_person, notNull=True)53
50 decider = ForeignKey(54 owner_id = Int(
51 dbName='decider', foreignKey='Person',55 name="owner", allow_none=False, validator=validate_public_person)
52 storm_validator=validate_public_person, notNull=False, default=None)56 owner = Reference(owner_id, "Person.id")
53 date_created = UtcDateTimeCol(notNull=True, default=UTC_NOW)57
54 date_decided = UtcDateTimeCol(notNull=False, default=None)58 decider_id = Int(
55 distroseries = ForeignKey(59 name="decider", allow_none=True, default=None,
56 dbName='distroseries', foreignKey='DistroSeries',60 validator=validate_public_person)
57 notNull=False, default=None)61 decider = Reference(decider_id, "Person.id")
58 productseries = ForeignKey(62
59 dbName='productseries', foreignKey='ProductSeries',63 date_created = DateTime(allow_none=False, default=UTC_NOW, tzinfo=pytz.UTC)
60 notNull=False, default=None)64 date_decided = DateTime(allow_none=True, default=None, tzinfo=pytz.UTC)
61 bug = ForeignKey(dbName='bug', foreignKey='Bug', notNull=True)65
62 status = EnumCol(66 distroseries_id = Int(name="distroseries", allow_none=True, default=None)
63 dbName='status', notNull=True, schema=BugNominationStatus,67 distroseries = Reference(distroseries_id, "DistroSeries.id")
68
69 productseries_id = Int(name="productseries", allow_none=True, default=None)
70 productseries = Reference(productseries_id, "ProductSeries.id")
71
72 bug_id = Int(name='bug', allow_none=False)
73 bug = Reference(bug_id, 'Bug.id')
74
75 status = DBEnum(
76 name='status', allow_none=False, enum=BugNominationStatus,
64 default=BugNominationStatus.PROPOSED)77 default=BugNominationStatus.PROPOSED)
6578
79 def __init__(self, bug, owner, decider=None, date_created=UTC_NOW,
80 date_decided=None, distroseries=None,
81 productseries=None, status=BugNominationStatus.PROPOSED):
82 self.owner = owner
83 self.decider = decider
84 self.date_created = date_created
85 self.date_decided = date_decided
86 self.distroseries = distroseries
87 self.productseries = productseries
88 self.bug = bug
89 self.status = status
90
66 @property91 @property
67 def target(self):92 def target(self):
68 """See IBugNomination."""93 """See IBugNomination."""
@@ -156,6 +181,12 @@ class BugNomination(SQLBase):
156 return True181 return True
157 return False182 return False
158183
184 def destroySelf(self):
185 IStore(self).remove(self)
186
187 def __repr__(self):
188 return "<BugNomination bug=%s owner=%s>" % (self.bug_id, self.owner_id)
189
159190
160@implementer(IBugNominationSet)191@implementer(IBugNominationSet)
161class BugNominationSet:192class BugNominationSet:
@@ -163,7 +194,25 @@ class BugNominationSet:
163194
164 def get(self, id):195 def get(self, id):
165 """See IBugNominationSet."""196 """See IBugNominationSet."""
166 try:197 store = IStore(BugNomination)
167 return BugNomination.get(id)198 nomination = store.get(BugNomination, id)
168 except SQLObjectNotFound:199 if nomination is None:
169 raise NotFoundError(id)200 raise NotFoundError(id)
201 return nomination
202
203 def getByBugTarget(self, bug, target):
204 if IDistroSeries.providedBy(target):
205 filter_args = dict(distroseries_id=target.id)
206 elif IProductSeries.providedBy(target):
207 filter_args = dict(productseries_id=target.id)
208 elif ISourcePackage.providedBy(target):
209 filter_args = dict(distroseries_id=target.series.id)
210 else:
211 return None
212 store = IStore(BugNomination)
213 return store.find(BugNomination, bug=bug, **filter_args).one()
214
215 def findByBug(self, bug):
216 """See IBugNominationSet."""
217 store = IStore(BugNomination)
218 return store.find(BugNomination, bug=bug)
diff --git a/lib/lp/bugs/model/bugtasksearch.py b/lib/lp/bugs/model/bugtasksearch.py
index 21f7313..184fed4 100644
--- a/lib/lp/bugs/model/bugtasksearch.py
+++ b/lib/lp/bugs/model/bugtasksearch.py
@@ -674,7 +674,7 @@ def _build_query(params):
674 raise AssertionError(674 raise AssertionError(
675 'Unknown nomination target: %r.' % params.nominated_for)675 'Unknown nomination target: %r.' % params.nominated_for)
676 extra_clauses.append(And(676 extra_clauses.append(And(
677 BugNomination.bugID == BugTaskFlat.bug_id,677 BugNomination.bug_id == BugTaskFlat.bug_id,
678 BugNomination.status == BugNominationStatus.PROPOSED,678 BugNomination.status == BugNominationStatus.PROPOSED,
679 target_col == params.nominated_for))679 target_col == params.nominated_for))
680 clauseTables.append(BugNomination)680 clauseTables.append(BugNomination)