Merge lp:~gary/launchpad/bug723999-2d into lp:launchpad
- bug723999-2d
- Merge into devel
Status: | Merged |
---|---|
Approved by: | Gary Poster |
Approved revision: | no longer in the source branch. |
Merged at revision: | 12548 |
Proposed branch: | lp:~gary/launchpad/bug723999-2d |
Merge into: | lp:launchpad |
Prerequisite: | lp:~gary/launchpad/bug723999-2c |
Diff against target: |
765 lines (+271/-317) 10 files modified
lib/lp/bugs/browser/bugsubscription.py (+1/-4) lib/lp/bugs/configure.zcml (+1/-0) lib/lp/bugs/interfaces/bug.py (+6/-0) lib/lp/bugs/interfaces/bugtask.py (+0/-12) lib/lp/bugs/model/bug.py (+4/-0) lib/lp/bugs/model/bugtask.py (+1/-23) lib/lp/bugs/model/structuralsubscription.py (+0/-28) lib/lp/bugs/model/tests/test_bug.py (+34/-0) lib/lp/bugs/model/tests/test_bugtask.py (+2/-248) lib/lp/bugs/tests/test_structuralsubscription.py (+222/-2) |
To merge this branch: | bzr merge lp:~gary/launchpad/bug723999-2d |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Benji York (community) | code | Approve | |
Review via email: mp+52478@code.launchpad.net |
Commit message
[r=benji][no-qa] Clean up structural subcription code to eliminate duplicated code and remove code middle-men that emerged after my work on bug 723999.
Description of the change
This is the final clean-up branch from my work on bug723999, building most recently on ~gary/launchpad/bug723999-2c.
This branch is all about removing three methods on the bugtaskset utility (lib/lp/
- _getStructuralS
- At the end of the 2c branch, getStructuralSu
- getAllStructura
That's pretty much it.
Thank you!
Gary
Preview Diff
1 | === modified file 'lib/lp/bugs/browser/bugsubscription.py' |
2 | --- lib/lp/bugs/browser/bugsubscription.py 2011-03-04 11:00:04 +0000 |
3 | +++ lib/lp/bugs/browser/bugsubscription.py 2011-03-07 22:10:38 +0000 |
4 | @@ -19,7 +19,6 @@ |
5 | from zope import formlib |
6 | from zope.app.form import CustomWidgetFactory |
7 | from zope.app.form.browser.itemswidgets import RadioWidget |
8 | -from zope.component import getUtility |
9 | from zope.schema import Choice |
10 | from zope.schema.vocabulary import ( |
11 | SimpleTerm, |
12 | @@ -41,7 +40,6 @@ |
13 | from lp.bugs.browser.bug import BugViewMixin |
14 | from lp.bugs.enum import BugNotificationLevel, HIDDEN_BUG_NOTIFICATION_LEVELS |
15 | from lp.bugs.interfaces.bugsubscription import IBugSubscription |
16 | -from lp.bugs.interfaces.bugtask import IBugTaskSet |
17 | from lp.services import features |
18 | from lp.services.propertycache import cachedproperty |
19 | |
20 | @@ -559,5 +557,4 @@ |
21 | |
22 | @property |
23 | def structural_subscriptions(self): |
24 | - return getUtility(IBugTaskSet).getAllStructuralSubscriptions( |
25 | - self.context.bug.bugtasks, self.user) |
26 | + return self.context.bug.getStructuralSubscriptionsForPerson(self.user) |
27 | |
28 | === modified file 'lib/lp/bugs/configure.zcml' |
29 | --- lib/lp/bugs/configure.zcml 2011-03-07 17:54:44 +0000 |
30 | +++ lib/lp/bugs/configure.zcml 2011-03-07 22:10:38 +0000 |
31 | @@ -747,6 +747,7 @@ |
32 | getSubscriptionsFromDuplicates |
33 | getSubscribersForPerson |
34 | getSubscriptionForPerson |
35 | + getStructuralSubscriptionsForPerson |
36 | getSubscriptionInfo |
37 | indexed_messages |
38 | _indexed_messages |
39 | |
40 | === modified file 'lib/lp/bugs/interfaces/bug.py' |
41 | --- lib/lp/bugs/interfaces/bug.py 2011-03-07 22:10:32 +0000 |
42 | +++ lib/lp/bugs/interfaces/bug.py 2011-03-07 22:10:38 +0000 |
43 | @@ -533,6 +533,12 @@ |
44 | If no such `BugSubscription` exists, return None. |
45 | """ |
46 | |
47 | + def getStructuralSubscriptionsForPerson(person): |
48 | + """Return the `StructuralSubscription`s for a `Person` to this `Bug`. |
49 | + |
50 | + This disregards filters. |
51 | + """ |
52 | + |
53 | def getSubscriptionInfo(level): |
54 | """Return a `BugSubscriptionInfo` at the given `level`. |
55 | |
56 | |
57 | === modified file 'lib/lp/bugs/interfaces/bugtask.py' |
58 | --- lib/lp/bugs/interfaces/bugtask.py 2011-03-03 18:58:49 +0000 |
59 | +++ lib/lp/bugs/interfaces/bugtask.py 2011-03-07 22:10:38 +0000 |
60 | @@ -1597,18 +1597,6 @@ |
61 | def getOpenBugTasksPerProduct(user, products): |
62 | """Return open bugtask count for multiple products.""" |
63 | |
64 | - def getAllStructuralSubscriptions(bugtasks): |
65 | - """Return all potential structural subscriptions for the bugtasks. |
66 | - |
67 | - This method ignores subscription filters. |
68 | - """ |
69 | - |
70 | - def getStructuralSubscribers(bugtasks, recipients=None, level=None): |
71 | - """Return `IPerson`s subscribed to the given bug tasks. |
72 | - |
73 | - This takes into account bug subscription filters. |
74 | - """ |
75 | - |
76 | def getPrecachedNonConjoinedBugTasks(user, milestone): |
77 | """List of non-conjoined bugtasks targeted to the milestone. |
78 | |
79 | |
80 | === modified file 'lib/lp/bugs/model/bug.py' |
81 | --- lib/lp/bugs/model/bug.py 2011-03-07 22:10:32 +0000 |
82 | +++ lib/lp/bugs/model/bug.py 2011-03-07 22:10:38 +0000 |
83 | @@ -982,6 +982,10 @@ |
84 | BugSubscription.person == person, |
85 | BugSubscription.bug == self).one() |
86 | |
87 | + def getStructuralSubscriptionsForPerson(self, person): |
88 | + """See `IBug`.""" |
89 | + return get_all_structural_subscriptions(self.bugtasks, person) |
90 | + |
91 | def getAlsoNotifiedSubscribers(self, recipients=None, level=None): |
92 | """See `IBug`. |
93 | |
94 | |
95 | === modified file 'lib/lp/bugs/model/bugtask.py' |
96 | --- lib/lp/bugs/model/bugtask.py 2011-03-07 07:27:56 +0000 |
97 | +++ lib/lp/bugs/model/bugtask.py 2011-03-07 22:10:38 +0000 |
98 | @@ -131,12 +131,7 @@ |
99 | ) |
100 | from lp.bugs.model.bugnomination import BugNomination |
101 | from lp.bugs.model.bugsubscription import BugSubscription |
102 | -from lp.bugs.model.structuralsubscription import ( |
103 | - get_all_structural_subscriptions, |
104 | - get_structural_subscribers_for_bugtasks, |
105 | - get_structural_subscription_targets, |
106 | - StructuralSubscription, |
107 | - ) |
108 | +from lp.bugs.model.structuralsubscription import StructuralSubscription |
109 | from lp.registry.interfaces.distribution import ( |
110 | IDistribution, |
111 | IDistributionSet, |
112 | @@ -3107,20 +3102,3 @@ |
113 | counts.append(package_counts) |
114 | |
115 | return counts |
116 | - |
117 | - def _getStructuralSubscriptionTargets(self, bugtasks): |
118 | - """Return (bugtask, target) pairs for each target of the bugtasks. |
119 | - |
120 | - Each bugtask may be responsible theoretically for 0 or more targets. |
121 | - In practice, each generates one, two or three. |
122 | - """ |
123 | - return get_structural_subscription_targets(bugtasks) |
124 | - |
125 | - def getAllStructuralSubscriptions(self, bugtasks, recipient=None): |
126 | - """See `IBugTaskSet`.""" |
127 | - return get_all_structural_subscriptions(bugtasks, recipient) |
128 | - |
129 | - def getStructuralSubscribers(self, bugtasks, recipients=None, level=None): |
130 | - """See `IBugTaskSet`.""" |
131 | - return get_structural_subscribers_for_bugtasks( |
132 | - bugtasks, recipients, level) |
133 | |
134 | === modified file 'lib/lp/bugs/model/structuralsubscription.py' |
135 | --- lib/lp/bugs/model/structuralsubscription.py 2011-03-07 22:10:32 +0000 |
136 | +++ lib/lp/bugs/model/structuralsubscription.py 2011-03-07 22:10:38 +0000 |
137 | @@ -5,7 +5,6 @@ |
138 | __all__ = [ |
139 | 'get_all_structural_subscriptions', |
140 | 'get_structural_subscribers', |
141 | - 'get_structural_subscribers_for_bugtasks', |
142 | 'get_structural_subscription_targets', |
143 | 'StructuralSubscription', |
144 | 'StructuralSubscriptionTargetMixin', |
145 | @@ -608,33 +607,6 @@ |
146 | return subscribers |
147 | |
148 | |
149 | -def get_structural_subscribers_for_bugtasks(bugtasks, |
150 | - recipients=None, |
151 | - level=None): |
152 | - """Return subscribers for structural filters for the bugtasks at "level". |
153 | - |
154 | - :param bugtasks: an iterable of bugtasks. Should be a single bugtask, or |
155 | - all of the bugtasks from one bug. |
156 | - :param recipients: a BugNotificationRecipients object or None. |
157 | - Populates if given. |
158 | - :param level: a level from lp.bugs.enum.BugNotificationLevel. |
159 | - |
160 | - Excludes structural subscriptions for people who are directly subscribed |
161 | - to the bug.""" |
162 | - bugtasks = list(bugtasks) |
163 | - if not bugtasks: |
164 | - return EmptyResultSet() |
165 | - if len(bugtasks) == 1: |
166 | - target = bugtasks[0] |
167 | - else: |
168 | - target = bugtasks[0].bug |
169 | - if target.bugtasks != bugtasks: |
170 | - raise NotImplementedError( |
171 | - 'bugtasks must be one, or the full set of bugtasks from one ' |
172 | - 'bug') |
173 | - return get_structural_subscribers(target, recipients, level) |
174 | - |
175 | - |
176 | class ArrayAgg(NamedFunc): |
177 | "Aggregate values (within a GROUP BY) into an array." |
178 | __slots__ = () |
179 | |
180 | === modified file 'lib/lp/bugs/model/tests/test_bug.py' |
181 | --- lib/lp/bugs/model/tests/test_bug.py 2011-02-18 12:51:40 +0000 |
182 | +++ lib/lp/bugs/model/tests/test_bug.py 2011-03-07 22:10:38 +0000 |
183 | @@ -12,6 +12,7 @@ |
184 | person_logged_in, |
185 | TestCaseWithFactory, |
186 | ) |
187 | +from lp.testing.factory import is_security_proxied_or_harmless |
188 | |
189 | |
190 | class TestBug(TestCaseWithFactory): |
191 | @@ -247,3 +248,36 @@ |
192 | with person_logged_in(bug.owner): |
193 | info = bug.getSubscriptionInfo(BugNotificationLevel.METADATA) |
194 | self.assertEqual(BugNotificationLevel.METADATA, info.level) |
195 | + |
196 | + |
197 | +class TestGetStructuralSubscriptionsForPerson(TestCaseWithFactory): |
198 | + |
199 | + layer = DatabaseFunctionalLayer |
200 | + |
201 | + def getStructuralSubscriptionsForPerson(self, bug, recipient): |
202 | + # Call bug.getStructuralSubscriptionsForPerson() and check that the |
203 | + # result is security proxied. |
204 | + result = bug.getStructuralSubscriptionsForPerson(recipient) |
205 | + self.assertTrue(is_security_proxied_or_harmless(result)) |
206 | + return result |
207 | + |
208 | + def setUp(self): |
209 | + super(TestGetStructuralSubscriptionsForPerson, self).setUp() |
210 | + self.subscriber = self.factory.makePerson() |
211 | + login_person(self.subscriber) |
212 | + self.product = self.factory.makeProduct() |
213 | + self.milestone = self.factory.makeMilestone(product=self.product) |
214 | + self.bug = self.factory.makeBug( |
215 | + product=self.product, milestone=self.milestone) |
216 | + |
217 | + def test_no_subscriptions(self): |
218 | + subscriptions = self.getStructuralSubscriptionsForPerson( |
219 | + self.bug, self.subscriber) |
220 | + self.assertEqual([], list(subscriptions)) |
221 | + |
222 | + def test_one_subscription(self): |
223 | + sub = self.product.addBugSubscription( |
224 | + self.subscriber, self.subscriber) |
225 | + subscriptions = self.getStructuralSubscriptionsForPerson( |
226 | + self.bug, self.subscriber) |
227 | + self.assertEqual([sub], list(subscriptions)) |
228 | |
229 | === modified file 'lib/lp/bugs/model/tests/test_bugtask.py' |
230 | --- lib/lp/bugs/model/tests/test_bugtask.py 2011-03-03 02:14:14 +0000 |
231 | +++ lib/lp/bugs/model/tests/test_bugtask.py 2011-03-07 22:10:38 +0000 |
232 | @@ -8,17 +8,9 @@ |
233 | import unittest |
234 | |
235 | from lazr.lifecycle.snapshot import Snapshot |
236 | -from storm.store import ( |
237 | - EmptyResultSet, |
238 | - ResultSet, |
239 | - ) |
240 | -from testtools.matchers import ( |
241 | - Equals, |
242 | - StartsWith, |
243 | - ) |
244 | +from testtools.matchers import Equals |
245 | from zope.component import getUtility |
246 | from zope.interface import providedBy |
247 | -from zope.security.proxy import removeSecurityProxy |
248 | |
249 | from canonical.database.sqlbase import flush_database_updates |
250 | from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities |
251 | @@ -32,7 +24,6 @@ |
252 | LaunchpadZopelessLayer, |
253 | ) |
254 | from lp.app.enums import ServiceUsage |
255 | -from lp.bugs.enum import BugNotificationLevel |
256 | from lp.bugs.interfaces.bug import IBugSet |
257 | from lp.bugs.interfaces.bugtarget import IBugTarget |
258 | from lp.bugs.interfaces.bugtask import ( |
259 | @@ -45,7 +36,6 @@ |
260 | UNRESOLVED_BUGTASK_STATUSES, |
261 | ) |
262 | from lp.bugs.interfaces.bugwatch import IBugWatchSet |
263 | -from lp.bugs.mail.bugnotificationrecipients import BugNotificationRecipients |
264 | from lp.bugs.model.bugtask import build_tag_search_clause |
265 | from lp.bugs.tests.bug import ( |
266 | create_old_bug, |
267 | @@ -72,10 +62,7 @@ |
268 | TestCase, |
269 | TestCaseWithFactory, |
270 | ) |
271 | -from lp.testing.factory import ( |
272 | - is_security_proxied_or_harmless, |
273 | - LaunchpadObjectFactory, |
274 | - ) |
275 | +from lp.testing.factory import LaunchpadObjectFactory |
276 | from lp.testing.matchers import HasQueryCount |
277 | |
278 | |
279 | @@ -1346,239 +1333,6 @@ |
280 | self.assertNotIn(BugTaskStatus.UNKNOWN, UNRESOLVED_BUGTASK_STATUSES) |
281 | |
282 | |
283 | -class TestGetStructuralSubscriptionTargets(TestCaseWithFactory): |
284 | - # This tests a private method because it has some subtleties that are |
285 | - # nice to test in isolation. |
286 | - |
287 | - layer = DatabaseFunctionalLayer |
288 | - |
289 | - def getStructuralSubscriptionTargets(self, bugtasks): |
290 | - unwrapped = removeSecurityProxy(getUtility(IBugTaskSet)) |
291 | - return unwrapped._getStructuralSubscriptionTargets(bugtasks) |
292 | - |
293 | - def test_product_target(self): |
294 | - product = self.factory.makeProduct() |
295 | - bug = self.factory.makeBug(product=product) |
296 | - bugtask = bug.bugtasks[0] |
297 | - result = self.getStructuralSubscriptionTargets(bug.bugtasks) |
298 | - self.assertEqual(list(result), [(bugtask, product)]) |
299 | - |
300 | - def test_milestone_target(self): |
301 | - actor = self.factory.makePerson() |
302 | - login_person(actor) |
303 | - product = self.factory.makeProduct() |
304 | - milestone = self.factory.makeMilestone(product=product) |
305 | - bug = self.factory.makeBug(product=product, milestone=milestone) |
306 | - bugtask = bug.bugtasks[0] |
307 | - result = self.getStructuralSubscriptionTargets(bug.bugtasks) |
308 | - self.assertEqual(set(result), set( |
309 | - ((bugtask, product), (bugtask, milestone)))) |
310 | - |
311 | - def test_sourcepackage_target(self): |
312 | - actor = self.factory.makePerson() |
313 | - login_person(actor) |
314 | - distroseries = self.factory.makeDistroSeries() |
315 | - sourcepackage = self.factory.makeSourcePackage( |
316 | - distroseries=distroseries) |
317 | - product = self.factory.makeProduct() |
318 | - bug = self.factory.makeBug(product=product) |
319 | - bug.addTask(actor, sourcepackage) |
320 | - product_bugtask = bug.bugtasks[0] |
321 | - sourcepackage_bugtask = bug.bugtasks[1] |
322 | - result = self.getStructuralSubscriptionTargets(bug.bugtasks) |
323 | - self.assertEqual(set(result), set( |
324 | - ((product_bugtask, product), |
325 | - (sourcepackage_bugtask, distroseries)))) |
326 | - |
327 | - def test_distribution_source_package_target(self): |
328 | - actor = self.factory.makePerson() |
329 | - login_person(actor) |
330 | - distribution = self.factory.makeDistribution() |
331 | - dist_sourcepackage = self.factory.makeDistributionSourcePackage( |
332 | - distribution=distribution) |
333 | - product = self.factory.makeProduct() |
334 | - bug = self.factory.makeBug(product=product) |
335 | - bug.addTask(actor, dist_sourcepackage) |
336 | - product_bugtask = bug.bugtasks[0] |
337 | - dist_sourcepackage_bugtask = bug.bugtasks[1] |
338 | - result = self.getStructuralSubscriptionTargets(bug.bugtasks) |
339 | - self.assertEqual(set(result), set( |
340 | - ((product_bugtask, product), |
341 | - (dist_sourcepackage_bugtask, dist_sourcepackage), |
342 | - (dist_sourcepackage_bugtask, distribution)))) |
343 | - |
344 | - |
345 | -class TestGetAllStructuralSubscriptions(TestCaseWithFactory): |
346 | - |
347 | - layer = DatabaseFunctionalLayer |
348 | - |
349 | - def getAllStructuralSubscriptions(self, bugtasks, recipient): |
350 | - # Call IBugTaskSet.getAllStructuralSubscriptions() and check that the |
351 | - # result is security proxied. |
352 | - result = getUtility(IBugTaskSet).getAllStructuralSubscriptions( |
353 | - bugtasks, recipient) |
354 | - self.assertTrue(is_security_proxied_or_harmless(result)) |
355 | - return result |
356 | - |
357 | - def setUp(self): |
358 | - super(TestGetAllStructuralSubscriptions, self).setUp() |
359 | - self.subscriber = self.factory.makePerson() |
360 | - login_person(self.subscriber) |
361 | - self.product = self.factory.makeProduct() |
362 | - self.milestone = self.factory.makeMilestone(product=self.product) |
363 | - self.bug = self.factory.makeBug( |
364 | - product=self.product, milestone=self.milestone) |
365 | - |
366 | - def test_no_subscriptions(self): |
367 | - subscriptions = self.getAllStructuralSubscriptions( |
368 | - self.bug.bugtasks, self.subscriber) |
369 | - self.assertEqual([], list(subscriptions)) |
370 | - |
371 | - def test_one_subscription(self): |
372 | - sub = self.product.addBugSubscription( |
373 | - self.subscriber, self.subscriber) |
374 | - subscriptions = self.getAllStructuralSubscriptions( |
375 | - self.bug.bugtasks, self.subscriber) |
376 | - self.assertEqual([sub], list(subscriptions)) |
377 | - |
378 | - def test_two_subscriptions(self): |
379 | - sub1 = self.product.addBugSubscription( |
380 | - self.subscriber, self.subscriber) |
381 | - sub2 = self.milestone.addBugSubscription( |
382 | - self.subscriber, self.subscriber) |
383 | - subscriptions = self.getAllStructuralSubscriptions( |
384 | - self.bug.bugtasks, self.subscriber) |
385 | - self.assertEqual(set([sub1, sub2]), set(subscriptions)) |
386 | - |
387 | - def test_two_bugtasks_one_subscription(self): |
388 | - sub = self.product.addBugSubscription( |
389 | - self.subscriber, self.subscriber) |
390 | - product2 = self.factory.makeProduct() |
391 | - self.bug.addTask(self.subscriber, product2) |
392 | - subscriptions = self.getAllStructuralSubscriptions( |
393 | - self.bug.bugtasks, self.subscriber) |
394 | - self.assertEqual([sub], list(subscriptions)) |
395 | - |
396 | - def test_two_bugtasks_two_subscriptions(self): |
397 | - sub1 = self.product.addBugSubscription( |
398 | - self.subscriber, self.subscriber) |
399 | - product2 = self.factory.makeProduct() |
400 | - self.bug.addTask(self.subscriber, product2) |
401 | - sub2 = product2.addBugSubscription( |
402 | - self.subscriber, self.subscriber) |
403 | - subscriptions = self.getAllStructuralSubscriptions( |
404 | - self.bug.bugtasks, self.subscriber) |
405 | - self.assertEqual(set([sub1, sub2]), set(subscriptions)) |
406 | - |
407 | - def test_ignore_other_subscriptions(self): |
408 | - sub1 = self.product.addBugSubscription( |
409 | - self.subscriber, self.subscriber) |
410 | - another_subscriber = self.factory.makePerson() |
411 | - login_person(another_subscriber) |
412 | - sub2 = self.product.addBugSubscription( |
413 | - another_subscriber, another_subscriber) |
414 | - subscriptions = self.getAllStructuralSubscriptions( |
415 | - self.bug.bugtasks, self.subscriber) |
416 | - self.assertEqual([sub1], list(subscriptions)) |
417 | - subscriptions = self.getAllStructuralSubscriptions( |
418 | - self.bug.bugtasks, another_subscriber) |
419 | - self.assertEqual([sub2], list(subscriptions)) |
420 | - |
421 | - |
422 | -class TestGetStructuralSubscribers(TestCaseWithFactory): |
423 | - |
424 | - layer = DatabaseFunctionalLayer |
425 | - |
426 | - def make_product_with_bug(self): |
427 | - product = self.factory.makeProduct() |
428 | - bug = self.factory.makeBug(product=product) |
429 | - return product, bug |
430 | - |
431 | - def getStructuralSubscribers(self, bugtasks, *args, **kwargs): |
432 | - # Call IBugTaskSet.getStructuralSubscribers() and check that the |
433 | - # result is security proxied. |
434 | - result = getUtility(IBugTaskSet).getStructuralSubscribers( |
435 | - bugtasks, *args, **kwargs) |
436 | - self.assertTrue(is_security_proxied_or_harmless(result)) |
437 | - return result |
438 | - |
439 | - def test_getStructuralSubscribers_no_subscribers(self): |
440 | - # If there are no subscribers for any of the bug's targets then no |
441 | - # subscribers will be returned by getStructuralSubscribers(). |
442 | - product, bug = self.make_product_with_bug() |
443 | - subscribers = self.getStructuralSubscribers(bug.bugtasks) |
444 | - self.assertIsInstance(subscribers, (ResultSet, EmptyResultSet)) |
445 | - self.assertEqual([], list(subscribers)) |
446 | - |
447 | - def test_getStructuralSubscribers_single_target(self): |
448 | - # Subscribers for any of the bug's targets are returned. |
449 | - subscriber = self.factory.makePerson() |
450 | - login_person(subscriber) |
451 | - product, bug = self.make_product_with_bug() |
452 | - product.addBugSubscription(subscriber, subscriber) |
453 | - self.assertEqual( |
454 | - [subscriber], list( |
455 | - self.getStructuralSubscribers(bug.bugtasks))) |
456 | - |
457 | - def test_getStructuralSubscribers_multiple_targets(self): |
458 | - # Subscribers for any of the bug's targets are returned. |
459 | - actor = self.factory.makePerson() |
460 | - login_person(actor) |
461 | - |
462 | - subscriber1 = self.factory.makePerson() |
463 | - subscriber2 = self.factory.makePerson() |
464 | - |
465 | - product1 = self.factory.makeProduct(owner=actor) |
466 | - product1.addBugSubscription(subscriber1, subscriber1) |
467 | - product2 = self.factory.makeProduct(owner=actor) |
468 | - product2.addBugSubscription(subscriber2, subscriber2) |
469 | - |
470 | - bug = self.factory.makeBug(product=product1) |
471 | - bug.addTask(actor, product2) |
472 | - |
473 | - subscribers = self.getStructuralSubscribers(bug.bugtasks) |
474 | - self.assertIsInstance(subscribers, ResultSet) |
475 | - self.assertEqual(set([subscriber1, subscriber2]), set(subscribers)) |
476 | - |
477 | - def test_getStructuralSubscribers_recipients(self): |
478 | - # If provided, getStructuralSubscribers() calls the appropriate |
479 | - # methods on a BugNotificationRecipients object. |
480 | - subscriber = self.factory.makePerson() |
481 | - login_person(subscriber) |
482 | - product, bug = self.make_product_with_bug() |
483 | - product.addBugSubscription(subscriber, subscriber) |
484 | - recipients = BugNotificationRecipients() |
485 | - subscribers = self.getStructuralSubscribers( |
486 | - bug.bugtasks, recipients=recipients) |
487 | - # The return value is a list only when populating recipients. |
488 | - self.assertIsInstance(subscribers, list) |
489 | - self.assertEqual([subscriber], recipients.getRecipients()) |
490 | - reason, header = recipients.getReason(subscriber) |
491 | - self.assertThat( |
492 | - reason, StartsWith( |
493 | - u"You received this bug notification because " |
494 | - u"you are subscribed to ")) |
495 | - self.assertThat(header, StartsWith(u"Subscriber ")) |
496 | - |
497 | - def test_getStructuralSubscribers_level(self): |
498 | - # getStructuralSubscribers() respects the given level. |
499 | - subscriber = self.factory.makePerson() |
500 | - login_person(subscriber) |
501 | - product, bug = self.make_product_with_bug() |
502 | - subscription = product.addBugSubscription(subscriber, subscriber) |
503 | - filter = subscription.bug_filters.one() |
504 | - filter.bug_notification_level = BugNotificationLevel.METADATA |
505 | - self.assertEqual( |
506 | - [subscriber], list( |
507 | - self.getStructuralSubscribers( |
508 | - bug.bugtasks, level=BugNotificationLevel.METADATA))) |
509 | - filter.bug_notification_level = BugNotificationLevel.METADATA |
510 | - self.assertEqual( |
511 | - [], list( |
512 | - self.getStructuralSubscribers( |
513 | - bug.bugtasks, level=BugNotificationLevel.COMMENTS))) |
514 | - |
515 | - |
516 | def test_suite(): |
517 | suite = unittest.TestSuite() |
518 | suite.addTest(unittest.TestLoader().loadTestsFromName(__name__)) |
519 | |
520 | === modified file 'lib/lp/bugs/tests/test_structuralsubscription.py' |
521 | --- lib/lp/bugs/tests/test_structuralsubscription.py 2011-03-07 22:10:32 +0000 |
522 | +++ lib/lp/bugs/tests/test_structuralsubscription.py 2011-03-07 22:10:38 +0000 |
523 | @@ -5,7 +5,12 @@ |
524 | |
525 | __metaclass__ = type |
526 | |
527 | -from storm.store import Store |
528 | +from storm.store import ( |
529 | + EmptyResultSet, |
530 | + ResultSet, |
531 | + Store, |
532 | + ) |
533 | +from testtools.matchers import StartsWith |
534 | from zope.security.interfaces import Unauthorized |
535 | |
536 | from canonical.testing.layers import ( |
537 | @@ -17,8 +22,13 @@ |
538 | BugTaskImportance, |
539 | BugTaskStatus, |
540 | ) |
541 | +from lp.bugs.mail.bugnotificationrecipients import BugNotificationRecipients |
542 | from lp.bugs.model.bugsubscriptionfilter import BugSubscriptionFilter |
543 | -from lp.bugs.model.structuralsubscription import get_structural_subscribers |
544 | +from lp.bugs.model.structuralsubscription import ( |
545 | + get_all_structural_subscriptions, |
546 | + get_structural_subscribers, |
547 | + get_structural_subscription_targets, |
548 | + ) |
549 | from lp.testing import ( |
550 | anonymous_logged_in, |
551 | login_person, |
552 | @@ -444,3 +454,213 @@ |
553 | |
554 | def makeTarget(self): |
555 | return self.factory.makeProductSeries() |
556 | + |
557 | + |
558 | +class TestGetStructuralSubscriptionTargets(TestCaseWithFactory): |
559 | + |
560 | + layer = DatabaseFunctionalLayer |
561 | + |
562 | + def test_product_target(self): |
563 | + product = self.factory.makeProduct() |
564 | + bug = self.factory.makeBug(product=product) |
565 | + bugtask = bug.bugtasks[0] |
566 | + result = get_structural_subscription_targets(bug.bugtasks) |
567 | + self.assertEqual(list(result), [(bugtask, product)]) |
568 | + |
569 | + def test_milestone_target(self): |
570 | + actor = self.factory.makePerson() |
571 | + login_person(actor) |
572 | + product = self.factory.makeProduct() |
573 | + milestone = self.factory.makeMilestone(product=product) |
574 | + bug = self.factory.makeBug(product=product, milestone=milestone) |
575 | + bugtask = bug.bugtasks[0] |
576 | + result = get_structural_subscription_targets(bug.bugtasks) |
577 | + self.assertEqual(set(result), set( |
578 | + ((bugtask, product), (bugtask, milestone)))) |
579 | + |
580 | + def test_sourcepackage_target(self): |
581 | + actor = self.factory.makePerson() |
582 | + login_person(actor) |
583 | + distroseries = self.factory.makeDistroSeries() |
584 | + sourcepackage = self.factory.makeSourcePackage( |
585 | + distroseries=distroseries) |
586 | + product = self.factory.makeProduct() |
587 | + bug = self.factory.makeBug(product=product) |
588 | + bug.addTask(actor, sourcepackage) |
589 | + product_bugtask = bug.bugtasks[0] |
590 | + sourcepackage_bugtask = bug.bugtasks[1] |
591 | + result = get_structural_subscription_targets(bug.bugtasks) |
592 | + self.assertEqual(set(result), set( |
593 | + ((product_bugtask, product), |
594 | + (sourcepackage_bugtask, distroseries)))) |
595 | + |
596 | + def test_distribution_source_package_target(self): |
597 | + actor = self.factory.makePerson() |
598 | + login_person(actor) |
599 | + distribution = self.factory.makeDistribution() |
600 | + dist_sourcepackage = self.factory.makeDistributionSourcePackage( |
601 | + distribution=distribution) |
602 | + product = self.factory.makeProduct() |
603 | + bug = self.factory.makeBug(product=product) |
604 | + bug.addTask(actor, dist_sourcepackage) |
605 | + product_bugtask = bug.bugtasks[0] |
606 | + dist_sourcepackage_bugtask = bug.bugtasks[1] |
607 | + result = get_structural_subscription_targets(bug.bugtasks) |
608 | + self.assertEqual(set(result), set( |
609 | + ((product_bugtask, product), |
610 | + (dist_sourcepackage_bugtask, dist_sourcepackage), |
611 | + (dist_sourcepackage_bugtask, distribution)))) |
612 | + |
613 | + |
614 | +class TestGetAllStructuralSubscriptions(TestCaseWithFactory): |
615 | + |
616 | + layer = DatabaseFunctionalLayer |
617 | + |
618 | + def setUp(self): |
619 | + super(TestGetAllStructuralSubscriptions, self).setUp() |
620 | + self.subscriber = self.factory.makePerson() |
621 | + login_person(self.subscriber) |
622 | + self.product = self.factory.makeProduct() |
623 | + self.milestone = self.factory.makeMilestone(product=self.product) |
624 | + self.bug = self.factory.makeBug( |
625 | + product=self.product, milestone=self.milestone) |
626 | + |
627 | + def test_no_subscriptions(self): |
628 | + subscriptions = get_all_structural_subscriptions( |
629 | + self.bug.bugtasks, self.subscriber) |
630 | + self.assertEqual([], list(subscriptions)) |
631 | + |
632 | + def test_one_subscription(self): |
633 | + sub = self.product.addBugSubscription( |
634 | + self.subscriber, self.subscriber) |
635 | + subscriptions = get_all_structural_subscriptions( |
636 | + self.bug.bugtasks, self.subscriber) |
637 | + self.assertEqual([sub], list(subscriptions)) |
638 | + |
639 | + def test_two_subscriptions(self): |
640 | + sub1 = self.product.addBugSubscription( |
641 | + self.subscriber, self.subscriber) |
642 | + sub2 = self.milestone.addBugSubscription( |
643 | + self.subscriber, self.subscriber) |
644 | + subscriptions = get_all_structural_subscriptions( |
645 | + self.bug.bugtasks, self.subscriber) |
646 | + self.assertEqual(set([sub1, sub2]), set(subscriptions)) |
647 | + |
648 | + def test_two_bugtasks_one_subscription(self): |
649 | + sub = self.product.addBugSubscription( |
650 | + self.subscriber, self.subscriber) |
651 | + product2 = self.factory.makeProduct() |
652 | + self.bug.addTask(self.subscriber, product2) |
653 | + subscriptions = get_all_structural_subscriptions( |
654 | + self.bug.bugtasks, self.subscriber) |
655 | + self.assertEqual([sub], list(subscriptions)) |
656 | + |
657 | + def test_two_bugtasks_two_subscriptions(self): |
658 | + sub1 = self.product.addBugSubscription( |
659 | + self.subscriber, self.subscriber) |
660 | + product2 = self.factory.makeProduct() |
661 | + self.bug.addTask(self.subscriber, product2) |
662 | + sub2 = product2.addBugSubscription( |
663 | + self.subscriber, self.subscriber) |
664 | + subscriptions = get_all_structural_subscriptions( |
665 | + self.bug.bugtasks, self.subscriber) |
666 | + self.assertEqual(set([sub1, sub2]), set(subscriptions)) |
667 | + |
668 | + def test_ignore_other_subscriptions(self): |
669 | + sub1 = self.product.addBugSubscription( |
670 | + self.subscriber, self.subscriber) |
671 | + another_subscriber = self.factory.makePerson() |
672 | + login_person(another_subscriber) |
673 | + sub2 = self.product.addBugSubscription( |
674 | + another_subscriber, another_subscriber) |
675 | + subscriptions = get_all_structural_subscriptions( |
676 | + self.bug.bugtasks, self.subscriber) |
677 | + self.assertEqual([sub1], list(subscriptions)) |
678 | + subscriptions = get_all_structural_subscriptions( |
679 | + self.bug.bugtasks, another_subscriber) |
680 | + self.assertEqual([sub2], list(subscriptions)) |
681 | + |
682 | + |
683 | +class TestGetStructuralSubscribers(TestCaseWithFactory): |
684 | + |
685 | + layer = DatabaseFunctionalLayer |
686 | + |
687 | + def make_product_with_bug(self): |
688 | + product = self.factory.makeProduct() |
689 | + bug = self.factory.makeBug(product=product) |
690 | + return product, bug |
691 | + |
692 | + def test_getStructuralSubscribers_no_subscribers(self): |
693 | + # If there are no subscribers for any of the bug's targets then no |
694 | + # subscribers will be returned by get_structural_subscribers(). |
695 | + product, bug = self.make_product_with_bug() |
696 | + subscribers = get_structural_subscribers(bug, None, None, None) |
697 | + self.assertIsInstance(subscribers, (ResultSet, EmptyResultSet)) |
698 | + self.assertEqual([], list(subscribers)) |
699 | + |
700 | + def test_getStructuralSubscribers_single_target(self): |
701 | + # Subscribers for any of the bug's targets are returned. |
702 | + subscriber = self.factory.makePerson() |
703 | + login_person(subscriber) |
704 | + product, bug = self.make_product_with_bug() |
705 | + product.addBugSubscription(subscriber, subscriber) |
706 | + self.assertEqual( |
707 | + [subscriber], list( |
708 | + get_structural_subscribers(bug, None, None, None))) |
709 | + |
710 | + def test_getStructuralSubscribers_multiple_targets(self): |
711 | + # Subscribers for any of the bug's targets are returned. |
712 | + actor = self.factory.makePerson() |
713 | + login_person(actor) |
714 | + |
715 | + subscriber1 = self.factory.makePerson() |
716 | + subscriber2 = self.factory.makePerson() |
717 | + |
718 | + product1 = self.factory.makeProduct(owner=actor) |
719 | + product1.addBugSubscription(subscriber1, subscriber1) |
720 | + product2 = self.factory.makeProduct(owner=actor) |
721 | + product2.addBugSubscription(subscriber2, subscriber2) |
722 | + |
723 | + bug = self.factory.makeBug(product=product1) |
724 | + bug.addTask(actor, product2) |
725 | + |
726 | + subscribers = get_structural_subscribers(bug, None, None, None) |
727 | + self.assertIsInstance(subscribers, ResultSet) |
728 | + self.assertEqual(set([subscriber1, subscriber2]), set(subscribers)) |
729 | + |
730 | + def test_getStructuralSubscribers_recipients(self): |
731 | + # If provided, get_structural_subscribers() calls the appropriate |
732 | + # methods on a BugNotificationRecipients object. |
733 | + subscriber = self.factory.makePerson() |
734 | + login_person(subscriber) |
735 | + product, bug = self.make_product_with_bug() |
736 | + product.addBugSubscription(subscriber, subscriber) |
737 | + recipients = BugNotificationRecipients() |
738 | + subscribers = get_structural_subscribers(bug, recipients, None, None) |
739 | + # The return value is a list only when populating recipients. |
740 | + self.assertIsInstance(subscribers, list) |
741 | + self.assertEqual([subscriber], recipients.getRecipients()) |
742 | + reason, header = recipients.getReason(subscriber) |
743 | + self.assertThat( |
744 | + reason, StartsWith( |
745 | + u"You received this bug notification because " |
746 | + u"you are subscribed to ")) |
747 | + self.assertThat(header, StartsWith(u"Subscriber ")) |
748 | + |
749 | + def test_getStructuralSubscribers_level(self): |
750 | + # get_structural_subscribers() respects the given level. |
751 | + subscriber = self.factory.makePerson() |
752 | + login_person(subscriber) |
753 | + product, bug = self.make_product_with_bug() |
754 | + subscription = product.addBugSubscription(subscriber, subscriber) |
755 | + filter = subscription.bug_filters.one() |
756 | + filter.bug_notification_level = BugNotificationLevel.METADATA |
757 | + self.assertEqual( |
758 | + [subscriber], list( |
759 | + get_structural_subscribers( |
760 | + bug, None, BugNotificationLevel.METADATA, None))) |
761 | + filter.bug_notification_level = BugNotificationLevel.METADATA |
762 | + self.assertEqual( |
763 | + [], list( |
764 | + get_structural_subscribers( |
765 | + bug, None, BugNotificationLevel.COMMENTS, None))) |
Looks good. This branch, like the others in this series, was cohesive
so that helped in reviewing it.
One small note: The import of StructuralSubsc ription in bugs/model/ bugtask. py could be on one line if you wanted.
lib/lp/