Merge ~pappacena/launchpad:stormify-bug-task into launchpad:master
- Git
- lp:~pappacena/launchpad
- stormify-bug-task
- Merge into master
Status: | Merged |
---|---|
Approved by: | Thiago F. Pappacena |
Approved revision: | 2f08d3244eaaca8c0543a2ea9e8905a84cacc209 |
Merge reported by: | Otto Co-Pilot |
Merged at revision: | not available |
Proposed branch: | ~pappacena/launchpad:stormify-bug-task |
Merge into: | launchpad:master |
Diff against target: |
1317 lines (+273/-229) 28 files modified
lib/lp/bugs/browser/buglisting.py (+3/-3) lib/lp/bugs/browser/cvereport.py (+2/-2) lib/lp/bugs/browser/person.py (+2/-2) lib/lp/bugs/browser/tests/bugs-views.txt (+4/-1) lib/lp/bugs/browser/tests/test_bugtask.py (+5/-5) lib/lp/bugs/configure.zcml (+8/-8) lib/lp/bugs/doc/bugtask-expiration.txt (+6/-3) lib/lp/bugs/doc/bugtask-retrieval.txt (+10/-6) lib/lp/bugs/doc/bugtask-search.txt (+27/-12) lib/lp/bugs/feed/bug.py (+3/-3) lib/lp/bugs/interfaces/bugtask.py (+12/-8) lib/lp/bugs/interfaces/bugtaskfilter.py (+3/-3) lib/lp/bugs/model/bug.py (+11/-11) lib/lp/bugs/model/bugtask.py (+124/-109) lib/lp/bugs/model/bugtasksearch.py (+22/-22) lib/lp/bugs/model/cve.py (+1/-1) lib/lp/bugs/model/personsubscriptioninfo.py (+3/-3) lib/lp/bugs/scripts/bugsummaryrebuild.py (+4/-4) lib/lp/bugs/scripts/bugtasktargetnamecaches.py (+3/-3) lib/lp/code/model/branchcollection.py (+1/-1) lib/lp/registry/browser/milestone.py (+2/-2) lib/lp/registry/model/distribution.py (+1/-1) lib/lp/registry/model/distroseries.py (+2/-2) lib/lp/registry/model/person.py (+3/-3) lib/lp/registry/model/product.py (+1/-1) lib/lp/registry/model/productseries.py (+3/-3) lib/lp/registry/model/sourcepackage.py (+6/-6) lib/lp/registry/scripts/closeaccount.py (+1/-1) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Colin Watson (community) | Approve | ||
Ioana Lasc (community) | Approve | ||
Review via email: mp+393473@code.launchpad.net |
Commit message
Stormifying BugTask class, to prepare it to receive foreign key to OCI project
Description of the change
This MP is quite big in terms of lines changed, but it's mostly a refactoring, and the final behavior shouldn't have changed.
Thiago F. Pappacena (pappacena) wrote : | # |
Ioana Lasc (ilasc) wrote : | # |
Nicely done!
A few minor comments around make lint failures:
./lib/lp/
159: source exceeds 78 characters.
./lib/lp/
1: narrative uses a moin header.
17: narrative uses a moin header.
26: source has trailing whitespace.
42: narrative uses a moin header.
8: 'NotFoundError' imported but unused
./lib/lp/
1: narrative uses a moin header.
27: narrative uses a moin header.
58: narrative uses a moin header.
116: narrative uses a moin header.
150: narrative uses a moin header.
155: narrative uses a moin header.
203: narrative uses a moin header.
222: narrative uses a moin header.
245: narrative uses a moin header.
You can use this as an example for the moin header issues: https:/
Thiago F. Pappacena (pappacena) wrote : | # |
Good catch, ilasc! Thanks for the review!
It should be good now.
Ioana Lasc (ilasc) : | # |
Colin Watson (cjwatson) wrote : | # |
This mostly looks fine, but I'm interested in your thoughts on my comments regarding PassthroughValue; maybe there's some other reason for the refactoring that I missed.
- 3f09d61... by Thiago F. Pappacena
-
Changing _defaultOrder attribute to __storm_order__ on BugTask
Thiago F. Pappacena (pappacena) wrote : | # |
ctwatson, I've added a reply to your comment on PassthoughValue, and submitted a patch for the other 2 comments.
Colin Watson (cjwatson) : | # |
Thiago F. Pappacena (pappacena) : | # |
Colin Watson (cjwatson) : | # |
Thiago F. Pappacena (pappacena) : | # |
- 2f08d32... by Thiago F. Pappacena
-
Reverting the PassthroughValue wrapper removal
Preview Diff
1 | diff --git a/lib/lp/bugs/browser/buglisting.py b/lib/lp/bugs/browser/buglisting.py |
2 | index c0e67a6..6acbf8a 100644 |
3 | --- a/lib/lp/bugs/browser/buglisting.py |
4 | +++ b/lib/lp/bugs/browser/buglisting.py |
5 | @@ -1,4 +1,4 @@ |
6 | -# Copyright 2009-2019 Canonical Ltd. This software is licensed under the |
7 | +# Copyright 2009-2020 Canonical Ltd. This software is licensed under the |
8 | # GNU Affero General Public License version 3 (see the file LICENSE). |
9 | |
10 | """IBugTask-related browser views.""" |
11 | @@ -657,8 +657,8 @@ class BugTaskListingItem: |
12 | else: |
13 | milestone_name = None |
14 | assignee = None |
15 | - if self.assigneeID is not None: |
16 | - assignee = self.people[self.assigneeID].displayname |
17 | + if self.assignee_id is not None: |
18 | + assignee = self.people[self.assignee_id].displayname |
19 | reporter = self.people[self.bug.ownerID] |
20 | |
21 | # the case that there is no target context (e.g. viewing bug that |
22 | diff --git a/lib/lp/bugs/browser/cvereport.py b/lib/lp/bugs/browser/cvereport.py |
23 | index 9626295..e799288 100644 |
24 | --- a/lib/lp/bugs/browser/cvereport.py |
25 | +++ b/lib/lp/bugs/browser/cvereport.py |
26 | @@ -1,4 +1,4 @@ |
27 | -# Copyright 2009-2011 Canonical Ltd. This software is licensed under the |
28 | +# Copyright 2009-2020 Canonical Ltd. This software is licensed under the |
29 | # GNU Affero General Public License version 3 (see the file LICENSE). |
30 | |
31 | """Views to generate CVE reports (as in distro & distroseries/+cve pages).""" |
32 | @@ -122,7 +122,7 @@ class CVEReportView(LaunchpadView): |
33 | |
34 | # The page contains links to the bug task assignees: |
35 | # Pre-load the related Person and ValidPersonCache records |
36 | - assignee_ids = [task.assigneeID for task in bugtasks] |
37 | + assignee_ids = [task.assignee_id for task in bugtasks] |
38 | list(getUtility(IPersonSet).getPrecachedPersonsFromIDs( |
39 | assignee_ids, need_validity=True)) |
40 | |
41 | diff --git a/lib/lp/bugs/browser/person.py b/lib/lp/bugs/browser/person.py |
42 | index c25219d..b3f4fae 100644 |
43 | --- a/lib/lp/bugs/browser/person.py |
44 | +++ b/lib/lp/bugs/browser/person.py |
45 | @@ -1,4 +1,4 @@ |
46 | -# Copyright 2012 Canonical Ltd. This software is licensed under the |
47 | +# Copyright 2012-2020 Canonical Ltd. This software is licensed under the |
48 | # GNU Affero General Public License version 3 (see the file LICENSE). |
49 | |
50 | """IPerson browser views related to bugs.""" |
51 | @@ -132,7 +132,7 @@ class RelevantMilestonesMixin: |
52 | """Return data used to render the milestone checkboxes.""" |
53 | tasks = self.searchUnbatched() |
54 | milestones = sorted( |
55 | - load_related(Milestone, tasks, ['milestoneID']), |
56 | + load_related(Milestone, tasks, ['milestone_id']), |
57 | key=milestone_sort_key, reverse=True) |
58 | return [ |
59 | dict(title=milestone.title, value=milestone.id, checked=False) |
60 | diff --git a/lib/lp/bugs/browser/tests/bugs-views.txt b/lib/lp/bugs/browser/tests/bugs-views.txt |
61 | index 54baf33..59fce27 100644 |
62 | --- a/lib/lp/bugs/browser/tests/bugs-views.txt |
63 | +++ b/lib/lp/bugs/browser/tests/bugs-views.txt |
64 | @@ -22,8 +22,11 @@ Launchpad currently. |
65 | |
66 | >>> from lp.bugs.interfaces.bugtask import BugTaskStatus |
67 | >>> from lp.bugs.model.bugtask import BugTask |
68 | + >>> from lp.services.database.interfaces import IStore |
69 | + >>> store = IStore(BugTask) |
70 | >>> [bugtask.bug.id |
71 | - ... for bugtask in BugTask.selectBy(_status=BugTaskStatus.FIXRELEASED)] |
72 | + ... for bugtask in store.find( |
73 | + ... BugTask, BugTask._status == BugTaskStatus.FIXRELEASED)] |
74 | [8] |
75 | >>> for bug in bugs_view.most_recently_fixed_bugs: |
76 | ... print("%s: %s" % (bug.id, bug.title)) |
77 | diff --git a/lib/lp/bugs/browser/tests/test_bugtask.py b/lib/lp/bugs/browser/tests/test_bugtask.py |
78 | index dd33206..cb98e74 100644 |
79 | --- a/lib/lp/bugs/browser/tests/test_bugtask.py |
80 | +++ b/lib/lp/bugs/browser/tests/test_bugtask.py |
81 | @@ -129,7 +129,7 @@ class TestBugTaskView(TestCaseWithFactory): |
82 | 0, 10, login_method=lambda: login(ADMIN_EMAIL)) |
83 | # This may seem large: it is; there is easily another 25% fat in |
84 | # there. |
85 | - self.assertThat(recorder1, HasQueryCount(LessThan(85))) |
86 | + self.assertThat(recorder1, HasQueryCount(LessThan(86))) |
87 | self.assertThat(recorder2, HasQueryCount.byEquality(recorder1)) |
88 | |
89 | def test_rendered_query_counts_constant_with_attachments(self): |
90 | @@ -140,7 +140,7 @@ class TestBugTaskView(TestCaseWithFactory): |
91 | lambda: self.getUserBrowser(url, person), |
92 | lambda: self.factory.makeBugAttachment(bug=task.bug), |
93 | 1, 9, login_method=lambda: login(ADMIN_EMAIL)) |
94 | - self.assertThat(recorder1, HasQueryCount(LessThan(86))) |
95 | + self.assertThat(recorder1, HasQueryCount(LessThan(87))) |
96 | self.assertThat(recorder2, HasQueryCount.byEquality(recorder1)) |
97 | |
98 | def makeLinkedBranchMergeProposal(self, sourcepackage, bug, owner): |
99 | @@ -175,7 +175,7 @@ class TestBugTaskView(TestCaseWithFactory): |
100 | recorder1, recorder2 = record_two_runs( |
101 | lambda: self.getUserBrowser(url, owner), |
102 | make_merge_proposals, 0, 1) |
103 | - self.assertThat(recorder1, HasQueryCount(LessThan(93))) |
104 | + self.assertThat(recorder1, HasQueryCount(LessThan(94))) |
105 | # Ideally this should be much fewer, but this tries to keep a win of |
106 | # removing more than half of these. |
107 | self.assertThat( |
108 | @@ -221,7 +221,7 @@ class TestBugTaskView(TestCaseWithFactory): |
109 | lambda: self.getUserBrowser(url, person), |
110 | lambda: add_activity("description", self.factory.makePerson()), |
111 | 1, 20, login_method=lambda: login(ADMIN_EMAIL)) |
112 | - self.assertThat(recorder1, HasQueryCount(LessThan(86))) |
113 | + self.assertThat(recorder1, HasQueryCount(LessThan(87))) |
114 | self.assertThat(recorder2, HasQueryCount.byEquality(recorder1)) |
115 | |
116 | def test_rendered_query_counts_constant_with_milestones(self): |
117 | @@ -231,7 +231,7 @@ class TestBugTaskView(TestCaseWithFactory): |
118 | |
119 | with celebrity_logged_in('admin'): |
120 | browses_under_limit = BrowsesWithQueryLimit( |
121 | - 86, self.factory.makePerson()) |
122 | + 87, self.factory.makePerson()) |
123 | |
124 | self.assertThat(bug, browses_under_limit) |
125 | |
126 | diff --git a/lib/lp/bugs/configure.zcml b/lib/lp/bugs/configure.zcml |
127 | index 7edae44..3e4544b 100644 |
128 | --- a/lib/lp/bugs/configure.zcml |
129 | +++ b/lib/lp/bugs/configure.zcml |
130 | @@ -167,9 +167,9 @@ |
131 | <allow |
132 | attributes=" |
133 | id |
134 | - assigneeID |
135 | + assignee_id |
136 | bug |
137 | - bugID |
138 | + bug_id |
139 | target |
140 | date_assigned |
141 | datecreated |
142 | @@ -182,12 +182,12 @@ |
143 | date_fix_released |
144 | date_left_closed |
145 | date_closed |
146 | - distributionID |
147 | - distroseriesID |
148 | - milestoneID |
149 | - productID |
150 | - productseriesID |
151 | - sourcepackagenameID |
152 | + distribution_id |
153 | + distroseries_id |
154 | + milestone_id |
155 | + product_id |
156 | + productseries_id |
157 | + sourcepackagename_id |
158 | task_age |
159 | bug_subscribers |
160 | is_complete |
161 | diff --git a/lib/lp/bugs/doc/bugtask-expiration.txt b/lib/lp/bugs/doc/bugtask-expiration.txt |
162 | index 4d4e82b..11b755e 100644 |
163 | --- a/lib/lp/bugs/doc/bugtask-expiration.txt |
164 | +++ b/lib/lp/bugs/doc/bugtask-expiration.txt |
165 | @@ -156,7 +156,8 @@ Let's also make some bugs that almost qualify for expiration. |
166 | >>> ubuntu_alsa = ubuntu.getSourcePackage('alsa-utils') |
167 | >>> another_assigned_bugtask = create_old_bug( |
168 | ... 'assigned', 61, ubuntu, assignee=sample_person) |
169 | - >>> another_assigned_bugtask.transitionToTarget(ubuntu_alsa, sample_person) |
170 | + >>> another_assigned_bugtask.transitionToTarget( |
171 | + ... ubuntu_alsa, sample_person) |
172 | >>> ubuntu_evolution = ubuntu.getSourcePackage('evolution') |
173 | >>> invalid_bugtask = bugtaskset.createTask( |
174 | ... another_assigned_bugtask.bug, sample_person, ubuntu_evolution, |
175 | @@ -472,7 +473,9 @@ Running the script |
176 | There are no Expired Bugtasks in sampledata, from the tests above. |
177 | |
178 | >>> from lp.bugs.model.bugtask import BugTask |
179 | - >>> BugTask.selectBy(status=BugTaskStatus.EXPIRED).count() |
180 | + >>> from lp.services.database.interfaces import IStore |
181 | + >>> store = IStore(BugTask) |
182 | + >>> store.find(BugTask, BugTask.status == BugTaskStatus.EXPIRED).count() |
183 | 0 |
184 | |
185 | We want to check the hoary bugtask messages later. |
186 | @@ -510,7 +513,7 @@ config.malone.expiration_dbuser. |
187 | >>> process.returncode |
188 | 0 |
189 | |
190 | - >>> bugtasks = [BugTask.get(bugtask.id) for bugtask in bugtasks] |
191 | + >>> bugtasks = [bugtaskset.get(bugtask.id) for bugtask in bugtasks] |
192 | |
193 | |
194 | After the script has run |
195 | diff --git a/lib/lp/bugs/doc/bugtask-retrieval.txt b/lib/lp/bugs/doc/bugtask-retrieval.txt |
196 | index e78c433..5fac87c 100644 |
197 | --- a/lib/lp/bugs/doc/bugtask-retrieval.txt |
198 | +++ b/lib/lp/bugs/doc/bugtask-retrieval.txt |
199 | @@ -1,19 +1,21 @@ |
200 | -= Retrieving bug tasks = |
201 | +Retrieving bug tasks |
202 | +********************* |
203 | |
204 | The IBugTaskSet interface provide a couple of methods for retrieving |
205 | IBugTask instances. For convenience, Launchpad provides a default |
206 | implementation of IBugTaskSet, allowing retrieval of any bug task in |
207 | Launchpad. We'll use this implementation for demonstration purposes: |
208 | |
209 | - >>> from lp.app.errors import NotFoundError |
210 | >>> from lp.bugs.interfaces.bugtask import ( |
211 | ... IBugTask, |
212 | ... IBugTaskSet, |
213 | ... ) |
214 | + >>> from lp.services.database.interfaces import IStore |
215 | >>> task_set = getUtility(IBugTaskSet) |
216 | |
217 | |
218 | -== Retrieving a single bug task == |
219 | +Retrieving a single bug task |
220 | +***************************** |
221 | |
222 | The IBugTaskSet get method retrieves a single bug task matching a given |
223 | ID: |
224 | @@ -22,7 +24,7 @@ ID: |
225 | >>> retrieved_task |
226 | <BugTask ...> |
227 | |
228 | - >>> from lp.testing import verifyObject |
229 | + >>> from lp.testing import verifyObject |
230 | >>> verifyObject(IBugTask, retrieved_task) |
231 | True |
232 | |
233 | @@ -38,15 +40,17 @@ raises a NotFoundError: |
234 | NotFoundError: ... |
235 | |
236 | |
237 | -== Retrieving multiple bug tasks == |
238 | +Retrieving multiple bug tasks |
239 | +****************************** |
240 | |
241 | The IBugTaskSet getMultiple method can retrieve multiple bug tasks in a |
242 | single operation. To demonstrate, we'll begin by generating a list of |
243 | sample bug tasks: |
244 | |
245 | >>> from lp.bugs.model.bugtask import BugTask |
246 | + >>> store = IStore(BugTask) |
247 | >>> sample_task_count = 10 |
248 | - >>> sample_tasks = BugTask.select(limit=sample_task_count) |
249 | + >>> sample_tasks = store.find(BugTask)[:sample_task_count] |
250 | >>> sample_task_ids = [task.id for task in sample_tasks] |
251 | |
252 | When given a sequence of bug task IDs, the method returns a dictionary |
253 | diff --git a/lib/lp/bugs/doc/bugtask-search.txt b/lib/lp/bugs/doc/bugtask-search.txt |
254 | index 750b3c5..1e45abe 100644 |
255 | --- a/lib/lp/bugs/doc/bugtask-search.txt |
256 | +++ b/lib/lp/bugs/doc/bugtask-search.txt |
257 | @@ -1,4 +1,5 @@ |
258 | -= Searching BugTasks = |
259 | +Searching BugTasks |
260 | +******************* |
261 | |
262 | BugTasks are usually searched through an IBugTarget's searchTasks() |
263 | method, but they all delegate the search to IBugTaskSet.search(). That |
264 | @@ -6,19 +7,26 @@ method accepts a single parameter; an BugTaskSearchParams instance. |
265 | |
266 | >>> from lp.bugs.interfaces.bugtask import IBugTaskSet |
267 | >>> from lp.bugs.interfaces.bugtasksearch import BugTaskSearchParams |
268 | + >>> from lp.services.database.interfaces import IStore |
269 | >>> bugtask_set = getUtility(IBugTaskSet) |
270 | >>> all_public = BugTaskSearchParams(user=None) |
271 | >>> found_bugtasks = bugtask_set.search(all_public) |
272 | |
273 | + >>> from lp.app.enums import InformationType |
274 | + >>> from lp.bugs.model.bug import Bug |
275 | >>> from lp.bugs.model.bugtask import BugTask |
276 | - >>> all_public_bugtasks = BugTask.select( |
277 | - ... "BugTask.bug = Bug.id AND Bug.information_type IN (1, 2)", |
278 | - ... clauseTables=['Bug']) |
279 | + >>> store = IStore(BugTask) |
280 | + >>> info_types = [InformationType.PUBLIC, InformationType.PUBLICSECURITY] |
281 | + >>> all_public_bugtasks = store.find( |
282 | + ... BugTask, |
283 | + ... BugTask.bug_id == Bug.id, |
284 | + ... Bug.information_type.is_in(info_types)) |
285 | >>> found_bugtasks.count() == all_public_bugtasks.count() |
286 | True |
287 | |
288 | |
289 | -== Searching using bug full-text index == |
290 | +Searching using bug full-text index |
291 | +************************************ |
292 | |
293 | The searchtext parameter does an extensive and expensive search (it |
294 | looks through the bug's full text index, bug comments, bugtask |
295 | @@ -49,7 +57,8 @@ But if we put that word in the bug #4 description, it will be found. |
296 | ... print("#%s" % bugtask.bug.id) |
297 | #4 |
298 | |
299 | -=== BugTaskSearchParams' parameters searchtext and fast_searchtext === |
300 | +BugTaskSearchParams' parameters searchtext and fast_searchtext |
301 | +*************************************************************** |
302 | |
303 | Normally, the parameter searchtext should be used. The alternative |
304 | parameter fast_searchtext requires a syntactically correct tsquery |
305 | @@ -107,7 +116,8 @@ Passing invalid tsquery expressions as fast_searchtext raises an exception. |
306 | >>> transaction.abort() |
307 | |
308 | |
309 | -== Bugs with partner packages == |
310 | +Bugs with partner packages |
311 | +*************************** |
312 | |
313 | Bugs may also be targeted to partner packages. First turn "cdrkit" into |
314 | a partner package: |
315 | @@ -141,12 +151,14 @@ We can file a bug against it and see that show up in a search: |
316 | 1 |
317 | |
318 | |
319 | -== Ordering search results == |
320 | +Ordering search results |
321 | +************************ |
322 | |
323 | The result returned by bugtask searches can come sorted by a specified order |
324 | |
325 | |
326 | -=== Ordering by number of duplicates === |
327 | +Ordering by number of duplicates |
328 | +********************************* |
329 | |
330 | It is possible to sort the results by the number of duplicates each bag has. |
331 | |
332 | @@ -194,7 +206,8 @@ a duplicate. |
333 | cdrkit (Ubuntu) Bug to be fixed in trunk |
334 | |
335 | |
336 | -=== Ordering by number of comments === |
337 | +Ordering by number of comments |
338 | +******************************* |
339 | |
340 | It is also possible to sort the results by the number of comments on a bug. |
341 | |
342 | @@ -213,7 +226,8 @@ Here is the list of bugs for Ubuntu, sorted by their number of comments. |
343 | Bug to be fixed in trunk [1 comments] |
344 | |
345 | |
346 | -=== Ordering by bug heat === |
347 | +Ordering by bug heat |
348 | +********************* |
349 | |
350 | Another way of sorting searches is by bug heat. |
351 | |
352 | @@ -236,7 +250,8 @@ Another way of sorting searches is by bug heat. |
353 | Firefox does not support SVG [heat: 1] |
354 | |
355 | |
356 | -=== Ordering by patch age === |
357 | +Ordering by patch age |
358 | +********************** |
359 | |
360 | We can also sort search results by the creation time of the youngest |
361 | patch attached to a bug. |
362 | diff --git a/lib/lp/bugs/feed/bug.py b/lib/lp/bugs/feed/bug.py |
363 | index 218f199..3f443b0 100644 |
364 | --- a/lib/lp/bugs/feed/bug.py |
365 | +++ b/lib/lp/bugs/feed/bug.py |
366 | @@ -1,4 +1,4 @@ |
367 | -# Copyright 2009-2017 Canonical Ltd. This software is licensed under the |
368 | +# Copyright 2009-2020 Canonical Ltd. This software is licensed under the |
369 | # GNU Affero General Public License version 3 (see the file LICENSE). |
370 | |
371 | """Bug feed (syndication) views.""" |
372 | @@ -147,9 +147,9 @@ class BugsFeedBase(FeedBase): |
373 | """ |
374 | bug_ids = [] |
375 | for task in tasks: |
376 | - if task.bugID in bug_ids: |
377 | + if task.bug_id in bug_ids: |
378 | continue |
379 | - bug_ids.append(task.bugID) |
380 | + bug_ids.append(task.bug_id) |
381 | if len(bug_ids) >= self.quantity: |
382 | break |
383 | # XXX: BradCrittenden 2008-03-26 bug=TBD: |
384 | diff --git a/lib/lp/bugs/interfaces/bugtask.py b/lib/lp/bugs/interfaces/bugtask.py |
385 | index f7c1600..7051df8 100644 |
386 | --- a/lib/lp/bugs/interfaces/bugtask.py |
387 | +++ b/lib/lp/bugs/interfaces/bugtask.py |
388 | @@ -1,4 +1,4 @@ |
389 | -# Copyright 2009-2016 Canonical Ltd. This software is licensed under the |
390 | +# Copyright 2009-2020 Canonical Ltd. This software is licensed under the |
391 | # GNU Affero General Public License version 3 (see the file LICENSE). |
392 | |
393 | """Bug task interfaces.""" |
394 | @@ -374,6 +374,9 @@ class IllegalTarget(Exception): |
395 | |
396 | class IBugTaskDelete(Interface): |
397 | """An interface for operations allowed with the Delete permission.""" |
398 | + def destroySelf(): |
399 | + """Removes this BugTask from the database.""" |
400 | + |
401 | @export_destructor_operation() |
402 | @call_with(who=REQUEST_USER) |
403 | @operation_for_version('devel') |
404 | @@ -395,30 +398,31 @@ class IBugTask(IHasBug, IBugTaskDelete): |
405 | id = Int(title=_("Bug Task #")) |
406 | bug = exported( |
407 | BugField(title=_("Bug"), readonly=True)) |
408 | + bug_id = Int(title=_("The bug ID for this bug task")) |
409 | product = Choice( |
410 | title=_('Project'), required=False, vocabulary='Product') |
411 | - productID = Attribute('The product ID') |
412 | + product_id = Attribute('The product ID') |
413 | productseries = Choice( |
414 | title=_('Series'), required=False, vocabulary='ProductSeries') |
415 | - productseriesID = Attribute('The product series ID') |
416 | + productseries_id = Attribute('The product series ID') |
417 | sourcepackagename = Choice( |
418 | title=_("Package"), required=False, |
419 | vocabulary='SourcePackageName') |
420 | - sourcepackagenameID = Attribute('The sourcepackagename ID') |
421 | + sourcepackagename_id = Attribute('The sourcepackagename ID') |
422 | distribution = Choice( |
423 | title=_("Distribution"), required=False, vocabulary='Distribution') |
424 | - distributionID = Attribute('The distribution ID') |
425 | + distribution_id = Attribute('The distribution ID') |
426 | distroseries = Choice( |
427 | title=_("Series"), required=False, |
428 | vocabulary='DistroSeries') |
429 | - distroseriesID = Attribute('The distroseries ID') |
430 | + distroseries_id = Attribute('The distroseries ID') |
431 | milestone = exported(ReferenceChoice( |
432 | title=_('Milestone'), |
433 | required=False, |
434 | readonly=True, |
435 | vocabulary='BugTaskMilestone', |
436 | schema=Interface)) # IMilestone |
437 | - milestoneID = Attribute('The id of the milestone.') |
438 | + milestone_id = Attribute('The id of the milestone.') |
439 | |
440 | # The status and importance's vocabularies do not |
441 | # contain an UNKNOWN item in bugtasks that aren't linked to a remote |
442 | @@ -440,7 +444,7 @@ class IBugTask(IHasBug, IBugTaskDelete): |
443 | title=_('Assigned to'), required=False, |
444 | vocabulary='ValidAssignee', |
445 | readonly=True)) |
446 | - assigneeID = Int(title=_('The assignee ID (for eager loading)')) |
447 | + assignee_id = Int(title=_('The assignee ID (for eager loading)')) |
448 | bugtargetdisplayname = exported( |
449 | Text(title=_("The short, descriptive name of the target"), |
450 | readonly=True), |
451 | diff --git a/lib/lp/bugs/interfaces/bugtaskfilter.py b/lib/lp/bugs/interfaces/bugtaskfilter.py |
452 | index 898c955..4ecccfb 100644 |
453 | --- a/lib/lp/bugs/interfaces/bugtaskfilter.py |
454 | +++ b/lib/lp/bugs/interfaces/bugtaskfilter.py |
455 | @@ -1,4 +1,4 @@ |
456 | -# Copyright 2011 Canonical Ltd. This software is licensed under the |
457 | +# Copyright 2011-2020 Canonical Ltd. This software is licensed under the |
458 | # GNU Affero General Public License version 3 (see the file LICENSE). |
459 | |
460 | """Fiter bugtasks based on context.""" |
461 | @@ -67,7 +67,7 @@ def filter_bugtasks_by_context(context, bugtasks): |
462 | |
463 | bug_mapping = defaultdict(list) |
464 | for task in bugtasks: |
465 | - bug_mapping[task.bugID].append(weight_calculator(task)) |
466 | + bug_mapping[task.bug_id].append(weight_calculator(task)) |
467 | |
468 | filtered = [sorted(tasks)[0].task for tasks in six.itervalues(bug_mapping)] |
469 | - return sorted(filtered, key=attrgetter('bugID')) |
470 | + return sorted(filtered, key=attrgetter('bug_id')) |
471 | diff --git a/lib/lp/bugs/model/bug.py b/lib/lp/bugs/model/bug.py |
472 | index c1e35a1..12f9e72 100644 |
473 | --- a/lib/lp/bugs/model/bug.py |
474 | +++ b/lib/lp/bugs/model/bug.py |
475 | @@ -659,14 +659,14 @@ class Bug(SQLBase, InformationTypeMixin): |
476 | from lp.registry.model.productseries import ProductSeries |
477 | from lp.registry.model.sourcepackagename import SourcePackageName |
478 | store = Store.of(self) |
479 | - tasks = list(store.find(BugTask, BugTask.bugID == self.id)) |
480 | + tasks = list(store.find(BugTask, BugTask.bug_id == self.id)) |
481 | # The bugtasks attribute is iterated in the API and web |
482 | # services, so it needs to preload all related data otherwise |
483 | # late evaluation is triggered in both places. Separately, |
484 | # bugtask_sort_key requires the related products, series, |
485 | # distros, distroseries and source package names to be loaded. |
486 | - ids = set(map(operator.attrgetter('assigneeID'), tasks)) |
487 | - ids.update(map(operator.attrgetter('ownerID'), tasks)) |
488 | + ids = set(map(operator.attrgetter('assignee_id'), tasks)) |
489 | + ids.update(map(operator.attrgetter('owner_id'), tasks)) |
490 | ids.discard(None) |
491 | if ids: |
492 | list(getUtility(IPersonSet).getPrecachedPersonsFromIDs( |
493 | @@ -678,11 +678,11 @@ class Bug(SQLBase, InformationTypeMixin): |
494 | if not ids: |
495 | return |
496 | list(store.find(klass, klass.id.is_in(ids))) |
497 | - load_something('productID', Product) |
498 | - load_something('productseriesID', ProductSeries) |
499 | - load_something('distributionID', Distribution) |
500 | - load_something('distroseriesID', DistroSeries) |
501 | - load_something('sourcepackagenameID', SourcePackageName) |
502 | + load_something('product_id', Product) |
503 | + load_something('productseries_id', ProductSeries) |
504 | + load_something('distribution_id', Distribution) |
505 | + load_something('distroseries_id', DistroSeries) |
506 | + load_something('sourcepackagename_id', SourcePackageName) |
507 | list(store.find(BugWatch, BugWatch.bugID == self.id)) |
508 | return sorted(tasks, key=bugtask_sort_key) |
509 | |
510 | @@ -692,7 +692,7 @@ class Bug(SQLBase, InformationTypeMixin): |
511 | from lp.registry.model.product import Product |
512 | return Store.of(self).using( |
513 | BugTask, |
514 | - LeftJoin(Product, Product.id == BugTask.productID) |
515 | + LeftJoin(Product, Product.id == BugTask.product_id) |
516 | ).find( |
517 | BugTask, bug=self |
518 | ).order_by( |
519 | @@ -2619,10 +2619,10 @@ class BugSubscriptionInfo: |
520 | """ |
521 | if self.bugtask is None: |
522 | assignees = load_people( |
523 | - Person.id.is_in(Select(BugTask.assigneeID, |
524 | + Person.id.is_in(Select(BugTask.assignee_id, |
525 | BugTask.bug == self.bug))) |
526 | else: |
527 | - assignees = load_people(Person.id == self.bugtask.assigneeID) |
528 | + assignees = load_people(Person.id == self.bugtask.assignee_id) |
529 | if self.bug.private: |
530 | return IStore(Person).find(Person, |
531 | Person.id.is_in([a.id for a in assignees]), |
532 | diff --git a/lib/lp/bugs/model/bugtask.py b/lib/lp/bugs/model/bugtask.py |
533 | index fb2bfee..32440f1 100644 |
534 | --- a/lib/lp/bugs/model/bugtask.py |
535 | +++ b/lib/lp/bugs/model/bugtask.py |
536 | @@ -33,11 +33,6 @@ import re |
537 | from lazr.lifecycle.event import ObjectDeletedEvent |
538 | import pytz |
539 | import six |
540 | -from sqlobject import ( |
541 | - ForeignKey, |
542 | - SQLObjectNotFound, |
543 | - StringCol, |
544 | - ) |
545 | from storm.expr import ( |
546 | And, |
547 | Cast, |
548 | @@ -51,6 +46,12 @@ from storm.expr import ( |
549 | Sum, |
550 | ) |
551 | from storm.info import ClassAlias |
552 | +from storm.properties import ( |
553 | + DateTime, |
554 | + Int, |
555 | + Unicode, |
556 | + ) |
557 | +from storm.references import Reference |
558 | from storm.store import ( |
559 | EmptyResultSet, |
560 | Store, |
561 | @@ -124,18 +125,17 @@ from lp.services.database.bulk import ( |
562 | load_related, |
563 | ) |
564 | from lp.services.database.constants import UTC_NOW |
565 | -from lp.services.database.datetimecol import UtcDateTimeCol |
566 | from lp.services.database.decoratedresultset import DecoratedResultSet |
567 | -from lp.services.database.enumcol import EnumCol |
568 | +from lp.services.database.enumcol import DBEnum |
569 | from lp.services.database.interfaces import IStore |
570 | from lp.services.database.nl_search import nl_phrase_search |
571 | from lp.services.database.sqlbase import ( |
572 | block_implicit_flushes, |
573 | cursor, |
574 | quote, |
575 | - SQLBase, |
576 | sqlvalues, |
577 | ) |
578 | +from lp.services.database.stormbase import StormBase |
579 | from lp.services.helpers import shortlist |
580 | from lp.services.propertycache import get_property_cache |
581 | from lp.services.searchbuilder import any |
582 | @@ -263,23 +263,18 @@ class PassthroughValue: |
583 | |
584 | @block_implicit_flushes |
585 | def validate_conjoined_attribute(self, attr, value): |
586 | + # If this is a conjoined slave then call setattr on the master. |
587 | + # Effectively this means that making a change to the slave will |
588 | + # actually make the change to the master (which will then be passed |
589 | + # down to the slave, of course). This helps to prevent OOPSes when |
590 | + # people try to update the conjoined slave via the API. |
591 | + |
592 | # If the value has been wrapped in a _PassthroughValue instance, |
593 | # then we are being updated by our conjoined master: pass the |
594 | # value through without any checking. |
595 | if isinstance(value, PassthroughValue): |
596 | return value.value |
597 | |
598 | - # Check to see if the object is being instantiated. This test is specific |
599 | - # to SQLBase. Checking for specific attributes (like self.bug) is |
600 | - # insufficient and fragile. |
601 | - if self._SO_creating: |
602 | - return value |
603 | - |
604 | - # If this is a conjoined slave then call setattr on the master. |
605 | - # Effectively this means that making a change to the slave will |
606 | - # actually make the change to the master (which will then be passed |
607 | - # down to the slave, of course). This helps to prevent OOPSes when |
608 | - # people try to update the conjoined slave via the API. |
609 | conjoined_master = self.conjoined_master |
610 | if conjoined_master is not None: |
611 | setattr(conjoined_master, attr, value) |
612 | @@ -409,13 +404,13 @@ def validate_new_target(bug, target, check_source_package=True): |
613 | |
614 | |
615 | @implementer(IBugTask) |
616 | -class BugTask(SQLBase): |
617 | +class BugTask(StormBase): |
618 | """See `IBugTask`.""" |
619 | - _table = "BugTask" |
620 | - _defaultOrder = ['distribution', 'product', 'productseries', |
621 | - 'distroseries', 'milestone', 'sourcepackagename'] |
622 | + __storm_table__ = "BugTask" |
623 | + __storm_order__ = ['distribution', 'product', 'productseries', |
624 | + 'distroseries', 'milestone', 'sourcepackagename'] |
625 | _CONJOINED_ATTRIBUTES = ( |
626 | - "_status", "importance", "assigneeID", "milestoneID", |
627 | + "_status", "importance", "assignee_id", "milestone_id", |
628 | "date_assigned", "date_confirmed", "date_inprogress", |
629 | "date_closed", "date_incomplete", "date_left_new", |
630 | "date_triaged", "date_fix_committed", "date_fix_released", |
631 | @@ -424,66 +419,84 @@ class BugTask(SQLBase): |
632 | |
633 | _inhibit_target_check = False |
634 | |
635 | - bug = ForeignKey(dbName='bug', foreignKey='Bug', notNull=True) |
636 | - product = ForeignKey( |
637 | - dbName='product', foreignKey='Product', |
638 | - notNull=False, default=None) |
639 | - productseries = ForeignKey( |
640 | - dbName='productseries', foreignKey='ProductSeries', |
641 | - notNull=False, default=None) |
642 | - sourcepackagename = ForeignKey( |
643 | - dbName='sourcepackagename', foreignKey='SourcePackageName', |
644 | - notNull=False, default=None) |
645 | - distribution = ForeignKey( |
646 | - dbName='distribution', foreignKey='Distribution', |
647 | - notNull=False, default=None) |
648 | - distroseries = ForeignKey( |
649 | - dbName='distroseries', foreignKey='DistroSeries', |
650 | - notNull=False, default=None) |
651 | - milestone = ForeignKey( |
652 | - dbName='milestone', foreignKey='Milestone', |
653 | - notNull=False, default=None, |
654 | - storm_validator=validate_conjoined_attribute) |
655 | - _status = EnumCol( |
656 | - dbName='status', notNull=True, |
657 | - schema=(BugTaskStatus, BugTaskStatusSearch), |
658 | + id = Int(primary=True) |
659 | + |
660 | + bug_id = Int(name='bug', allow_none=False) |
661 | + bug = Reference(bug_id, 'Bug.id') |
662 | + |
663 | + product_id = Int(name="product", allow_none=True) |
664 | + product = Reference(product_id, 'Product.id') |
665 | + |
666 | + productseries_id = Int(name="productseries", allow_none=True) |
667 | + productseries = Reference(productseries_id, 'ProductSeries.id') |
668 | + |
669 | + sourcepackagename_id = Int(name="sourcepackagename", allow_none=True) |
670 | + sourcepackagename = Reference(sourcepackagename_id, "SourcePackageName.id") |
671 | + |
672 | + distribution_id = Int(name="distribution", allow_none=True) |
673 | + distribution = Reference(distribution_id, "Distribution.id") |
674 | + |
675 | + distroseries_id = Int(name="distroseries", allow_none=True) |
676 | + distroseries = Reference(distroseries_id, "DistroSeries.id") |
677 | + |
678 | + milestone_id = Int( |
679 | + name="milestone", allow_none=True, |
680 | + validator=validate_conjoined_attribute) |
681 | + milestone = Reference(milestone_id, "Milestone.id") |
682 | + |
683 | + _status = DBEnum( |
684 | + name='status', allow_none=False, |
685 | + enum=(BugTaskStatus, BugTaskStatusSearch), |
686 | default=BugTaskStatus.NEW, |
687 | - storm_validator=validate_status) |
688 | - importance = EnumCol( |
689 | - dbName='importance', notNull=True, |
690 | - schema=BugTaskImportance, |
691 | + validator=validate_status) |
692 | + importance = DBEnum( |
693 | + name='importance', allow_none=False, |
694 | + enum=BugTaskImportance, |
695 | default=BugTaskImportance.UNDECIDED, |
696 | - storm_validator=validate_conjoined_attribute) |
697 | - assignee = ForeignKey( |
698 | - dbName='assignee', foreignKey='Person', |
699 | - storm_validator=validate_assignee, |
700 | - notNull=False, default=None) |
701 | - bugwatch = ForeignKey(dbName='bugwatch', foreignKey='BugWatch', |
702 | - notNull=False, default=None) |
703 | - date_assigned = UtcDateTimeCol(notNull=False, default=None, |
704 | - storm_validator=validate_conjoined_attribute) |
705 | - datecreated = UtcDateTimeCol(notNull=False, default=UTC_NOW) |
706 | - date_confirmed = UtcDateTimeCol(notNull=False, default=None, |
707 | - storm_validator=validate_conjoined_attribute) |
708 | - date_inprogress = UtcDateTimeCol(notNull=False, default=None, |
709 | - storm_validator=validate_conjoined_attribute) |
710 | - date_closed = UtcDateTimeCol(notNull=False, default=None, |
711 | - storm_validator=validate_conjoined_attribute) |
712 | - date_incomplete = UtcDateTimeCol(notNull=False, default=None, |
713 | - storm_validator=validate_conjoined_attribute) |
714 | - date_left_new = UtcDateTimeCol(notNull=False, default=None, |
715 | - storm_validator=validate_conjoined_attribute) |
716 | - date_triaged = UtcDateTimeCol(notNull=False, default=None, |
717 | - storm_validator=validate_conjoined_attribute) |
718 | - date_fix_committed = UtcDateTimeCol(notNull=False, default=None, |
719 | - storm_validator=validate_conjoined_attribute) |
720 | - date_fix_released = UtcDateTimeCol(notNull=False, default=None, |
721 | - storm_validator=validate_conjoined_attribute) |
722 | - date_left_closed = UtcDateTimeCol(notNull=False, default=None, |
723 | - storm_validator=validate_conjoined_attribute) |
724 | - owner = ForeignKey( |
725 | - dbName='owner', foreignKey='Person', |
726 | - storm_validator=validate_public_person, notNull=True) |
727 | + validator=validate_conjoined_attribute) |
728 | + |
729 | + assignee_id = Int( |
730 | + name="assignee", allow_none=True, validator=validate_assignee) |
731 | + assignee = Reference(assignee_id, "Person.id") |
732 | + |
733 | + bugwatch_id = Int(name="bugwatch", allow_none=True) |
734 | + bugwatch = Reference(bugwatch_id, "BugWatch.id") |
735 | + |
736 | + date_assigned = DateTime( |
737 | + tzinfo=pytz.UTC, allow_none=True, default=None, |
738 | + validator=validate_conjoined_attribute) |
739 | + datecreated = DateTime(tzinfo=pytz.UTC, allow_none=True, default=UTC_NOW) |
740 | + date_confirmed = DateTime( |
741 | + tzinfo=pytz.UTC, allow_none=True, default=None, |
742 | + validator=validate_conjoined_attribute) |
743 | + date_inprogress = DateTime( |
744 | + tzinfo=pytz.UTC, allow_none=True, default=None, |
745 | + validator=validate_conjoined_attribute) |
746 | + date_closed = DateTime( |
747 | + tzinfo=pytz.UTC, allow_none=True, default=None, |
748 | + validator=validate_conjoined_attribute) |
749 | + date_incomplete = DateTime( |
750 | + tzinfo=pytz.UTC, allow_none=True, default=None, |
751 | + validator=validate_conjoined_attribute) |
752 | + date_left_new = DateTime( |
753 | + tzinfo=pytz.UTC, allow_none=True, default=None, |
754 | + validator=validate_conjoined_attribute) |
755 | + date_triaged = DateTime( |
756 | + tzinfo=pytz.UTC, allow_none=True, default=None, |
757 | + validator=validate_conjoined_attribute) |
758 | + date_fix_committed = DateTime( |
759 | + tzinfo=pytz.UTC, allow_none=True, default=None, |
760 | + validator=validate_conjoined_attribute) |
761 | + date_fix_released = DateTime( |
762 | + tzinfo=pytz.UTC, allow_none=True, default=None, |
763 | + validator=validate_conjoined_attribute) |
764 | + date_left_closed = DateTime( |
765 | + tzinfo=pytz.UTC, allow_none=True, default=None, |
766 | + validator=validate_conjoined_attribute) |
767 | + |
768 | + owner_id = Int( |
769 | + name="owner", allow_none=False, validator=validate_public_person) |
770 | + owner = Reference(owner_id, "Person.id") |
771 | # The targetnamecache is a value that is only supposed to be set |
772 | # when a bugtask is created/modified or by the |
773 | # update-bugtask-targetnamecaches cronscript. For this reason it's |
774 | @@ -492,8 +505,8 @@ class BugTask(SQLBase): |
775 | # |
776 | # This field is actually incorrectly named, since it currently |
777 | # stores the bugtargetdisplayname. |
778 | - targetnamecache = StringCol( |
779 | - dbName='targetnamecache', notNull=False, default=None) |
780 | + targetnamecache = Unicode( |
781 | + name='targetnamecache', allow_none=True, default=None) |
782 | |
783 | @property |
784 | def status(self): |
785 | @@ -596,6 +609,9 @@ class BugTask(SQLBase): |
786 | "Cannot delete only bugtask affecting: %s." |
787 | % self.target.bugtargetdisplayname) |
788 | |
789 | + def destroySelf(self): |
790 | + Store.of(self).remove(self) |
791 | + |
792 | def delete(self, who=None): |
793 | """See `IBugTask`.""" |
794 | if who is None: |
795 | @@ -644,7 +660,7 @@ class BugTask(SQLBase): |
796 | matching_bugtasks, user, limit) |
797 | |
798 | # Make sure to exclude the bug of the current bugtask. |
799 | - return [bug for bug in matching_bugs if bug.id != self.bugID] |
800 | + return [bug for bug in matching_bugs if bug.id != self.bug_id] |
801 | |
802 | def subscribe(self, person, subscribed_by): |
803 | """See `IBugTask`.""" |
804 | @@ -716,7 +732,7 @@ class BugTask(SQLBase): |
805 | 'A product should always have a development series.') |
806 | devel_focusID = self.product.development_focusID |
807 | for bugtask in bugtasks: |
808 | - if bugtask.productseriesID == devel_focusID: |
809 | + if bugtask.productseries_id == devel_focusID: |
810 | conjoined_master = bugtask |
811 | break |
812 | |
813 | @@ -1089,8 +1105,8 @@ class BugTask(SQLBase): |
814 | # series have tasks on this bug. |
815 | if not Store.of(self).find( |
816 | BugTask, |
817 | - BugTask.bugID == self.bugID, |
818 | - BugTask.distroseriesID == DistroSeries.id, |
819 | + BugTask.bug_id == self.bug_id, |
820 | + BugTask.distroseries_id == DistroSeries.id, |
821 | DistroSeries.distributionID.is_in( |
822 | distro.id for distro in distros if distro), |
823 | ).is_empty(): |
824 | @@ -1324,7 +1340,7 @@ class BugTask(SQLBase): |
825 | return self.userHasBugSupervisorPrivilegesContext(self.target, user) |
826 | |
827 | def __repr__(self): |
828 | - return "<BugTask for bug %s on %r>" % (self.bugID, self.target) |
829 | + return "<BugTask for bug %s on %r>" % (self.bug_id, self.target) |
830 | |
831 | |
832 | @implementer(IBugTaskSet) |
833 | @@ -1346,9 +1362,8 @@ class BugTaskSet: |
834 | # XXX: JSK: 2007-12-19: This method should probably return |
835 | # None when task_id is not present. See: |
836 | # https://bugs.launchpad.net/launchpad/+bug/123592 |
837 | - try: |
838 | - bugtask = BugTask.get(task_id) |
839 | - except SQLObjectNotFound: |
840 | + bugtask = IStore(BugTask).find(BugTask, BugTask.id == task_id).one() |
841 | + if bugtask is None: |
842 | raise NotFoundError("BugTask with ID %s does not exist." % |
843 | str(task_id)) |
844 | return bugtask |
845 | @@ -1358,7 +1373,7 @@ class BugTaskSet: |
846 | # Import locally to avoid circular imports. |
847 | from lp.bugs.model.bug import Bug, BugTag |
848 | bugtask_ids = set(bugtask.id for bugtask in bugtasks) |
849 | - bug_ids = set(bugtask.bugID for bugtask in bugtasks) |
850 | + bug_ids = set(bugtask.bug_id for bugtask in bugtasks) |
851 | tags = IStore(BugTag).find( |
852 | (BugTag.tag, BugTask.id), |
853 | BugTask.bug == Bug.id, |
854 | @@ -1375,7 +1390,7 @@ class BugTaskSet: |
855 | # Avoid circular imports. |
856 | from lp.registry.interfaces.person import IPersonSet |
857 | people_ids = set( |
858 | - [bugtask.assigneeID for bugtask in bugtasks] + |
859 | + [bugtask.assignee_id for bugtask in bugtasks] + |
860 | [bugtask.bug.ownerID for bugtask in bugtasks]) |
861 | people = getUtility(IPersonSet).getPrecachedPersonsFromIDs(people_ids) |
862 | return dict( |
863 | @@ -1387,7 +1402,7 @@ class BugTaskSet: |
864 | from lp.bugs.model.bug import Bug |
865 | from lp.bugs.model.bugbranch import BugBranch |
866 | |
867 | - bug_ids = set(bugtask.bugID for bugtask in bugtasks) |
868 | + bug_ids = set(bugtask.bug_id for bugtask in bugtasks) |
869 | bug_ids_with_specifications = set( |
870 | int(id) for _, id in getUtility(IXRefSet).findFromMany( |
871 | [(u'bug', six.text_type(bug_id)) for bug_id in bug_ids], |
872 | @@ -1397,7 +1412,7 @@ class BugTaskSet: |
873 | # Badging looks up milestones too : eager load into the storm cache. |
874 | milestoneset = getUtility(IMilestoneSet) |
875 | # And trigger a load: |
876 | - milestone_ids = set(map(attrgetter('milestoneID'), bugtasks)) |
877 | + milestone_ids = set(map(attrgetter('milestone_id'), bugtasks)) |
878 | milestone_ids.discard(None) |
879 | if milestone_ids: |
880 | list(milestoneset.getByIds(milestone_ids)) |
881 | @@ -1415,7 +1430,7 @@ class BugTaskSet: |
882 | |
883 | badge_properties = {} |
884 | for bugtask in bugtasks: |
885 | - bug = bugs[bugtask.bugID] |
886 | + bug = bugs[bugtask.bug_id] |
887 | badge_properties[bugtask] = { |
888 | 'has_specification': |
889 | bug.id in bug_ids_with_specifications, |
890 | @@ -1433,7 +1448,7 @@ class BugTaskSet: |
891 | task_ids = [int(task_id) for task_id in task_ids] |
892 | # Query the database, returning the results in a dictionary: |
893 | if len(task_ids) > 0: |
894 | - tasks = BugTask.select('id in %s' % sqlvalues(task_ids)) |
895 | + tasks = IStore(BugTask).find(BugTask, BugTask.id.is_in(task_ids)) |
896 | return dict([(task.id, task) for task in tasks]) |
897 | else: |
898 | return {} |
899 | @@ -1486,12 +1501,12 @@ class BugTaskSet: |
900 | eager_load = None |
901 | else: |
902 | def eager_load(rows): |
903 | - load_related(Bug, rows, ['bugID']) |
904 | - load_related(Product, rows, ['productID']) |
905 | - load_related(ProductSeries, rows, ['productseriesID']) |
906 | - load_related(Distribution, rows, ['distributionID']) |
907 | - load_related(DistroSeries, rows, ['distroseriesID']) |
908 | - load_related(SourcePackageName, rows, ['sourcepackagenameID']) |
909 | + load_related(Bug, rows, ['bug_id']) |
910 | + load_related(Product, rows, ['product_id']) |
911 | + load_related(ProductSeries, rows, ['productseries_id']) |
912 | + load_related(Distribution, rows, ['distribution_id']) |
913 | + load_related(DistroSeries, rows, ['distroseries_id']) |
914 | + load_related(SourcePackageName, rows, ['sourcepackagename_id']) |
915 | return search_bugs(eager_load, (params,) + args) |
916 | |
917 | def searchBugIds(self, params): |
918 | @@ -1757,7 +1772,7 @@ class BugTaskSet: |
919 | ids = ids[:limit] |
920 | |
921 | return DecoratedResultSet( |
922 | - ids, lambda id: BugTask.get(id), |
923 | + ids, lambda id: getUtility(IBugTaskSet).get(id), |
924 | pre_iter_hook=lambda rows: load(BugTask, rows)) |
925 | |
926 | def _getTargetJoinAndClause(self, target): |
927 | @@ -1946,12 +1961,12 @@ class BugTaskSet: |
928 | # for the milestone vocabulary |
929 | for task in bugtasks: |
930 | task = removeSecurityProxy(task) |
931 | - distro_ids.add(task.distributionID) |
932 | - distro_series_ids.add(task.distroseriesID) |
933 | - product_ids.add(task.productID) |
934 | + distro_ids.add(task.distribution_id) |
935 | + distro_series_ids.add(task.distroseries_id) |
936 | + product_ids.add(task.product_id) |
937 | if task.productseries: |
938 | product_ids.add(task.productseries.productID) |
939 | - product_series_ids.add(task.productseriesID) |
940 | + product_series_ids.add(task.productseries_id) |
941 | |
942 | distro_ids.discard(None) |
943 | distro_series_ids.discard(None) |
944 | diff --git a/lib/lp/bugs/model/bugtasksearch.py b/lib/lp/bugs/model/bugtasksearch.py |
945 | index 15a489d..9ceb517 100644 |
946 | --- a/lib/lp/bugs/model/bugtasksearch.py |
947 | +++ b/lib/lp/bugs/model/bugtasksearch.py |
948 | @@ -957,9 +957,9 @@ def _build_exclude_conjoined_clause(milestone): |
949 | current_series = milestone.distribution.currentseries |
950 | join = LeftJoin( |
951 | ConjoinedMaster, |
952 | - And(ConjoinedMaster.bugID == BugTaskFlat.bug_id, |
953 | + And(ConjoinedMaster.bug_id == BugTaskFlat.bug_id, |
954 | BugTaskFlat.distribution_id == milestone.distribution.id, |
955 | - ConjoinedMaster.distroseriesID == current_series.id, |
956 | + ConjoinedMaster.distroseries_id == current_series.id, |
957 | Not(ConjoinedMaster._status.is_in( |
958 | BugTask._NON_CONJOINED_STATUSES)))) |
959 | join_tables = [(ConjoinedMaster, join)] |
960 | @@ -974,8 +974,8 @@ def _build_exclude_conjoined_clause(milestone): |
961 | LeftJoin(Product, BugTaskFlat.product_id == Product.id), |
962 | LeftJoin( |
963 | ConjoinedMaster, |
964 | - And(ConjoinedMaster.bugID == BugTaskFlat.bug_id, |
965 | - ConjoinedMaster.productseriesID |
966 | + And(ConjoinedMaster.bug_id == BugTaskFlat.bug_id, |
967 | + ConjoinedMaster.productseries_id |
968 | == Product.development_focusID, |
969 | Not(ConjoinedMaster._status.is_in( |
970 | BugTask._NON_CONJOINED_STATUSES)))), |
971 | @@ -987,9 +987,9 @@ def _build_exclude_conjoined_clause(milestone): |
972 | milestone.product.development_focusID) |
973 | join = LeftJoin( |
974 | ConjoinedMaster, |
975 | - And(ConjoinedMaster.bugID == BugTaskFlat.bug_id, |
976 | + And(ConjoinedMaster.bug_id == BugTaskFlat.bug_id, |
977 | BugTaskFlat.product_id == milestone.product.id, |
978 | - ConjoinedMaster.productseriesID == dev_focus_id, |
979 | + ConjoinedMaster.productseries_id == dev_focus_id, |
980 | Not(ConjoinedMaster._status.is_in( |
981 | BugTask._NON_CONJOINED_STATUSES)))) |
982 | join_tables = [(ConjoinedMaster, join)] |
983 | @@ -1054,9 +1054,9 @@ def _build_pending_bugwatch_elsewhere_clause(params): |
984 | # Restrict the target to params.upstream_target. |
985 | target = params.upstream_target |
986 | if IProduct.providedBy(target): |
987 | - target_col = RelatedBugTask.productID |
988 | + target_col = RelatedBugTask.product_id |
989 | elif IDistribution.providedBy(target): |
990 | - target_col = RelatedBugTask.distributionID |
991 | + target_col = RelatedBugTask.distribution_id |
992 | else: |
993 | raise AssertionError( |
994 | 'params.upstream_target must be a Distribution or ' |
995 | @@ -1070,10 +1070,10 @@ def _build_pending_bugwatch_elsewhere_clause(params): |
996 | extra_joins = [ |
997 | LeftJoin( |
998 | OtherDistribution, |
999 | - OtherDistribution.id == RelatedBugTask.distributionID), |
1000 | + OtherDistribution.id == RelatedBugTask.distribution_id), |
1001 | LeftJoin( |
1002 | OtherProduct, |
1003 | - OtherProduct.id == RelatedBugTask.productID), |
1004 | + OtherProduct.id == RelatedBugTask.product_id), |
1005 | ] |
1006 | target_clause = Or( |
1007 | OtherDistribution.official_malone == False, |
1008 | @@ -1091,9 +1091,9 @@ def _build_pending_bugwatch_elsewhere_clause(params): |
1009 | 1, |
1010 | tables=[RelatedBugTask] + extra_joins, |
1011 | where=And( |
1012 | - RelatedBugTask.bugID == BugTaskFlat.bug_id, |
1013 | + RelatedBugTask.bug_id == BugTaskFlat.bug_id, |
1014 | task_match_clause, |
1015 | - RelatedBugTask.bugwatchID == None, |
1016 | + RelatedBugTask.bugwatch_id == None, |
1017 | RelatedBugTask._status != BugTaskStatus.INVALID, |
1018 | target_clause))) |
1019 | |
1020 | @@ -1102,18 +1102,18 @@ def _build_no_upstream_bugtask_clause(params): |
1021 | """Return a clause for BugTaskSearchParams.has_no_upstream_bugtask.""" |
1022 | OtherBugTask = ClassAlias(BugTask) |
1023 | if params.upstream_target is None: |
1024 | - target = OtherBugTask.productID != None |
1025 | + target = OtherBugTask.product_id != None |
1026 | elif IProduct.providedBy(params.upstream_target): |
1027 | - target = OtherBugTask.productID == params.upstream_target.id |
1028 | + target = OtherBugTask.product_id == params.upstream_target.id |
1029 | elif IDistribution.providedBy(params.upstream_target): |
1030 | - target = OtherBugTask.distributionID == params.upstream_target.id |
1031 | + target = OtherBugTask.distribution_id == params.upstream_target.id |
1032 | else: |
1033 | raise AssertionError( |
1034 | 'params.upstream_target must be a Distribution or ' |
1035 | 'a Product') |
1036 | return Not(Exists(Select( |
1037 | 1, tables=[OtherBugTask], |
1038 | - where=And(OtherBugTask.bugID == BugTaskFlat.bug_id, target)))) |
1039 | + where=And(OtherBugTask.bug_id == BugTaskFlat.bug_id, target)))) |
1040 | |
1041 | |
1042 | def _build_open_or_resolved_upstream_clause(params, |
1043 | @@ -1128,12 +1128,12 @@ def _build_open_or_resolved_upstream_clause(params, |
1044 | RelatedBugTask._status, any(*statuses_for_upstream_tasks)) |
1045 | if params.upstream_target is None: |
1046 | watch_target_clause = True |
1047 | - no_watch_target_clause = RelatedBugTask.productID != None |
1048 | + no_watch_target_clause = RelatedBugTask.product_id != None |
1049 | else: |
1050 | if IProduct.providedBy(params.upstream_target): |
1051 | - target_col = RelatedBugTask.productID |
1052 | + target_col = RelatedBugTask.product_id |
1053 | elif IDistribution.providedBy(params.upstream_target): |
1054 | - target_col = RelatedBugTask.distributionID |
1055 | + target_col = RelatedBugTask.distribution_id |
1056 | else: |
1057 | raise AssertionError( |
1058 | 'params.upstream_target must be a Distribution or ' |
1059 | @@ -1144,14 +1144,14 @@ def _build_open_or_resolved_upstream_clause(params, |
1060 | 1, |
1061 | tables=[RelatedBugTask], |
1062 | where=And( |
1063 | - RelatedBugTask.bugID == BugTaskFlat.bug_id, |
1064 | + RelatedBugTask.bug_id == BugTaskFlat.bug_id, |
1065 | RelatedBugTask.id != BugTaskFlat.bugtask_id, |
1066 | Or( |
1067 | And(watch_target_clause, |
1068 | - RelatedBugTask.bugwatchID != None, |
1069 | + RelatedBugTask.bugwatch_id != None, |
1070 | watch_status_clause), |
1071 | And(no_watch_target_clause, |
1072 | - RelatedBugTask.bugwatchID == None, |
1073 | + RelatedBugTask.bugwatch_id == None, |
1074 | no_watch_status_clause))))) |
1075 | |
1076 | |
1077 | diff --git a/lib/lp/bugs/model/cve.py b/lib/lp/bugs/model/cve.py |
1078 | index 05b5fa8..553bff3 100644 |
1079 | --- a/lib/lp/bugs/model/cve.py |
1080 | +++ b/lib/lp/bugs/model/cve.py |
1081 | @@ -203,7 +203,7 @@ class CveSet: |
1082 | |
1083 | def getBugCvesForBugTasks(self, bugtasks, cve_mapper=None): |
1084 | """See ICveSet.""" |
1085 | - bugs = bulk.load_related(Bug, bugtasks, ('bugID', )) |
1086 | + bugs = bulk.load_related(Bug, bugtasks, ('bug_id', )) |
1087 | if len(bugs) == 0: |
1088 | return [] |
1089 | store = Store.of(bugtasks[0]) |
1090 | diff --git a/lib/lp/bugs/model/personsubscriptioninfo.py b/lib/lp/bugs/model/personsubscriptioninfo.py |
1091 | index 3767e6b..1d82c22 100644 |
1092 | --- a/lib/lp/bugs/model/personsubscriptioninfo.py |
1093 | +++ b/lib/lp/bugs/model/personsubscriptioninfo.py |
1094 | @@ -1,4 +1,4 @@ |
1095 | -# Copyright 2011-2012 Canonical Ltd. This software is licensed under the |
1096 | +# Copyright 2011-2020 Canonical Ltd. This software is licensed under the |
1097 | # GNU Affero General Public License version 3 (see the file LICENSE). |
1098 | |
1099 | __metaclass__ = type |
1100 | @@ -184,8 +184,8 @@ class PersonSubscriptions(object): |
1101 | list(getUtility(IPersonSet).getPrecachedPersonsFromIDs( |
1102 | [bug.ownerID for bug in bugs])) |
1103 | all_tasks = [task for task in bug.bugtasks for bug in bugs] |
1104 | - load_related(Product, all_tasks, ['productID']) |
1105 | - load_related(Distribution, all_tasks, ['distributionID']) |
1106 | + load_related(Product, all_tasks, ['product_id']) |
1107 | + load_related(Distribution, all_tasks, ['distribution_id']) |
1108 | for bug in bugs: |
1109 | # indicate the reporter and bug_supervisor |
1110 | duplicates.annotateReporter(bug, bug.owner) |
1111 | diff --git a/lib/lp/bugs/scripts/bugsummaryrebuild.py b/lib/lp/bugs/scripts/bugsummaryrebuild.py |
1112 | index 3537a98..ab89e7b 100644 |
1113 | --- a/lib/lp/bugs/scripts/bugsummaryrebuild.py |
1114 | +++ b/lib/lp/bugs/scripts/bugsummaryrebuild.py |
1115 | @@ -1,4 +1,4 @@ |
1116 | -# Copyright 2012-2018 Canonical Ltd. This software is licensed under the |
1117 | +# Copyright 2012-2020 Canonical Ltd. This software is licensed under the |
1118 | # GNU Affero General Public License version 3 (see the file LICENSE). |
1119 | |
1120 | __metaclass__ = type |
1121 | @@ -69,9 +69,9 @@ def get_bugsummary_targets(): |
1122 | def get_bugtask_targets(): |
1123 | """Get the current set of targets represented in BugTask.""" |
1124 | new_targets = set(IStore(BugTask).find( |
1125 | - (BugTask.productID, BugTask.productseriesID, |
1126 | - BugTask.distributionID, BugTask.distroseriesID, |
1127 | - BugTask.sourcepackagenameID)).config(distinct=True)) |
1128 | + (BugTask.product_id, BugTask.productseries_id, |
1129 | + BugTask.distribution_id, BugTask.distroseries_id, |
1130 | + BugTask.sourcepackagename_id)).config(distinct=True)) |
1131 | # BugSummary counts package tasks in the packageless totals, so |
1132 | # ensure that there's also a packageless total for each distro(series). |
1133 | new_targets.update(set( |
1134 | diff --git a/lib/lp/bugs/scripts/bugtasktargetnamecaches.py b/lib/lp/bugs/scripts/bugtasktargetnamecaches.py |
1135 | index 429ff49..5e4cb1e 100644 |
1136 | --- a/lib/lp/bugs/scripts/bugtasktargetnamecaches.py |
1137 | +++ b/lib/lp/bugs/scripts/bugtasktargetnamecaches.py |
1138 | @@ -1,4 +1,4 @@ |
1139 | -# Copyright 2009 Canonical Ltd. This software is licensed under the |
1140 | +# Copyright 2009-2020 Canonical Ltd. This software is licensed under the |
1141 | # GNU Affero General Public License version 3 (see the file LICENSE). |
1142 | |
1143 | """A utility module for the update-bugtasktargetnamecaches.py cronscript.""" |
1144 | @@ -32,8 +32,8 @@ from lp.services.looptuner import ( |
1145 | # These two tuples must be in the same order. They specify the ID |
1146 | # columns to get from BugTask, and the classes that they correspond to. |
1147 | target_columns = ( |
1148 | - BugTask.productID, BugTask.productseriesID, BugTask.distributionID, |
1149 | - BugTask.distroseriesID, BugTask.sourcepackagenameID, |
1150 | + BugTask.product_id, BugTask.productseries_id, BugTask.distribution_id, |
1151 | + BugTask.distroseries_id, BugTask.sourcepackagename_id, |
1152 | BugTask.targetnamecache) |
1153 | target_classes = ( |
1154 | Product, ProductSeries, Distribution, DistroSeries, SourcePackageName) |
1155 | diff --git a/lib/lp/code/model/branchcollection.py b/lib/lp/code/model/branchcollection.py |
1156 | index f07416a..0ab5fd8 100644 |
1157 | --- a/lib/lp/code/model/branchcollection.py |
1158 | +++ b/lib/lp/code/model/branchcollection.py |
1159 | @@ -550,7 +550,7 @@ class GenericBranchCollection: |
1160 | store = IStore(BugBranch) |
1161 | rs = store.using( |
1162 | BugBranch, |
1163 | - Join(BugTask, BugTask.bugID == BugBranch.bug_id), |
1164 | + Join(BugTask, BugTask.bug_id == BugBranch.bug_id), |
1165 | ).find( |
1166 | (BugTask, BugBranch), |
1167 | BugBranch.bug_id.is_in(bug_ids), |
1168 | diff --git a/lib/lp/registry/browser/milestone.py b/lib/lp/registry/browser/milestone.py |
1169 | index 936967a..263bd8a 100644 |
1170 | --- a/lib/lp/registry/browser/milestone.py |
1171 | +++ b/lib/lp/registry/browser/milestone.py |
1172 | @@ -1,4 +1,4 @@ |
1173 | -# Copyright 2009-2018 Canonical Ltd. This software is licensed under the |
1174 | +# Copyright 2009-2020 Canonical Ltd. This software is licensed under the |
1175 | # GNU Affero General Public License version 3 (see the file LICENSE). |
1176 | |
1177 | """Milestone views.""" |
1178 | @@ -234,7 +234,7 @@ class MilestoneViewMixin(object): |
1179 | # We want the assignees loaded as we show them in the milestone home |
1180 | # page. |
1181 | list(getUtility(IPersonSet).getPrecachedPersonsFromIDs( |
1182 | - [bug.assigneeID for bug in non_conjoined_slaves], |
1183 | + [bug.assignee_id for bug in non_conjoined_slaves], |
1184 | need_validity=True)) |
1185 | return non_conjoined_slaves |
1186 | |
1187 | diff --git a/lib/lp/registry/model/distribution.py b/lib/lp/registry/model/distribution.py |
1188 | index b9baba7..0f07325 100644 |
1189 | --- a/lib/lp/registry/model/distribution.py |
1190 | +++ b/lib/lp/registry/model/distribution.py |
1191 | @@ -1473,7 +1473,7 @@ class Distribution(SQLBase, BugTargetBase, MakesAnnouncements, |
1192 | distributionID = self.id |
1193 | |
1194 | def weight_function(bugtask): |
1195 | - if bugtask.distributionID == distributionID: |
1196 | + if bugtask.distribution_id == distributionID: |
1197 | return OrderedBugTask(1, bugtask.id, bugtask) |
1198 | return OrderedBugTask(2, bugtask.id, bugtask) |
1199 | |
1200 | diff --git a/lib/lp/registry/model/distroseries.py b/lib/lp/registry/model/distroseries.py |
1201 | index 9f0fc8c..2811a42 100644 |
1202 | --- a/lib/lp/registry/model/distroseries.py |
1203 | +++ b/lib/lp/registry/model/distroseries.py |
1204 | @@ -1454,9 +1454,9 @@ class DistroSeries(SQLBase, BugTargetBase, HasSpecificationsMixin, |
1205 | distributionID = self.distributionID |
1206 | |
1207 | def weight_function(bugtask): |
1208 | - if bugtask.distroseriesID == seriesID: |
1209 | + if bugtask.distroseries_id == seriesID: |
1210 | return OrderedBugTask(1, bugtask.id, bugtask) |
1211 | - elif bugtask.distributionID == distributionID: |
1212 | + elif bugtask.distribution_id == distributionID: |
1213 | return OrderedBugTask(2, bugtask.id, bugtask) |
1214 | else: |
1215 | return OrderedBugTask(3, bugtask.id, bugtask) |
1216 | diff --git a/lib/lp/registry/model/person.py b/lib/lp/registry/model/person.py |
1217 | index 6f96764..197fd84 100644 |
1218 | --- a/lib/lp/registry/model/person.py |
1219 | +++ b/lib/lp/registry/model/person.py |
1220 | @@ -1477,8 +1477,8 @@ class Person( |
1221 | tasks = list(getUtility(IBugTaskSet).search(search_params)) |
1222 | # Eager load the things we need that are not already eager loaded by |
1223 | # BugTaskSet.search(). |
1224 | - bulk.load_related(Person, tasks, ['assigneeID']) |
1225 | - bulk.load_related(Milestone, tasks, ['milestoneID']) |
1226 | + bulk.load_related(Person, tasks, ['assignee_id']) |
1227 | + bulk.load_related(Milestone, tasks, ['milestone_id']) |
1228 | |
1229 | for task in tasks: |
1230 | # We skip masters (instead of slaves) from conjoined relationships |
1231 | @@ -1821,7 +1821,7 @@ class Person( |
1232 | Bug.id, |
1233 | tables=( |
1234 | Bug, |
1235 | - Join(BugTask, BugTask.bugID == Bug.id)), |
1236 | + Join(BugTask, BugTask.bug_id == Bug.id)), |
1237 | where=And(Bug.information_type.is_in( |
1238 | PRIVATE_INFORMATION_TYPES), |
1239 | BugTask.assignee == self.id)), |
1240 | diff --git a/lib/lp/registry/model/product.py b/lib/lp/registry/model/product.py |
1241 | index ae43ede..07d652e 100644 |
1242 | --- a/lib/lp/registry/model/product.py |
1243 | +++ b/lib/lp/registry/model/product.py |
1244 | @@ -1470,7 +1470,7 @@ class Product(SQLBase, BugTargetBase, MakesAnnouncements, |
1245 | productID = self.id |
1246 | |
1247 | def weight_function(bugtask): |
1248 | - if bugtask.productID == productID: |
1249 | + if bugtask.product_id == productID: |
1250 | return OrderedBugTask(1, bugtask.id, bugtask) |
1251 | return OrderedBugTask(2, bugtask.id, bugtask) |
1252 | |
1253 | diff --git a/lib/lp/registry/model/productseries.py b/lib/lp/registry/model/productseries.py |
1254 | index 416577e..3459214 100644 |
1255 | --- a/lib/lp/registry/model/productseries.py |
1256 | +++ b/lib/lp/registry/model/productseries.py |
1257 | @@ -1,4 +1,4 @@ |
1258 | -# Copyright 2009-2013 Canonical Ltd. This software is licensed under the |
1259 | +# Copyright 2009-2020 Canonical Ltd. This software is licensed under the |
1260 | # GNU Affero General Public License version 3 (see the file LICENSE). |
1261 | |
1262 | """Models for `IProductSeries`.""" |
1263 | @@ -575,9 +575,9 @@ class ProductSeries(SQLBase, BugTargetBase, HasMilestonesMixin, |
1264 | productID = self.productID |
1265 | |
1266 | def weight_function(bugtask): |
1267 | - if bugtask.productseriesID == seriesID: |
1268 | + if bugtask.productseries_id == seriesID: |
1269 | return OrderedBugTask(1, bugtask.id, bugtask) |
1270 | - elif bugtask.productID == productID: |
1271 | + elif bugtask.product_id == productID: |
1272 | return OrderedBugTask(2, bugtask.id, bugtask) |
1273 | else: |
1274 | return OrderedBugTask(3, bugtask.id, bugtask) |
1275 | diff --git a/lib/lp/registry/model/sourcepackage.py b/lib/lp/registry/model/sourcepackage.py |
1276 | index 9e40417..61b66e4 100644 |
1277 | --- a/lib/lp/registry/model/sourcepackage.py |
1278 | +++ b/lib/lp/registry/model/sourcepackage.py |
1279 | @@ -1,4 +1,4 @@ |
1280 | -# Copyright 2009-2015 Canonical Ltd. This software is licensed under the |
1281 | +# Copyright 2009-2020 Canonical Ltd. This software is licensed under the |
1282 | # GNU Affero General Public License version 3 (see the file LICENSE). |
1283 | |
1284 | """Database classes that implement SourcePackage items.""" |
1285 | @@ -774,14 +774,14 @@ class SourcePackage(BugTargetBase, HasCodeImportsMixin, |
1286 | distributionID = self.distroseries.distributionID |
1287 | |
1288 | def weight_function(bugtask): |
1289 | - if bugtask.sourcepackagenameID == sourcepackagenameID: |
1290 | - if bugtask.distroseriesID == seriesID: |
1291 | + if bugtask.sourcepackagename_id == sourcepackagenameID: |
1292 | + if bugtask.distroseries_id == seriesID: |
1293 | return OrderedBugTask(1, bugtask.id, bugtask) |
1294 | - elif bugtask.distributionID == distributionID: |
1295 | + elif bugtask.distribution_id == distributionID: |
1296 | return OrderedBugTask(2, bugtask.id, bugtask) |
1297 | - elif bugtask.distroseriesID == seriesID: |
1298 | + elif bugtask.distroseries_id == seriesID: |
1299 | return OrderedBugTask(3, bugtask.id, bugtask) |
1300 | - elif bugtask.distributionID == distributionID: |
1301 | + elif bugtask.distribution_id == distributionID: |
1302 | return OrderedBugTask(4, bugtask.id, bugtask) |
1303 | # Catch the default case, and where there is a task for the same |
1304 | # sourcepackage on a different distro. |
1305 | diff --git a/lib/lp/registry/scripts/closeaccount.py b/lib/lp/registry/scripts/closeaccount.py |
1306 | index fba057f..9949b95 100644 |
1307 | --- a/lib/lp/registry/scripts/closeaccount.py |
1308 | +++ b/lib/lp/registry/scripts/closeaccount.py |
1309 | @@ -235,7 +235,7 @@ def close_account(username, log): |
1310 | |
1311 | # Reassign their bugs |
1312 | table_notification('BugTask') |
1313 | - store.find(BugTask, BugTask.assigneeID == person.id).set(assigneeID=None) |
1314 | + store.find(BugTask, BugTask.assignee_id == person.id).set(assignee_id=None) |
1315 | |
1316 | # Reassign questions assigned to the user, and close all their questions |
1317 | # in non-final states since nobody else can. |
The changes are all related to BugTask refactoring. Mostly:
- Using StormBase instead of SQLBase class;
- Renaming the foreign key ID attributes to match newer pattern ("foreignkey_id", instead of "foreignKeyID"). This change itself is responsible for most of the lines changed, since there were queries across the code base using BugTask attributes (like BugTask.bugID, BugTask.assigneeID, etc);
- Refactoring of the `validate_ conjoined_ attribute` method to keep track of the changed attributes separately, on `BugTask. passthrough_ attrs` dict; currently, we are setting a `PassthroughValue` object wrapper in some attributes, but Storm doesn't allow it (an `Int` attribute only accepts ints, for example).
- Replacing `BugTask.get(id)` with `getUtility( BugTaskSet) .get(id) `;
- Changing `BugTask. select` /`BugTask. selectBy` with `store. find(BugTask, ...)`