← Back to team overview

launchpad-reviewers team mailing list archive

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

 

Thiago F. Pappacena has proposed merging ~pappacena/launchpad:stormify-bugnomination into launchpad:master.

Commit message:
Stormifying bug nomination

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~pappacena/launchpad/+git/launchpad/+merge/395021
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~pappacena/launchpad:stormify-bugnomination into launchpad:master.
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):
         """Traverse to a nomination by id."""
         if nomination_id.isdigit():
             try:
-                return getUtility(IBugNominationSet).get(nomination_id)
+                return getUtility(IBugNominationSet).get(int(nomination_id))
             except NotFoundError:
                 return None
 
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):
         """Traverse to a nomination by id."""
         if not nomination_id.isdigit():
             return None
-        return getUtility(IBugNominationSet).get(nomination_id)
+        return getUtility(IBugNominationSet).get(int(nomination_id))
 
     @redirection('references')
     def redirect_references(self):
@@ -1973,7 +1973,7 @@ class BugTasksTableView(LaunchpadView):
         nominations = list(bug.getNominations())
         # Eager load validity for all the persons we know of that will be
         # displayed.
-        ids = set(map(attrgetter('ownerID'), nominations))
+        ids = set(map(attrgetter('owner_id'), nominations))
         ids.discard(None)
         if ids:
             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 @@
                     productseries
                     bug
                     owner
-                    ownerID
+                    owner_id
                     decider
                     target
                     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 @@
-# Copyright 2009-2011 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2020 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Interfaces related to bug nomination."""
@@ -127,7 +127,7 @@ class IBugNomination(IHasBug, IHasOwner):
     owner = exported(PublicPersonChoice(
         title=_('Submitter'), required=True, readonly=True,
         vocabulary='ValidPersonOrTeam'))
-    ownerID = Attribute('The db id of the owner.')
+    owner_id = Attribute('The db id of the owner.')
     decider = exported(PublicPersonChoice(
         title=_('Decided By'), required=False, readonly=True,
         vocabulary='ValidPersonOrTeam'))
