Merge ~pappacena/launchpad:stormify-bugnomination into launchpad:master
- Git
- lp:~pappacena/launchpad
- stormify-bugnomination
- Merge into 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) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Colin Watson (community) | Approve | ||
Review via email: mp+395021@code.launchpad.net |
Commit message
Stormifying bug nomination
Description of the change
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 : | # |
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/lib/lp/bugs/browser/bug.py b/lib/lp/bugs/browser/bug.py | |||
2 | index 61360c9..eedf9b4 100644 | |||
3 | --- a/lib/lp/bugs/browser/bug.py | |||
4 | +++ b/lib/lp/bugs/browser/bug.py | |||
5 | @@ -193,7 +193,7 @@ class BugNavigation(Navigation): | |||
6 | 193 | """Traverse to a nomination by id.""" | 193 | """Traverse to a nomination by id.""" |
7 | 194 | if nomination_id.isdigit(): | 194 | if nomination_id.isdigit(): |
8 | 195 | try: | 195 | try: |
10 | 196 | return getUtility(IBugNominationSet).get(nomination_id) | 196 | return getUtility(IBugNominationSet).get(int(nomination_id)) |
11 | 197 | except NotFoundError: | 197 | except NotFoundError: |
12 | 198 | return None | 198 | return None |
13 | 199 | 199 | ||
14 | diff --git a/lib/lp/bugs/browser/bugtask.py b/lib/lp/bugs/browser/bugtask.py | |||
15 | index c6bc9d7..5aac3af 100644 | |||
16 | --- a/lib/lp/bugs/browser/bugtask.py | |||
17 | +++ b/lib/lp/bugs/browser/bugtask.py | |||
18 | @@ -408,7 +408,7 @@ class BugTaskNavigation(Navigation): | |||
19 | 408 | """Traverse to a nomination by id.""" | 408 | """Traverse to a nomination by id.""" |
20 | 409 | if not nomination_id.isdigit(): | 409 | if not nomination_id.isdigit(): |
21 | 410 | return None | 410 | return None |
23 | 411 | return getUtility(IBugNominationSet).get(nomination_id) | 411 | return getUtility(IBugNominationSet).get(int(nomination_id)) |
24 | 412 | 412 | ||
25 | 413 | @redirection('references') | 413 | @redirection('references') |
26 | 414 | def redirect_references(self): | 414 | def redirect_references(self): |
27 | @@ -1973,7 +1973,7 @@ class BugTasksTableView(LaunchpadView): | |||
28 | 1973 | nominations = list(bug.getNominations()) | 1973 | nominations = list(bug.getNominations()) |
29 | 1974 | # Eager load validity for all the persons we know of that will be | 1974 | # Eager load validity for all the persons we know of that will be |
30 | 1975 | # displayed. | 1975 | # displayed. |
32 | 1976 | ids = set(map(attrgetter('ownerID'), nominations)) | 1976 | ids = set(map(attrgetter('owner_id'), nominations)) |
33 | 1977 | ids.discard(None) | 1977 | ids.discard(None) |
34 | 1978 | if ids: | 1978 | if ids: |
35 | 1979 | list(getUtility(IPersonSet).getPrecachedPersonsFromIDs( | 1979 | list(getUtility(IPersonSet).getPrecachedPersonsFromIDs( |
36 | diff --git a/lib/lp/bugs/configure.zcml b/lib/lp/bugs/configure.zcml | |||
37 | index 3e4544b..3585d8d 100644 | |||
38 | --- a/lib/lp/bugs/configure.zcml | |||
39 | +++ b/lib/lp/bugs/configure.zcml | |||
40 | @@ -802,7 +802,7 @@ | |||
41 | 802 | productseries | 802 | productseries |
42 | 803 | bug | 803 | bug |
43 | 804 | owner | 804 | owner |
45 | 805 | ownerID | 805 | owner_id |
46 | 806 | decider | 806 | decider |
47 | 807 | target | 807 | target |
48 | 808 | status | 808 | status |
49 | diff --git a/lib/lp/bugs/interfaces/bugnomination.py b/lib/lp/bugs/interfaces/bugnomination.py | |||
50 | index c8ab348..242225d 100644 | |||
51 | --- a/lib/lp/bugs/interfaces/bugnomination.py | |||
52 | +++ b/lib/lp/bugs/interfaces/bugnomination.py | |||
53 | @@ -1,4 +1,4 @@ | |||
55 | 1 | # Copyright 2009-2011 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2009-2020 Canonical Ltd. This software is licensed under the |
56 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
57 | 3 | 3 | ||
58 | 4 | """Interfaces related to bug nomination.""" | 4 | """Interfaces related to bug nomination.""" |
59 | @@ -127,7 +127,7 @@ class IBugNomination(IHasBug, IHasOwner): | |||
60 | 127 | owner = exported(PublicPersonChoice( | 127 | owner = exported(PublicPersonChoice( |
61 | 128 | title=_('Submitter'), required=True, readonly=True, | 128 | title=_('Submitter'), required=True, readonly=True, |
62 | 129 | vocabulary='ValidPersonOrTeam')) | 129 | vocabulary='ValidPersonOrTeam')) |
64 | 130 | ownerID = Attribute('The db id of the owner.') | 130 | owner_id = Attribute('The db id of the owner.') |
65 | 131 | decider = exported(PublicPersonChoice( | 131 | decider = exported(PublicPersonChoice( |
66 | 132 | title=_('Decided By'), required=False, readonly=True, | 132 | title=_('Decided By'), required=False, readonly=True, |
67 | 133 | vocabulary='ValidPersonOrTeam')) | 133 | vocabulary='ValidPersonOrTeam')) |
68 | @@ -193,6 +193,15 @@ class IBugNominationSet(Interface): | |||
69 | 193 | nomination was not found. | 193 | nomination was not found. |
70 | 194 | """ | 194 | """ |
71 | 195 | 195 | ||
72 | 196 | def getByBugTarget(bug, target): | ||
73 | 197 | """Get a nomination by the bug and target. | ||
74 | 198 | |||
75 | 199 | Returns an IBugNomination, or None if none is found. | ||
76 | 200 | """ | ||
77 | 201 | |||
78 | 202 | def findByBug(bug): | ||
79 | 203 | """Returns the list of IBugNomination for the given bug.""" | ||
80 | 204 | |||
81 | 196 | 205 | ||
82 | 197 | class IBugNominationForm(Interface): | 206 | class IBugNominationForm(Interface): |
83 | 198 | """The browser form for nominating bugs for series.""" | 207 | """The browser form for nominating bugs for series.""" |
84 | diff --git a/lib/lp/bugs/model/bug.py b/lib/lp/bugs/model/bug.py | |||
85 | index 0ca6164..a9b177c 100644 | |||
86 | --- a/lib/lp/bugs/model/bug.py | |||
87 | +++ b/lib/lp/bugs/model/bug.py | |||
88 | @@ -127,6 +127,7 @@ from lp.bugs.interfaces.bugattachment import ( | |||
89 | 127 | from lp.bugs.interfaces.bugmessage import IBugMessageSet | 127 | from lp.bugs.interfaces.bugmessage import IBugMessageSet |
90 | 128 | from lp.bugs.interfaces.bugnomination import ( | 128 | from lp.bugs.interfaces.bugnomination import ( |
91 | 129 | BugNominationStatus, | 129 | BugNominationStatus, |
92 | 130 | IBugNominationSet, | ||
93 | 130 | NominationError, | 131 | NominationError, |
94 | 131 | NominationSeriesObsoleteError, | 132 | NominationSeriesObsoleteError, |
95 | 132 | ) | 133 | ) |
96 | @@ -1676,16 +1677,7 @@ class Bug(SQLBase, InformationTypeMixin): | |||
97 | 1676 | 1677 | ||
98 | 1677 | def getNominationFor(self, target): | 1678 | def getNominationFor(self, target): |
99 | 1678 | """See `IBug`.""" | 1679 | """See `IBug`.""" |
110 | 1679 | if IDistroSeries.providedBy(target): | 1680 | nomination = getUtility(IBugNominationSet).getByBugTarget(self, target) |
101 | 1680 | filter_args = dict(distroseriesID=target.id) | ||
102 | 1681 | elif IProductSeries.providedBy(target): | ||
103 | 1682 | filter_args = dict(productseriesID=target.id) | ||
104 | 1683 | elif ISourcePackage.providedBy(target): | ||
105 | 1684 | filter_args = dict(distroseriesID=target.series.id) | ||
106 | 1685 | else: | ||
107 | 1686 | return None | ||
108 | 1687 | |||
109 | 1688 | nomination = BugNomination.selectOneBy(bugID=self.id, **filter_args) | ||
111 | 1689 | 1681 | ||
112 | 1690 | if nomination is None: | 1682 | if nomination is None: |
113 | 1691 | raise NotFoundError( | 1683 | raise NotFoundError( |
114 | @@ -1702,7 +1694,7 @@ class Bug(SQLBase, InformationTypeMixin): | |||
115 | 1702 | return nomination.target.bugtargetdisplayname.lower() | 1694 | return nomination.target.bugtargetdisplayname.lower() |
116 | 1703 | 1695 | ||
117 | 1704 | if nominations is None: | 1696 | if nominations is None: |
119 | 1705 | nominations = BugNomination.selectBy(bugID=self.id) | 1697 | nominations = getUtility(IBugNominationSet).findByBug(self) |
120 | 1706 | if IProduct.providedBy(target): | 1698 | if IProduct.providedBy(target): |
121 | 1707 | filtered_nominations = [] | 1699 | filtered_nominations = [] |
122 | 1708 | for nomination in shortlist(nominations): | 1700 | for nomination in shortlist(nominations): |
123 | diff --git a/lib/lp/bugs/model/bugnomination.py b/lib/lp/bugs/model/bugnomination.py | |||
124 | index 4c322cd..d44877a 100644 | |||
125 | --- a/lib/lp/bugs/model/bugnomination.py | |||
126 | +++ b/lib/lp/bugs/model/bugnomination.py | |||
127 | @@ -1,4 +1,4 @@ | |||
129 | 1 | # Copyright 2009-2016 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2009-2020 Canonical Ltd. This software is licensed under the |
130 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
131 | 3 | 3 | ||
132 | 4 | """Database classes related to bug nomination. | 4 | """Database classes related to bug nomination. |
133 | @@ -16,10 +16,11 @@ __all__ = [ | |||
134 | 16 | from datetime import datetime | 16 | from datetime import datetime |
135 | 17 | 17 | ||
136 | 18 | import pytz | 18 | import pytz |
140 | 19 | from sqlobject import ( | 19 | from storm.properties import ( |
141 | 20 | ForeignKey, | 20 | DateTime, |
142 | 21 | SQLObjectNotFound, | 21 | Int, |
143 | 22 | ) | 22 | ) |
144 | 23 | from storm.references import Reference | ||
145 | 23 | from zope.component import getUtility | 24 | from zope.component import getUtility |
146 | 24 | from zope.interface import implementer | 25 | from zope.interface import implementer |
147 | 25 | 26 | ||
148 | @@ -32,37 +33,61 @@ from lp.bugs.interfaces.bugnomination import ( | |||
149 | 32 | IBugNominationSet, | 33 | IBugNominationSet, |
150 | 33 | ) | 34 | ) |
151 | 34 | from lp.bugs.interfaces.bugtask import IBugTaskSet | 35 | from lp.bugs.interfaces.bugtask import IBugTaskSet |
152 | 36 | from lp.registry.interfaces.distroseries import IDistroSeries | ||
153 | 35 | from lp.registry.interfaces.person import validate_public_person | 37 | from lp.registry.interfaces.person import validate_public_person |
154 | 38 | from lp.registry.interfaces.productseries import IProductSeries | ||
155 | 39 | from lp.registry.interfaces.sourcepackage import ISourcePackage | ||
156 | 36 | from lp.services.database.constants import UTC_NOW | 40 | from lp.services.database.constants import UTC_NOW |
160 | 37 | from lp.services.database.datetimecol import UtcDateTimeCol | 41 | from lp.services.database.enumcol import DBEnum |
161 | 38 | from lp.services.database.enumcol import EnumCol | 42 | from lp.services.database.interfaces import IStore |
162 | 39 | from lp.services.database.sqlbase import SQLBase | 43 | from lp.services.database.stormbase import StormBase |
163 | 40 | from lp.services.features import getFeatureFlag | 44 | from lp.services.features import getFeatureFlag |
164 | 41 | 45 | ||
165 | 42 | 46 | ||
166 | 43 | @implementer(IBugNomination) | 47 | @implementer(IBugNomination) |
187 | 44 | class BugNomination(SQLBase): | 48 | class BugNomination(StormBase): |
188 | 45 | _table = "BugNomination" | 49 | |
189 | 46 | 50 | __storm_table__ = "BugNomination" | |
190 | 47 | owner = ForeignKey( | 51 | |
191 | 48 | dbName='owner', foreignKey='Person', | 52 | id = Int(primary=True) |
192 | 49 | storm_validator=validate_public_person, notNull=True) | 53 | |
193 | 50 | decider = ForeignKey( | 54 | owner_id = Int( |
194 | 51 | dbName='decider', foreignKey='Person', | 55 | name="owner", allow_none=False, validator=validate_public_person) |
195 | 52 | storm_validator=validate_public_person, notNull=False, default=None) | 56 | owner = Reference(owner_id, "Person.id") |
196 | 53 | date_created = UtcDateTimeCol(notNull=True, default=UTC_NOW) | 57 | |
197 | 54 | date_decided = UtcDateTimeCol(notNull=False, default=None) | 58 | decider_id = Int( |
198 | 55 | distroseries = ForeignKey( | 59 | name="decider", allow_none=True, default=None, |
199 | 56 | dbName='distroseries', foreignKey='DistroSeries', | 60 | validator=validate_public_person) |
200 | 57 | notNull=False, default=None) | 61 | decider = Reference(decider_id, "Person.id") |
201 | 58 | productseries = ForeignKey( | 62 | |
202 | 59 | dbName='productseries', foreignKey='ProductSeries', | 63 | date_created = DateTime(allow_none=False, default=UTC_NOW, tzinfo=pytz.UTC) |
203 | 60 | notNull=False, default=None) | 64 | date_decided = DateTime(allow_none=True, default=None, tzinfo=pytz.UTC) |
204 | 61 | bug = ForeignKey(dbName='bug', foreignKey='Bug', notNull=True) | 65 | |
205 | 62 | status = EnumCol( | 66 | distroseries_id = Int(name="distroseries", allow_none=True, default=None) |
206 | 63 | dbName='status', notNull=True, schema=BugNominationStatus, | 67 | distroseries = Reference(distroseries_id, "DistroSeries.id") |
207 | 68 | |||
208 | 69 | productseries_id = Int(name="productseries", allow_none=True, default=None) | ||
209 | 70 | productseries = Reference(productseries_id, "ProductSeries.id") | ||
210 | 71 | |||
211 | 72 | bug_id = Int(name='bug', allow_none=False) | ||
212 | 73 | bug = Reference(bug_id, 'Bug.id') | ||
213 | 74 | |||
214 | 75 | status = DBEnum( | ||
215 | 76 | name='status', allow_none=False, enum=BugNominationStatus, | ||
216 | 64 | default=BugNominationStatus.PROPOSED) | 77 | default=BugNominationStatus.PROPOSED) |
217 | 65 | 78 | ||
218 | 79 | def __init__(self, bug, owner, decider=None, date_created=UTC_NOW, | ||
219 | 80 | date_decided=None, distroseries=None, | ||
220 | 81 | productseries=None, status=BugNominationStatus.PROPOSED): | ||
221 | 82 | self.owner = owner | ||
222 | 83 | self.decider = decider | ||
223 | 84 | self.date_created = date_created | ||
224 | 85 | self.date_decided = date_decided | ||
225 | 86 | self.distroseries = distroseries | ||
226 | 87 | self.productseries = productseries | ||
227 | 88 | self.bug = bug | ||
228 | 89 | self.status = status | ||
229 | 90 | |||
230 | 66 | @property | 91 | @property |
231 | 67 | def target(self): | 92 | def target(self): |
232 | 68 | """See IBugNomination.""" | 93 | """See IBugNomination.""" |
233 | @@ -156,6 +181,12 @@ class BugNomination(SQLBase): | |||
234 | 156 | return True | 181 | return True |
235 | 157 | return False | 182 | return False |
236 | 158 | 183 | ||
237 | 184 | def destroySelf(self): | ||
238 | 185 | IStore(self).remove(self) | ||
239 | 186 | |||
240 | 187 | def __repr__(self): | ||
241 | 188 | return "<BugNomination bug=%s owner=%s>" % (self.bug_id, self.owner_id) | ||
242 | 189 | |||
243 | 159 | 190 | ||
244 | 160 | @implementer(IBugNominationSet) | 191 | @implementer(IBugNominationSet) |
245 | 161 | class BugNominationSet: | 192 | class BugNominationSet: |
246 | @@ -163,7 +194,25 @@ class BugNominationSet: | |||
247 | 163 | 194 | ||
248 | 164 | def get(self, id): | 195 | def get(self, id): |
249 | 165 | """See IBugNominationSet.""" | 196 | """See IBugNominationSet.""" |
253 | 166 | try: | 197 | store = IStore(BugNomination) |
254 | 167 | return BugNomination.get(id) | 198 | nomination = store.get(BugNomination, id) |
255 | 168 | except SQLObjectNotFound: | 199 | if nomination is None: |
256 | 169 | raise NotFoundError(id) | 200 | raise NotFoundError(id) |
257 | 201 | return nomination | ||
258 | 202 | |||
259 | 203 | def getByBugTarget(self, bug, target): | ||
260 | 204 | if IDistroSeries.providedBy(target): | ||
261 | 205 | filter_args = dict(distroseries_id=target.id) | ||
262 | 206 | elif IProductSeries.providedBy(target): | ||
263 | 207 | filter_args = dict(productseries_id=target.id) | ||
264 | 208 | elif ISourcePackage.providedBy(target): | ||
265 | 209 | filter_args = dict(distroseries_id=target.series.id) | ||
266 | 210 | else: | ||
267 | 211 | return None | ||
268 | 212 | store = IStore(BugNomination) | ||
269 | 213 | return store.find(BugNomination, bug=bug, **filter_args).one() | ||
270 | 214 | |||
271 | 215 | def findByBug(self, bug): | ||
272 | 216 | """See IBugNominationSet.""" | ||
273 | 217 | store = IStore(BugNomination) | ||
274 | 218 | return store.find(BugNomination, bug=bug) | ||
275 | diff --git a/lib/lp/bugs/model/bugtasksearch.py b/lib/lp/bugs/model/bugtasksearch.py | |||
276 | index 21f7313..184fed4 100644 | |||
277 | --- a/lib/lp/bugs/model/bugtasksearch.py | |||
278 | +++ b/lib/lp/bugs/model/bugtasksearch.py | |||
279 | @@ -674,7 +674,7 @@ def _build_query(params): | |||
280 | 674 | raise AssertionError( | 674 | raise AssertionError( |
281 | 675 | 'Unknown nomination target: %r.' % params.nominated_for) | 675 | 'Unknown nomination target: %r.' % params.nominated_for) |
282 | 676 | extra_clauses.append(And( | 676 | extra_clauses.append(And( |
284 | 677 | BugNomination.bugID == BugTaskFlat.bug_id, | 677 | BugNomination.bug_id == BugTaskFlat.bug_id, |
285 | 678 | BugNomination.status == BugNominationStatus.PROPOSED, | 678 | BugNomination.status == BugNominationStatus.PROPOSED, |
286 | 679 | target_col == params.nominated_for)) | 679 | target_col == params.nominated_for)) |
287 | 680 | clauseTables.append(BugNomination) | 680 | clauseTables.append(BugNomination) |
Pushed the requested changes.