@@ -193,6 +193,15 @@ class IBugNominationSet(Interface):
         nomination was not found.
         """
 
+    def getByBugTarget(bug, target):
+        """Get a nomination by the bug and target.
+
+        Returns an IBugNomination, or None if none is found.
+        """
+
+    def findByBug(bug):
+        """Returns the list of IBugNomination for the given bug."""
+
 
 class IBugNominationForm(Interface):
     """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 (
 from lp.bugs.interfaces.bugmessage import IBugMessageSet
 from lp.bugs.interfaces.bugnomination import (
     BugNominationStatus,
+    IBugNominationSet,
     NominationError,
     NominationSeriesObsoleteError,
     )
@@ -1676,16 +1677,7 @@ class Bug(SQLBase, InformationTypeMixin):
 
     def getNominationFor(self, target):
         """See `IBug`."""
-        if IDistroSeries.providedBy(target):
-            filter_args = dict(distroseriesID=target.id)
-        elif IProductSeries.providedBy(target):
-            filter_args = dict(productseriesID=target.id)
-        elif ISourcePackage.providedBy(target):
-            filter_args = dict(distroseriesID=target.series.id)
-        else:
-            return None
-
-        nomination = BugNomination.selectOneBy(bugID=self.id, **filter_args)
+        nomination = getUtility(IBugNominationSet).getByBugTarget(self, target)
 
         if nomination is None:
             raise NotFoundError(
@@ -1702,7 +1694,7 @@ class Bug(SQLBase, InformationTypeMixin):
             return nomination.target.bugtargetdisplayname.lower()
 
         if nominations is None:
-            nominations = BugNomination.selectBy(bugID=self.id)
+            nominations = getUtility(IBugNominationSet).findByBug(self)
         if IProduct.providedBy(target):
             filtered_nominations = []
             for nomination in shortlist(nominations):
diff --git a/lib/lp/bugs/model/bugnomination.py b/lib/lp/bugs/model/bugnomination.py
index 4c322cd..3cd7868 100644
--- a/lib/lp/bugs/model/bugnomination.py
+++ b/lib/lp/bugs/model/bugnomination.py
@@ -1,4 +1,4 @@
-# Copyright 2009-2016 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2020 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Database classes related to bug nomination.
@@ -16,10 +16,11 @@ __all__ = [
 from datetime import datetime
 
 import pytz
-from sqlobject import (
-    ForeignKey,
-    SQLObjectNotFound,
+from storm.properties import (
+    DateTime,
+    Int,
     )
+from storm.references import Reference
 from zope.component import getUtility
 from zope.interface import implementer
 
@@ -32,37 +33,62 @@ from lp.bugs.interfaces.bugnomination import (
     IBugNominationSet,
     )
 from lp.bugs.interfaces.bugtask import IBugTaskSet
+from lp.registry.interfaces.distroseries import IDistroSeries
 from lp.registry.interfaces.person import validate_public_person
+from lp.registry.interfaces.productseries import IProductSeries
+from lp.registry.interfaces.sourcepackage import ISourcePackage
 from lp.services.database.constants import UTC_NOW
-from lp.services.database.datetimecol import UtcDateTimeCol
-from lp.services.database.enumcol import EnumCol
-from lp.services.database.sqlbase import SQLBase
+from lp.services.database.enumcol import DBEnum
+from lp.services.database.interfaces import IStore
+from lp.services.database.stormbase import StormBase
 from lp.services.features import getFeatureFlag
 
 
 @implementer(IBugNomination)
-class BugNomination(SQLBase):
-    _table = "BugNomination"
-
-    owner = ForeignKey(
-        dbName='owner', foreignKey='Person',
-        storm_validator=validate_public_person, notNull=True)
-    decider = ForeignKey(
-        dbName='decider', foreignKey='Person',
-        storm_validator=validate_public_person, notNull=False, default=None)
-    date_created = UtcDateTimeCol(notNull=True, default=UTC_NOW)
-    date_decided = UtcDateTimeCol(notNull=False, default=None)
-    distroseries = ForeignKey(
-        dbName='distroseries', foreignKey='DistroSeries',
-        notNull=False, default=None)
-    productseries = ForeignKey(
-        dbName='productseries', foreignKey='ProductSeries',
-        notNull=False, default=None)
-    bug = ForeignKey(dbName='bug', foreignKey='Bug', notNull=True)
-    status = EnumCol(
-        dbName='status', notNull=True, schema=BugNominationStatus,
+class BugNomination(StormBase):
+
+    __storm_table__ = "BugNomination"
+
+    id = Int(primary=True)
+
+    owner_id = Int(
+        name="owner", allow_none=False, validator=validate_public_person)
+    owner = Reference(owner_id, "Person.id")
+
+    decider_id = Int(
+        name="decider", allow_none=True, default=None,
+        validator=validate_public_person)
+    decider = Reference(decider_id, "Person.id")
+
+    date_created = DateTime(allow_none=False, default=UTC_NOW, tzinfo=pytz.UTC)
+    date_decided = DateTime(allow_none=True, default=None, tzinfo=pytz.UTC)
+
+    distroseries_id = Int(name="distroseries", allow_none=True, default=None)
+    distroseries = Reference(distroseries_id, "DistroSeries.id")
+
+    productseries_id = Int(name="productseries", allow_none=True, default=None)
+    productseries = Reference(productseries_id, "ProductSeries.id")
+
+    bug_id = Int(name='bug', allow_none=False)
+    bug = Reference(bug_id, 'Bug.id')
+
+    status = DBEnum(
+        name='status', allow_none=False, enum=BugNominationStatus,
         default=BugNominationStatus.PROPOSED)
 
+    def __init__(self, owner=None, decider=None, date_created=UTC_NOW,
+                 date_decided=None, distroseries=None,
+                 productseries=None, bug=None,
+                 status=BugNominationStatus.PROPOSED):
+        self.owner = owner
+        self.decider = decider
+        self.date_created = date_created
+        self.date_decided = date_decided
+        self.distroseries = distroseries
+        self.productseries = productseries
+        self.bug = bug
+        self.status = status
+
     @property
     def target(self):
         """See IBugNomination."""
@@ -156,6 +182,10 @@ class BugNomination(SQLBase):
                     return True
         return False
 
+    def __repr__(self):
+        return "<BugNomination at 0x%x bug=%s owner=%s>" % (
+            id(self), self.bug_id, self.owner_id)
+
 
 @implementer(IBugNominationSet)
 class BugNominationSet:
@@ -163,7 +193,25 @@ class BugNominationSet:
 
     def get(self, id):
         """See IBugNominationSet."""
-        try:
-            return BugNomination.get(id)
-        except SQLObjectNotFound:
+        store = IStore(BugNomination)
+        nomination = store.get(BugNomination, id)
+        if nomination is None:
             raise NotFoundError(id)
+        return nomination
+
+    def getByBugTarget(self, bug, target):
+        if IDistroSeries.providedBy(target):
+            filter_args = dict(distroseries_id=target.id)
+        elif IProductSeries.providedBy(target):
+            filter_args = dict(productseries_id=target.id)
+        elif ISourcePackage.providedBy(target):
+            filter_args = dict(distroseries_id=target.series.id)
+        else:
+            return None
+        store = IStore(BugNomination)
+        return store.find(BugNomination, bug=bug, **filter_args).one()
+
+    def findByBug(self, bug):
+        """See IBugNominationSet."""
+        store = IStore(BugNomination)
+        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):
             raise AssertionError(
                 'Unknown nomination target: %r.' % params.nominated_for)
         extra_clauses.append(And(
-            BugNomination.bugID == BugTaskFlat.bug_id,
+            BugNomination.bug_id == BugTaskFlat.bug_id,
             BugNomination.status == BugNominationStatus.PROPOSED,
             target_col == params.nominated_for))
         clauseTables.append(BugNomination)

Follow ups