Merge lp:~stevenk/launchpad/destroy-old-bugactivity into lp:launchpad
- destroy-old-bugactivity
- Merge into devel
Proposed by
Steve Kowalik
Status: | Merged |
---|---|
Approved by: | Curtis Hovey |
Approved revision: | no longer in the source branch. |
Merged at revision: | 16146 |
Proposed branch: | lp:~stevenk/launchpad/destroy-old-bugactivity |
Merge into: | lp:launchpad |
Diff against target: |
838 lines (+79/-374) 12 files modified
database/sampledata/current-dev.sql (+0/-1) database/schema/Makefile (+2/-1) lib/lp/bugs/adapters/bugchange.py (+2/-76) lib/lp/bugs/doc/bug-change.txt (+0/-87) lib/lp/bugs/doc/bugnotification-email.txt (+9/-15) lib/lp/bugs/doc/bugnotification-sending.txt (+21/-20) lib/lp/bugs/doc/bugnotification-threading.txt (+8/-7) lib/lp/bugs/scripts/tests/test_bugnotification.py (+5/-7) lib/lp/bugs/stories/bugs/xx-bug-activity.txt (+13/-56) lib/lp/bugs/subscribers/bug.py (+2/-8) lib/lp/bugs/tests/test_bugchanges.py (+17/-89) lib/lp/services/features/flags.py (+0/-7) |
To merge this branch: | bzr merge lp:~stevenk/launchpad/destroy-old-bugactivity |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Curtis Hovey (community) | code | Approve | |
Review via email: mp+129339@code.launchpad.net |
Commit message
Destroy Bug{Security,
Description of the change
Destroy Bug{Security,
I have changed all of the tests I could find, but I suspect ec2 may find some that I may have missed.
I have corrected a small bug in database/
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'database/sampledata/current-dev.sql' | |||
2 | --- database/sampledata/current-dev.sql 2012-10-12 05:43:38 +0000 | |||
3 | +++ database/sampledata/current-dev.sql 2012-10-15 03:36:20 +0000 | |||
4 | @@ -4321,7 +4321,6 @@ | |||
5 | 4321 | 4321 | ||
6 | 4322 | ALTER TABLE featureflag DISABLE TRIGGER ALL; | 4322 | ALTER TABLE featureflag DISABLE TRIGGER ALL; |
7 | 4323 | 4323 | ||
8 | 4324 | INSERT INTO featureflag (scope, priority, flag, value, date_modified) VALUES ('default', 0, 'disclosure.information_type_notifications.enabled', 'true', '2012-05-18 07:34:39.239649'); | ||
9 | 4325 | INSERT INTO featureflag (scope, priority, flag, value, date_modified) VALUES ('default', 0, 'js.combo_loader.enabled', 'true', '2012-05-18 07:34:39.239649'); | 4324 | INSERT INTO featureflag (scope, priority, flag, value, date_modified) VALUES ('default', 0, 'js.combo_loader.enabled', 'true', '2012-05-18 07:34:39.239649'); |
10 | 4326 | INSERT INTO featureflag (scope, priority, flag, value, date_modified) VALUES ('default', 1, 'longpoll.merge_proposals.enabled', 'true', '2012-05-18 07:34:39.239649'); | 4325 | INSERT INTO featureflag (scope, priority, flag, value, date_modified) VALUES ('default', 1, 'longpoll.merge_proposals.enabled', 'true', '2012-05-18 07:34:39.239649'); |
11 | 4327 | 4326 | ||
12 | 4328 | 4327 | ||
13 | === modified file 'database/schema/Makefile' | |||
14 | --- database/schema/Makefile 2012-07-12 09:58:32 +0000 | |||
15 | +++ database/schema/Makefile 2012-10-15 03:36:20 +0000 | |||
16 | @@ -38,7 +38,8 @@ | |||
17 | 38 | # The command we use to drop (if exists) and recreate a database. | 38 | # The command we use to drop (if exists) and recreate a database. |
18 | 39 | CREATEDB=${PYTHON} ../../utilities/pgmassacre.py -t | 39 | CREATEDB=${PYTHON} ../../utilities/pgmassacre.py -t |
19 | 40 | 40 | ||
21 | 41 | HEADER="-- Copyright 2010-2011 Canonical Ltd. This software is licensed \ | 41 | YEAR=$(shell date +'%Y') |
22 | 42 | HEADER="-- Copyright 2010-${YEAR} Canonical Ltd. This software is licensed \ | ||
23 | 42 | under the\n-- GNU Affero General Public License version 3 (see the file \ | 43 | under the\n-- GNU Affero General Public License version 3 (see the file \ |
24 | 43 | LICENSE)." | 44 | LICENSE)." |
25 | 44 | 45 | ||
26 | 45 | 46 | ||
27 | === modified file 'lib/lp/bugs/adapters/bugchange.py' | |||
28 | --- lib/lp/bugs/adapters/bugchange.py 2012-07-17 03:57:26 +0000 | |||
29 | +++ lib/lp/bugs/adapters/bugchange.py 2012-10-15 03:36:20 +0000 | |||
30 | @@ -24,7 +24,6 @@ | |||
31 | 24 | 'BugDescriptionChange', | 24 | 'BugDescriptionChange', |
32 | 25 | 'BugDuplicateChange', | 25 | 'BugDuplicateChange', |
33 | 26 | 'BugInformationTypeChange', | 26 | 'BugInformationTypeChange', |
34 | 27 | 'BugSecurityChange', | ||
35 | 28 | 'BugTagsChange', | 27 | 'BugTagsChange', |
36 | 29 | 'BugTaskAdded', | 28 | 'BugTaskAdded', |
37 | 30 | 'BugTaskAssigneeChange', | 29 | 'BugTaskAssigneeChange', |
38 | @@ -35,7 +34,6 @@ | |||
39 | 35 | 'BugTaskStatusChange', | 34 | 'BugTaskStatusChange', |
40 | 36 | 'BugTaskTargetChange', | 35 | 'BugTaskTargetChange', |
41 | 37 | 'BugTitleChange', | 36 | 'BugTitleChange', |
42 | 38 | 'BugVisibilityChange', | ||
43 | 39 | 'BugWatchAdded', | 37 | 'BugWatchAdded', |
44 | 40 | 'BugWatchRemoved', | 38 | 'BugWatchRemoved', |
45 | 41 | 'CveLinkedToBug', | 39 | 'CveLinkedToBug', |
46 | @@ -59,7 +57,6 @@ | |||
47 | 59 | UNRESOLVED_BUGTASK_STATUSES, | 57 | UNRESOLVED_BUGTASK_STATUSES, |
48 | 60 | ) | 58 | ) |
49 | 61 | from lp.registry.interfaces.product import IProduct | 59 | from lp.registry.interfaces.product import IProduct |
50 | 62 | from lp.services.features import getFeatureFlag | ||
51 | 63 | from lp.services.librarian.browser import ProxiedLibraryFileAlias | 60 | from lp.services.librarian.browser import ProxiedLibraryFileAlias |
52 | 64 | from lp.services.webapp.publisher import canonical_url | 61 | from lp.services.webapp.publisher import canonical_url |
53 | 65 | 62 | ||
54 | @@ -105,13 +102,8 @@ | |||
55 | 105 | # The order of the field names in this list is important; this is | 102 | # The order of the field names in this list is important; this is |
56 | 106 | # the order in which changes will appear both in the bug activity | 103 | # the order in which changes will appear both in the bug activity |
57 | 107 | # log and in notification emails. | 104 | # log and in notification emails. |
65 | 108 | bug_change_field_names = ['duplicateof', 'title', 'description'] | 105 | bug_change_field_names = ['duplicateof', 'title', 'description', |
66 | 109 | if bool(getFeatureFlag( | 106 | 'information_type', 'tags', 'attachment'] |
60 | 110 | 'disclosure.information_type_notifications.enabled')): | ||
61 | 111 | bug_change_field_names.append('information_type') | ||
62 | 112 | else: | ||
63 | 113 | bug_change_field_names.extend(('private', 'security_related')) | ||
64 | 114 | bug_change_field_names.extend(('tags', 'attachment')) | ||
67 | 115 | for field_name in bug_change_field_names: | 107 | for field_name in bug_change_field_names: |
68 | 116 | field_delta = getattr(bug_delta, field_name) | 108 | field_delta = getattr(bug_delta, field_name) |
69 | 117 | if field_delta is not None: | 109 | if field_delta is not None: |
70 | @@ -562,70 +554,6 @@ | |||
71 | 562 | self.old_value.title, self.new_value.title)} | 554 | self.old_value.title, self.new_value.title)} |
72 | 563 | 555 | ||
73 | 564 | 556 | ||
74 | 565 | # XXX: This can be deleted when information_type_notifications is removed. | ||
75 | 566 | class BugVisibilityChange(AttributeChange): | ||
76 | 567 | """Describes a change to a bug's visibility.""" | ||
77 | 568 | |||
78 | 569 | def _getVisibilityString(self, private): | ||
79 | 570 | """Return a string representation of `private`. | ||
80 | 571 | |||
81 | 572 | :return: 'Public' if private is False, 'Private' if | ||
82 | 573 | private is True. | ||
83 | 574 | """ | ||
84 | 575 | if private: | ||
85 | 576 | return 'Private' | ||
86 | 577 | else: | ||
87 | 578 | return 'Public' | ||
88 | 579 | |||
89 | 580 | def getBugActivity(self): | ||
90 | 581 | # Use _getVisibilityString() to set old and new values | ||
91 | 582 | # correctly. We lowercase them for UI consistency in the | ||
92 | 583 | # activity log. | ||
93 | 584 | old_value = self._getVisibilityString(self.old_value) | ||
94 | 585 | new_value = self._getVisibilityString(self.new_value) | ||
95 | 586 | return { | ||
96 | 587 | 'oldvalue': old_value.lower(), | ||
97 | 588 | 'newvalue': new_value.lower(), | ||
98 | 589 | 'whatchanged': 'visibility', | ||
99 | 590 | } | ||
100 | 591 | |||
101 | 592 | def getBugNotification(self): | ||
102 | 593 | visibility_string = self._getVisibilityString(self.new_value) | ||
103 | 594 | return {'text': "** Visibility changed to: %s" % visibility_string} | ||
104 | 595 | |||
105 | 596 | |||
106 | 597 | # XXX: This can be deleted when information_type_notifications is removed. | ||
107 | 598 | class BugSecurityChange(AttributeChange): | ||
108 | 599 | """Describes a change to a bug's security setting.""" | ||
109 | 600 | |||
110 | 601 | activity_mapping = { | ||
111 | 602 | (False, True): ('no', 'yes'), | ||
112 | 603 | (True, False): ('yes', 'no'), | ||
113 | 604 | } | ||
114 | 605 | |||
115 | 606 | notification_mapping = { | ||
116 | 607 | (False, True): | ||
117 | 608 | u"** This bug has been flagged as a security vulnerability", | ||
118 | 609 | (True, False): | ||
119 | 610 | u"** This bug is no longer flagged as a security vulnerability", | ||
120 | 611 | } | ||
121 | 612 | |||
122 | 613 | def getBugActivity(self): | ||
123 | 614 | old_value, new_value = self.activity_mapping[ | ||
124 | 615 | (self.old_value, self.new_value)] | ||
125 | 616 | return { | ||
126 | 617 | 'oldvalue': old_value, | ||
127 | 618 | 'newvalue': new_value, | ||
128 | 619 | 'whatchanged': 'security vulnerability', | ||
129 | 620 | } | ||
130 | 621 | |||
131 | 622 | def getBugNotification(self): | ||
132 | 623 | return { | ||
133 | 624 | 'text': self.notification_mapping[ | ||
134 | 625 | (self.old_value, self.new_value)], | ||
135 | 626 | } | ||
136 | 627 | |||
137 | 628 | |||
138 | 629 | class BugTagsChange(AttributeChange): | 557 | class BugTagsChange(AttributeChange): |
139 | 630 | """Used to represent a change to an `IBug`s tags.""" | 558 | """Used to represent a change to an `IBug`s tags.""" |
140 | 631 | 559 | ||
141 | @@ -940,8 +868,6 @@ | |||
142 | 940 | 868 | ||
143 | 941 | BUG_CHANGE_LOOKUP = { | 869 | BUG_CHANGE_LOOKUP = { |
144 | 942 | 'description': BugDescriptionChange, | 870 | 'description': BugDescriptionChange, |
145 | 943 | 'private': BugVisibilityChange, | ||
146 | 944 | 'security_related': BugSecurityChange, | ||
147 | 945 | 'information_type': BugInformationTypeChange, | 871 | 'information_type': BugInformationTypeChange, |
148 | 946 | 'tags': BugTagsChange, | 872 | 'tags': BugTagsChange, |
149 | 947 | 'title': BugTitleChange, | 873 | 'title': BugTitleChange, |
150 | 948 | 874 | ||
151 | === modified file 'lib/lp/bugs/doc/bug-change.txt' | |||
152 | --- lib/lp/bugs/doc/bug-change.txt 2012-08-08 11:48:29 +0000 | |||
153 | +++ lib/lp/bugs/doc/bug-change.txt 2012-10-15 03:36:20 +0000 | |||
154 | @@ -312,50 +312,6 @@ | |||
155 | 312 | 'whatchanged': 'marked as duplicate'} | 312 | 'whatchanged': 'marked as duplicate'} |
156 | 313 | 313 | ||
157 | 314 | 314 | ||
158 | 315 | === BugVisibilityChange === | ||
159 | 316 | |||
160 | 317 | BugVisibilityChange is used to represent a change in a Bug's `private` | ||
161 | 318 | attribute. | ||
162 | 319 | |||
163 | 320 | >>> from lp.bugs.adapters.bugchange import ( | ||
164 | 321 | ... BugVisibilityChange) | ||
165 | 322 | |||
166 | 323 | >>> bug_visibility_change = BugVisibilityChange( | ||
167 | 324 | ... when=nowish, person=example_person, | ||
168 | 325 | ... what_changed='private', old_value=example_bug.private, | ||
169 | 326 | ... new_value=True) | ||
170 | 327 | |||
171 | 328 | IBug.private is a boolean but to make it more readable we express it in | ||
172 | 329 | activity and notification records as a string, where True = 'Private' | ||
173 | 330 | and False = 'Public'. We also refer to it as "visibility" rather than | ||
174 | 331 | privacy. | ||
175 | 332 | |||
176 | 333 | >>> print pretty(bug_visibility_change.getBugActivity()) | ||
177 | 334 | {'newvalue': 'private', | ||
178 | 335 | 'oldvalue': 'public', | ||
179 | 336 | 'whatchanged': 'visibility'} | ||
180 | 337 | |||
181 | 338 | We also use the 'Private', 'Public' and 'Visibility' terms in the | ||
182 | 339 | notification text. | ||
183 | 340 | |||
184 | 341 | >>> print bug_visibility_change.getBugNotification()['text'] | ||
185 | 342 | ** Visibility changed to: Private | ||
186 | 343 | |||
187 | 344 | If we reverse the changes we'll see the opposite values in the | ||
188 | 345 | notification and activity entries. | ||
189 | 346 | |||
190 | 347 | >>> bug_visibility_change = BugVisibilityChange( | ||
191 | 348 | ... when=nowish, person=example_person, | ||
192 | 349 | ... what_changed='private', old_value=True, new_value=False) | ||
193 | 350 | >>> print pretty(bug_visibility_change.getBugActivity()) | ||
194 | 351 | {'newvalue': 'public', | ||
195 | 352 | 'oldvalue': 'private', | ||
196 | 353 | 'whatchanged': 'visibility'} | ||
197 | 354 | |||
198 | 355 | >>> print bug_visibility_change.getBugNotification()['text'] | ||
199 | 356 | ** Visibility changed to: Public | ||
200 | 357 | |||
201 | 358 | |||
202 | 359 | == BugTagsChange == | 315 | == BugTagsChange == |
203 | 360 | 316 | ||
204 | 361 | BugTagsChange is used to represent a change in a Bug's tag list. | 317 | BugTagsChange is used to represent a change in a Bug's tag list. |
205 | @@ -385,49 +341,6 @@ | |||
206 | 385 | ** Tags added: zillionth-tag | 341 | ** Tags added: zillionth-tag |
207 | 386 | 342 | ||
208 | 387 | 343 | ||
209 | 388 | === BugSecurityChange === | ||
210 | 389 | |||
211 | 390 | BugSecurityChange is used to represent a change in a Bug's | ||
212 | 391 | `security_related` attribute. | ||
213 | 392 | |||
214 | 393 | >>> from lp.bugs.adapters.bugchange import ( | ||
215 | 394 | ... BugSecurityChange) | ||
216 | 395 | |||
217 | 396 | >>> bug_security_change = BugSecurityChange( | ||
218 | 397 | ... when=nowish, person=example_person, | ||
219 | 398 | ... what_changed='security_related', | ||
220 | 399 | ... old_value=False, new_value=True) | ||
221 | 400 | |||
222 | 401 | IBug.security_related is a boolean but to make it more readable we | ||
223 | 402 | express it in activity and notification records as a short phrase. | ||
224 | 403 | |||
225 | 404 | Marking a bug as security related causes one set of terms/phrases to | ||
226 | 405 | be used. | ||
227 | 406 | |||
228 | 407 | >>> print pretty(bug_security_change.getBugActivity()) | ||
229 | 408 | {'newvalue': 'yes', | ||
230 | 409 | 'oldvalue': 'no', | ||
231 | 410 | 'whatchanged': 'security vulnerability'} | ||
232 | 411 | |||
233 | 412 | >>> print bug_security_change.getBugNotification()['text'] | ||
234 | 413 | ** This bug has been flagged as a security vulnerability | ||
235 | 414 | |||
236 | 415 | Going the other way the phrases are similar. | ||
237 | 416 | |||
238 | 417 | >>> bug_security_change = BugSecurityChange( | ||
239 | 418 | ... when=nowish, person=example_person, | ||
240 | 419 | ... what_changed='security_related', | ||
241 | 420 | ... old_value=True, new_value=False) | ||
242 | 421 | |||
243 | 422 | >>> print pretty(bug_security_change.getBugActivity()) | ||
244 | 423 | {'newvalue': 'no', | ||
245 | 424 | 'oldvalue': 'yes', | ||
246 | 425 | 'whatchanged': 'security vulnerability'} | ||
247 | 426 | |||
248 | 427 | >>> print bug_security_change.getBugNotification()['text'] | ||
249 | 428 | ** This bug is no longer flagged as a security vulnerability | ||
250 | 429 | |||
251 | 430 | |||
252 | 431 | === CveLinkedToBug / CveUnlinkedFromBug === | 344 | === CveLinkedToBug / CveUnlinkedFromBug === |
253 | 432 | 345 | ||
254 | 433 | These describe the linking or unlinking of a CVE to a bug. | 346 | These describe the linking or unlinking of a CVE to a bug. |
255 | 434 | 347 | ||
256 | === modified file 'lib/lp/bugs/doc/bugnotification-email.txt' | |||
257 | --- lib/lp/bugs/doc/bugnotification-email.txt 2012-09-17 16:13:40 +0000 | |||
258 | +++ lib/lp/bugs/doc/bugnotification-email.txt 2012-10-15 03:36:20 +0000 | |||
259 | @@ -233,10 +233,9 @@ | |||
260 | 233 | ... bug=edited_bug, | 233 | ... bug=edited_bug, |
261 | 234 | ... bugurl="http://www.example.com/bugs/6", | 234 | ... bugurl="http://www.example.com/bugs/6", |
262 | 235 | ... user=sample_person, | 235 | ... user=sample_person, |
267 | 236 | ... private={'old': False, 'new': edited_bug.private}, | 236 | ... information_type = { |
268 | 237 | ... security_related={ | 237 | ... 'old': InformationType.PUBLIC, |
269 | 238 | ... 'old': False, | 238 | ... 'new': InformationType.PRIVATESECURITY |
266 | 239 | ... 'new': edited_bug.security_related, | ||
270 | 240 | ... }) | 239 | ... }) |
271 | 241 | 240 | ||
272 | 242 | >>> for change in get_bug_changes(bug_delta): | 241 | >>> for change in get_bug_changes(bug_delta): |
273 | @@ -244,13 +243,10 @@ | |||
274 | 244 | ... text_representation = notification['text'] | 243 | ... text_representation = notification['text'] |
275 | 245 | ... print text_representation #doctest: -NORMALIZE_WHITESPACE | 244 | ... print text_representation #doctest: -NORMALIZE_WHITESPACE |
276 | 246 | ... print "-----------------------------" | 245 | ... print "-----------------------------" |
280 | 247 | ** Visibility changed to: Private | 246 | ** Information type changed from Public to Private Security |
278 | 248 | ----------------------------- | ||
279 | 249 | ** This bug has been flagged as a security vulnerability | ||
281 | 250 | ----------------------------- | 247 | ----------------------------- |
282 | 251 | 248 | ||
285 | 252 | Now we set the bug public, and not security-related and check if the | 249 | Now we set the bug back to public and check if the e-mail sent changed as well. |
284 | 253 | e-mail sent changed as well. | ||
286 | 254 | 250 | ||
287 | 255 | >>> changed = edited_bug.transitionToInformationType( | 251 | >>> changed = edited_bug.transitionToInformationType( |
288 | 256 | ... InformationType.PUBLIC, getUtility(ILaunchBag).user) | 252 | ... InformationType.PUBLIC, getUtility(ILaunchBag).user) |
289 | @@ -259,17 +255,15 @@ | |||
290 | 259 | ... bugurl="http://www.example.com/bugs/6", | 255 | ... bugurl="http://www.example.com/bugs/6", |
291 | 260 | ... user=sample_person, | 256 | ... user=sample_person, |
292 | 261 | ... private={'old': True, 'new': edited_bug.private}, | 257 | ... private={'old': True, 'new': edited_bug.private}, |
296 | 262 | ... security_related={ | 258 | ... information_type={ |
297 | 263 | ... 'old': True, | 259 | ... 'old': InformationType.PRIVATESECURITY, |
298 | 264 | ... 'new': edited_bug.security_related, | 260 | ... 'new': InformationType.PUBLIC |
299 | 265 | ... }) | 261 | ... }) |
300 | 266 | >>> for change in get_bug_changes(bug_delta): | 262 | >>> for change in get_bug_changes(bug_delta): |
301 | 267 | ... notification = change.getBugNotification() | 263 | ... notification = change.getBugNotification() |
302 | 268 | ... print notification['text'] #doctest: -NORMALIZE_WHITESPACE | 264 | ... print notification['text'] #doctest: -NORMALIZE_WHITESPACE |
303 | 269 | ... print "-----------------------------" | 265 | ... print "-----------------------------" |
307 | 270 | ** Visibility changed to: Public | 266 | ** Information type changed from Private Security to Public |
305 | 271 | ----------------------------- | ||
306 | 272 | ** This bug is no longer flagged as a security vulnerability | ||
308 | 273 | ----------------------------- | 267 | ----------------------------- |
309 | 274 | 268 | ||
310 | 275 | Let's add some tags to a bug: | 269 | Let's add some tags to a bug: |
311 | 276 | 270 | ||
312 | === modified file 'lib/lp/bugs/doc/bugnotification-sending.txt' | |||
313 | --- lib/lp/bugs/doc/bugnotification-sending.txt 2012-09-19 13:21:13 +0000 | |||
314 | +++ lib/lp/bugs/doc/bugnotification-sending.txt 2012-10-15 03:36:20 +0000 | |||
315 | @@ -166,16 +166,17 @@ | |||
316 | 166 | Let's add a few changes and see how it looks like: | 166 | Let's add a few changes and see how it looks like: |
317 | 167 | 167 | ||
318 | 168 | >>> from lp.bugs.adapters.bugchange import ( | 168 | >>> from lp.bugs.adapters.bugchange import ( |
320 | 169 | ... BugTitleChange, BugVisibilityChange) | 169 | ... BugTitleChange, BugInformationTypeChange) |
321 | 170 | >>> from lp.app.enums import InformationType | ||
322 | 170 | 171 | ||
323 | 171 | >>> bug_one.addChange( | 172 | >>> bug_one.addChange( |
324 | 172 | ... BugTitleChange( | 173 | ... BugTitleChange( |
325 | 173 | ... ten_minutes_ago, sample_person, "title", | 174 | ... ten_minutes_ago, sample_person, "title", |
326 | 174 | ... "Old summary", "New summary")) | 175 | ... "Old summary", "New summary")) |
327 | 175 | >>> bug_one.addChange( | 176 | >>> bug_one.addChange( |
331 | 176 | ... BugVisibilityChange( | 177 | ... BugInformationTypeChange( |
332 | 177 | ... ten_minutes_ago, sample_person, "private", | 178 | ... ten_minutes_ago, sample_person, "information_type", |
333 | 178 | ... False, True)) | 179 | ... InformationType.PUBLIC, InformationType.USERDATA)) |
334 | 179 | >>> pending_notifications = getUtility( | 180 | >>> pending_notifications = getUtility( |
335 | 180 | ... IBugNotificationSet).getNotificationsToSend() | 181 | ... IBugNotificationSet).getNotificationsToSend() |
336 | 181 | >>> len(pending_notifications) | 182 | >>> len(pending_notifications) |
337 | @@ -196,7 +197,7 @@ | |||
338 | 196 | - Old summary | 197 | - Old summary |
339 | 197 | + New summary | 198 | + New summary |
340 | 198 | <BLANKLINE> | 199 | <BLANKLINE> |
342 | 199 | ** Visibility changed to: Private | 200 | ** Information type changed from Public to Private |
343 | 200 | <BLANKLINE> | 201 | <BLANKLINE> |
344 | 201 | -- | 202 | -- |
345 | 202 | ... | 203 | ... |
346 | @@ -216,9 +217,9 @@ | |||
347 | 216 | ... ten_minutes_ago, sample_person, "title", | 217 | ... ten_minutes_ago, sample_person, "title", |
348 | 217 | ... "New summary", "Another summary")) | 218 | ... "New summary", "Another summary")) |
349 | 218 | >>> bug_one.addChange( | 219 | >>> bug_one.addChange( |
353 | 219 | ... BugVisibilityChange( | 220 | ... BugInformationTypeChange( |
354 | 220 | ... ten_minutes_ago, sample_person, "private", | 221 | ... ten_minutes_ago, sample_person, "information_type", |
355 | 221 | ... True, False)) | 222 | ... InformationType.USERDATA, InformationType.PUBLIC)) |
356 | 222 | >>> pending_notifications = getUtility( | 223 | >>> pending_notifications = getUtility( |
357 | 223 | ... IBugNotificationSet).getNotificationsToSend() | 224 | ... IBugNotificationSet).getNotificationsToSend() |
358 | 224 | >>> len(pending_notifications) | 225 | >>> len(pending_notifications) |
359 | @@ -283,9 +284,10 @@ | |||
360 | 283 | >>> now = datetime.now(pytz.timezone('UTC')) | 284 | >>> now = datetime.now(pytz.timezone('UTC')) |
361 | 284 | >>> for minutes_ago in reversed(range(10)): | 285 | >>> for minutes_ago in reversed(range(10)): |
362 | 285 | ... bug_one.addChange( | 286 | ... bug_one.addChange( |
364 | 286 | ... BugVisibilityChange( | 287 | ... BugInformationTypeChange( |
365 | 287 | ... now - timedelta(minutes=minutes_ago), sample_person, | 288 | ... now - timedelta(minutes=minutes_ago), sample_person, |
367 | 288 | ... "private", False, True)) | 289 | ... "information_type", InformationType.PUBLIC, |
368 | 290 | ... InformationType.USERDATA)) | ||
369 | 289 | >>> pending_notifications = getUtility( | 291 | >>> pending_notifications = getUtility( |
370 | 290 | ... IBugNotificationSet).getNotificationsToSend() | 292 | ... IBugNotificationSet).getNotificationsToSend() |
371 | 291 | >>> len(pending_notifications) | 293 | >>> len(pending_notifications) |
372 | @@ -336,7 +338,6 @@ | |||
373 | 336 | We will need a fresh new bug. | 338 | We will need a fresh new bug. |
374 | 337 | 339 | ||
375 | 338 | >>> from lp.bugs.interfaces.bug import CreateBugParams | 340 | >>> from lp.bugs.interfaces.bug import CreateBugParams |
376 | 339 | >>> from lp.app.enums import InformationType | ||
377 | 340 | >>> from lp.registry.interfaces.distribution import IDistributionSet | 341 | >>> from lp.registry.interfaces.distribution import IDistributionSet |
378 | 341 | >>> ubuntu = getUtility(IDistributionSet).getByName('ubuntu') | 342 | >>> ubuntu = getUtility(IDistributionSet).getByName('ubuntu') |
379 | 342 | >>> description = getUtility(IMessageSet).fromText( | 343 | >>> description = getUtility(IMessageSet).fromText( |
380 | @@ -471,13 +472,13 @@ | |||
381 | 471 | ... ten_minutes_ago, sample_person, "title", | 472 | ... ten_minutes_ago, sample_person, "title", |
382 | 472 | ... "Old summary", "New summary")) | 473 | ... "Old summary", "New summary")) |
383 | 473 | >>> bug_two.addChange( | 474 | >>> bug_two.addChange( |
387 | 474 | ... BugVisibilityChange( | 475 | ... BugInformationTypeChange( |
388 | 475 | ... ten_minutes_ago, sample_person, "title", | 476 | ... ten_minutes_ago, sample_person, "information_type", |
389 | 476 | ... False, True)) | 477 | ... InformationType.PUBLIC, InformationType.USERDATA)) |
390 | 477 | >>> bug_two.addChange( | 478 | >>> bug_two.addChange( |
394 | 478 | ... BugVisibilityChange( | 479 | ... BugInformationTypeChange( |
395 | 479 | ... ten_minutes_ago, sample_person, "title", | 480 | ... ten_minutes_ago, sample_person, "information_type", |
396 | 480 | ... True, False)) | 481 | ... InformationType.USERDATA, InformationType.PUBLIC)) |
397 | 481 | 482 | ||
398 | 482 | >>> notifications = getUtility( | 483 | >>> notifications = getUtility( |
399 | 483 | ... IBugNotificationSet).getNotificationsToSend() | 484 | ... IBugNotificationSet).getNotificationsToSend() |
400 | @@ -559,7 +560,7 @@ | |||
401 | 559 | INFO Notifying test@canonical.com about bug 1. | 560 | INFO Notifying test@canonical.com about bug 1. |
402 | 560 | ... | 561 | ... |
403 | 561 | 562 | ||
405 | 562 | Note that the message omitted the undone visibility change. | 563 | Note that the message omitted the undone information type change. |
406 | 563 | 564 | ||
407 | 564 | The cronscript has to be sure to mark all notifications, omitted and | 565 | The cronscript has to be sure to mark all notifications, omitted and |
408 | 565 | otherwise, as sent. It also marks the omitted notifications with a status, | 566 | otherwise, as sent. It also marks the omitted notifications with a status, |
409 | @@ -591,8 +592,8 @@ | |||
410 | 591 | summary Sent | 592 | summary Sent |
411 | 592 | comment Sent | 593 | comment Sent |
412 | 593 | summary Sent | 594 | summary Sent |
415 | 594 | visibility Omitted | 595 | information type Omitted |
416 | 595 | visibility Omitted | 596 | information type Omitted |
417 | 596 | 597 | ||
418 | 597 | 598 | ||
419 | 598 | The X-Launchpad-Bug header | 599 | The X-Launchpad-Bug header |
420 | 599 | 600 | ||
421 | === modified file 'lib/lp/bugs/doc/bugnotification-threading.txt' | |||
422 | --- lib/lp/bugs/doc/bugnotification-threading.txt 2012-07-27 01:15:04 +0000 | |||
423 | +++ lib/lp/bugs/doc/bugnotification-threading.txt 2012-10-15 03:36:20 +0000 | |||
424 | @@ -18,16 +18,17 @@ | |||
425 | 18 | >>> from datetime import datetime, timedelta | 18 | >>> from datetime import datetime, timedelta |
426 | 19 | >>> from lp.services.messages.interfaces.message import IMessageSet | 19 | >>> from lp.services.messages.interfaces.message import IMessageSet |
427 | 20 | >>> from lp.bugs.interfaces.bug import IBugSet | 20 | >>> from lp.bugs.interfaces.bug import IBugSet |
429 | 21 | >>> from lp.bugs.adapters.bugchange import BugVisibilityChange | 21 | >>> from lp.bugs.adapters.bugchange import BugInformationTypeChange |
430 | 22 | >>> from lp.app.enums import InformationType | ||
431 | 22 | 23 | ||
432 | 23 | >>> ten_minutes_ago = ( | 24 | >>> ten_minutes_ago = ( |
433 | 24 | ... datetime.now(pytz.timezone('UTC')) - timedelta(minutes=10)) | 25 | ... datetime.now(pytz.timezone('UTC')) - timedelta(minutes=10)) |
434 | 25 | >>> sample_person = getUtility(ILaunchBag).user | 26 | >>> sample_person = getUtility(ILaunchBag).user |
435 | 26 | >>> bug_one = getUtility(IBugSet).get(1) | 27 | >>> bug_one = getUtility(IBugSet).get(1) |
436 | 27 | >>> bug_one.addChange( | 28 | >>> bug_one.addChange( |
440 | 28 | ... BugVisibilityChange( | 29 | ... BugInformationTypeChange( |
441 | 29 | ... ten_minutes_ago, sample_person, "private", | 30 | ... ten_minutes_ago, sample_person, "information_type", |
442 | 30 | ... False, True)) | 31 | ... InformationType.PUBLIC, InformationType.USERDATA)) |
443 | 31 | 32 | ||
444 | 32 | >>> from lp.bugs.interfaces.bugnotification import IBugNotificationSet | 33 | >>> from lp.bugs.interfaces.bugnotification import IBugNotificationSet |
445 | 33 | >>> from lp.bugs.scripts.bugnotification import ( | 34 | >>> from lp.bugs.scripts.bugnotification import ( |
446 | @@ -68,9 +69,9 @@ | |||
447 | 68 | >>> bug_one.linkMessage(comment) | 69 | >>> bug_one.linkMessage(comment) |
448 | 69 | <...> | 70 | <...> |
449 | 70 | >>> bug_one.addChange( | 71 | >>> bug_one.addChange( |
453 | 71 | ... BugVisibilityChange( | 72 | ... BugInformationTypeChange( |
454 | 72 | ... ten_minutes_ago, sample_person, "private", | 73 | ... ten_minutes_ago, sample_person, "information_type", |
455 | 73 | ... True, False)) | 74 | ... InformationType.USERDATA, InformationType.PUBLIC)) |
456 | 74 | >>> notifications = getUtility( | 75 | >>> notifications = getUtility( |
457 | 75 | ... IBugNotificationSet).getNotificationsToSend() | 76 | ... IBugNotificationSet).getNotificationsToSend() |
458 | 76 | >>> messages = [emails for notifications, omitted, emails in | 77 | >>> messages = [emails for notifications, omitted, emails in |
459 | 77 | 78 | ||
460 | === modified file 'lib/lp/bugs/scripts/tests/test_bugnotification.py' | |||
461 | --- lib/lp/bugs/scripts/tests/test_bugnotification.py 2012-09-18 18:36:09 +0000 | |||
462 | +++ lib/lp/bugs/scripts/tests/test_bugnotification.py 2012-10-15 03:36:20 +0000 | |||
463 | @@ -1,4 +1,4 @@ | |||
465 | 1 | # Copyright 2009-2010 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2009-2012 Canonical Ltd. This software is licensed under the |
466 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
467 | 3 | """Tests for construction bug notification emails for sending.""" | 3 | """Tests for construction bug notification emails for sending.""" |
468 | 4 | 4 | ||
469 | @@ -29,10 +29,10 @@ | |||
470 | 29 | BranchUnlinkedFromBug, | 29 | BranchUnlinkedFromBug, |
471 | 30 | BugAttachmentChange, | 30 | BugAttachmentChange, |
472 | 31 | BugDuplicateChange, | 31 | BugDuplicateChange, |
473 | 32 | BugInformationTypeChange, | ||
474 | 32 | BugTagsChange, | 33 | BugTagsChange, |
475 | 33 | BugTaskStatusChange, | 34 | BugTaskStatusChange, |
476 | 34 | BugTitleChange, | 35 | BugTitleChange, |
477 | 35 | BugVisibilityChange, | ||
478 | 36 | BugWatchAdded, | 36 | BugWatchAdded, |
479 | 37 | BugWatchRemoved, | 37 | BugWatchRemoved, |
480 | 38 | CveLinkedToBug, | 38 | CveLinkedToBug, |
481 | @@ -96,8 +96,6 @@ | |||
482 | 96 | implements(IBug) | 96 | implements(IBug) |
483 | 97 | 97 | ||
484 | 98 | duplicateof = None | 98 | duplicateof = None |
485 | 99 | private = False | ||
486 | 100 | security_related = False | ||
487 | 101 | information_type = InformationType.PUBLIC | 99 | information_type = InformationType.PUBLIC |
488 | 102 | messages = [] | 100 | messages = [] |
489 | 103 | 101 | ||
490 | @@ -691,9 +689,9 @@ | |||
491 | 691 | 689 | ||
492 | 692 | def change_other(self): | 690 | def change_other(self): |
493 | 693 | self.bug.addChange( | 691 | self.bug.addChange( |
497 | 694 | BugVisibilityChange( | 692 | BugInformationTypeChange( |
498 | 695 | self.ten_minutes_ago, self.person, "private", | 693 | self.ten_minutes_ago, self.person, "information_type", |
499 | 696 | False, True)) | 694 | InformationType.PUBLIC, InformationType.USERDATA)) |
500 | 697 | 695 | ||
501 | 698 | def test_change_seen(self): | 696 | def test_change_seen(self): |
502 | 699 | # A smoketest. | 697 | # A smoketest. |
503 | 700 | 698 | ||
504 | === modified file 'lib/lp/bugs/stories/bugs/xx-bug-activity.txt' | |||
505 | --- lib/lp/bugs/stories/bugs/xx-bug-activity.txt 2012-08-03 01:42:13 +0000 | |||
506 | +++ lib/lp/bugs/stories/bugs/xx-bug-activity.txt 2012-10-15 03:36:20 +0000 | |||
507 | @@ -98,44 +98,6 @@ | |||
508 | 98 | + A new title for this bug | 98 | + A new title for this bug |
509 | 99 | -------- | 99 | -------- |
510 | 100 | 100 | ||
511 | 101 | Alterations to a bug's privacy will show up as 'visibility' changes. | ||
512 | 102 | |||
513 | 103 | >>> admin_browser.open( | ||
514 | 104 | ... 'http://bugs.launchpad.dev/redfish/+bug/15/+secrecy') | ||
515 | 105 | >>> admin_browser.getControl("Private", index=1).selected = True | ||
516 | 106 | >>> admin_browser.getControl("Change").click() | ||
517 | 107 | |||
518 | 108 | >>> admin_browser.open('http://launchpad.dev/bugs/15') | ||
519 | 109 | >>> print_comments(admin_browser.contents) | ||
520 | 110 | Foo Bar | ||
521 | 111 | ... ago | ||
522 | 112 | summary: | ||
523 | 113 | - Nonsensical bugs are useless | ||
524 | 114 | + A new title for this bug | ||
525 | 115 | visibility: | ||
526 | 116 | public => private | ||
527 | 117 | -------- | ||
528 | 118 | |||
529 | 119 | Changes to a bug's security_related field will be displayed as | ||
530 | 120 | 'security vulnerability' changes, with values of 'yes' or 'no'. Note | ||
531 | 121 | that changes are grouped together if they occur at similar times, but | ||
532 | 122 | are still shown in the order the changes were made. | ||
533 | 123 | |||
534 | 124 | >>> admin_browser.open( | ||
535 | 125 | ... 'http://bugs.launchpad.dev/redfish/+bug/15/+secrecy') | ||
536 | 126 | >>> admin_browser.getControl("Private Security").selected = True | ||
537 | 127 | >>> admin_browser.getControl("Change").click() | ||
538 | 128 | |||
539 | 129 | >>> admin_browser.open('http://launchpad.dev/bugs/15') | ||
540 | 130 | >>> print_comments(admin_browser.contents) | ||
541 | 131 | Foo Bar (name16) | ||
542 | 132 | ... ago | ||
543 | 133 | summary: | ||
544 | 134 | ... | ||
545 | 135 | security vulnerability: | ||
546 | 136 | no => yes | ||
547 | 137 | -------- | ||
548 | 138 | |||
549 | 139 | Changes to the bug's description will simply be displayed as 'description: | 101 | Changes to the bug's description will simply be displayed as 'description: |
550 | 140 | updated', since such changes can be quite long. | 102 | updated', since such changes can be quite long. |
551 | 141 | 103 | ||
552 | @@ -310,31 +272,26 @@ | |||
553 | 310 | ubuntu | 272 | ubuntu |
554 | 311 | -------- | 273 | -------- |
555 | 312 | 274 | ||
557 | 313 | Changes to information_type are shown when the feature flag is set. | 275 | Changes to information_type are shown. |
558 | 314 | 276 | ||
569 | 315 | >>> from lp.services.features.testing import FeatureFixture | 277 | >>> admin_browser.open( |
570 | 316 | >>> feature_flag = { | 278 | ... "http://bugs.launchpad.dev/evolution/+bug/7/+secrecy") |
571 | 317 | ... 'disclosure.information_type_notifications.enabled': 'on'} | 279 | >>> admin_browser.getControl("Private", index=1).selected = True |
572 | 318 | >>> with FeatureFixture(feature_flag): | 280 | >>> admin_browser.getControl('Change').click() |
573 | 319 | ... admin_browser.open( | 281 | >>> admin_browser.open("http://bugs.launchpad.dev/evolution/+bug/7") |
574 | 320 | ... "http://bugs.launchpad.dev/evolution/+bug/7/+secrecy") | 282 | >>> print_comments(admin_browser.contents) |
565 | 321 | ... admin_browser.getControl("Private", index=1).selected = True | ||
566 | 322 | ... admin_browser.getControl('Change').click() | ||
567 | 323 | ... admin_browser.open("http://bugs.launchpad.dev/evolution/+bug/7") | ||
568 | 324 | ... print_comments(admin_browser.contents) | ||
575 | 325 | Foo Bar (name16) | 283 | Foo Bar (name16) |
576 | 326 | ... ago | 284 | ... ago |
577 | 327 | information type: | 285 | information type: |
578 | 328 | Public => Private | 286 | Public => Private |
579 | 329 | -------- | 287 | -------- |
580 | 330 | 288 | ||
588 | 331 | >>> with FeatureFixture(feature_flag): | 289 | >>> admin_browser.open( |
589 | 332 | ... admin_browser.open( | 290 | ... "http://bugs.launchpad.dev/jokosher/+bug/14/+secrecy") |
590 | 333 | ... "http://bugs.launchpad.dev/jokosher/+bug/14/+secrecy") | 291 | >>> admin_browser.getControl("Private", index=1).selected = True |
591 | 334 | ... admin_browser.getControl("Private", index=1).selected = True | 292 | >>> admin_browser.getControl('Change').click() |
592 | 335 | ... admin_browser.getControl('Change').click() | 293 | >>> admin_browser.open("http://bugs.launchpad.dev/jokosher/+bug/14") |
593 | 336 | ... admin_browser.open("http://bugs.launchpad.dev/jokosher/+bug/14") | 294 | >>> print_comments(admin_browser.contents) |
587 | 337 | ... print_comments(admin_browser.contents) | ||
594 | 338 | Foo Bar (name16) | 295 | Foo Bar (name16) |
595 | 339 | ... ago | 296 | ... ago |
596 | 340 | information type: | 297 | information type: |
597 | 341 | 298 | ||
598 | === modified file 'lib/lp/bugs/subscribers/bug.py' | |||
599 | --- lib/lp/bugs/subscribers/bug.py 2012-09-20 04:49:19 +0000 | |||
600 | +++ lib/lp/bugs/subscribers/bug.py 2012-10-15 03:36:20 +0000 | |||
601 | @@ -30,7 +30,6 @@ | |||
602 | 30 | from lp.registry.interfaces.person import IPerson | 30 | from lp.registry.interfaces.person import IPerson |
603 | 31 | from lp.services.config import config | 31 | from lp.services.config import config |
604 | 32 | from lp.services.database.sqlbase import block_implicit_flushes | 32 | from lp.services.database.sqlbase import block_implicit_flushes |
605 | 33 | from lp.services.features import getFeatureFlag | ||
606 | 34 | from lp.services.mail.helpers import get_contact_email_addresses | 33 | from lp.services.mail.helpers import get_contact_email_addresses |
607 | 35 | from lp.services.mail.sendmail import ( | 34 | from lp.services.mail.sendmail import ( |
608 | 36 | format_address, | 35 | format_address, |
609 | @@ -110,13 +109,8 @@ | |||
610 | 110 | IBugDelta if there are changes, or None if there were no changes. | 109 | IBugDelta if there are changes, or None if there were no changes. |
611 | 111 | """ | 110 | """ |
612 | 112 | changes = {} | 111 | changes = {} |
620 | 113 | fields = ["title", "description", "name"] | 112 | fields = ["title", "description", "name", "information_type", |
621 | 114 | if bool(getFeatureFlag( | 113 | "duplicateof", "tags"] |
615 | 115 | 'disclosure.information_type_notifications.enabled')): | ||
616 | 116 | fields.append('information_type') | ||
617 | 117 | else: | ||
618 | 118 | fields.extend(('private', 'security_related')) | ||
619 | 119 | fields.extend(("duplicateof", "tags")) | ||
622 | 120 | for field_name in fields: | 114 | for field_name in fields: |
623 | 121 | # fields for which we show old => new when their values change | 115 | # fields for which we show old => new when their values change |
624 | 122 | old_val = getattr(old_bug, field_name) | 116 | old_val = getattr(old_bug, field_name) |
625 | 123 | 117 | ||
626 | === modified file 'lib/lp/bugs/tests/test_bugchanges.py' | |||
627 | --- lib/lp/bugs/tests/test_bugchanges.py 2012-09-18 18:36:09 +0000 | |||
628 | +++ lib/lp/bugs/tests/test_bugchanges.py 2012-10-15 03:36:20 +0000 | |||
629 | @@ -25,7 +25,6 @@ | |||
630 | 25 | from lp.bugs.interfaces.cve import ICveSet | 25 | from lp.bugs.interfaces.cve import ICveSet |
631 | 26 | from lp.bugs.model.bugnotification import BugNotification | 26 | from lp.bugs.model.bugnotification import BugNotification |
632 | 27 | from lp.bugs.scripts.bugnotification import construct_email_notifications | 27 | from lp.bugs.scripts.bugnotification import construct_email_notifications |
633 | 28 | from lp.services.features.testing import FeatureFixture | ||
634 | 29 | from lp.services.librarian.browser import ProxiedLibraryFileAlias | 28 | from lp.services.librarian.browser import ProxiedLibraryFileAlias |
635 | 30 | from lp.services.webapp.interfaces import ILaunchBag | 29 | from lp.services.webapp.interfaces import ILaunchBag |
636 | 31 | from lp.services.webapp.publisher import canonical_url | 30 | from lp.services.webapp.publisher import canonical_url |
637 | @@ -47,8 +46,7 @@ | |||
638 | 47 | super(TestBugChanges, self).setUp('foo.bar@canonical.com') | 46 | super(TestBugChanges, self).setUp('foo.bar@canonical.com') |
639 | 48 | self.admin_user = getUtility(ILaunchBag).user | 47 | self.admin_user = getUtility(ILaunchBag).user |
640 | 49 | self.user = self.factory.makePerson( | 48 | self.user = self.factory.makePerson( |
643 | 50 | displayname='Arthur Dent', | 49 | displayname='Arthur Dent', selfgenerated_bugnotifications=True) |
642 | 51 | selfgenerated_bugnotifications=True) | ||
644 | 52 | self.product = self.factory.makeProduct( | 50 | self.product = self.factory.makeProduct( |
645 | 53 | owner=self.user, official_malone=True) | 51 | owner=self.user, official_malone=True) |
646 | 54 | self.bug = self.factory.makeBug(target=self.product, owner=self.user) | 52 | self.bug = self.factory.makeBug(target=self.product, owner=self.user) |
647 | @@ -57,11 +55,9 @@ | |||
648 | 57 | # Add some structural subscribers to show that notifications | 55 | # Add some structural subscribers to show that notifications |
649 | 58 | # aren't sent to LIFECYCLE subscribers by default. | 56 | # aren't sent to LIFECYCLE subscribers by default. |
650 | 59 | self.product_lifecycle_subscriber = self.newSubscriber( | 57 | self.product_lifecycle_subscriber = self.newSubscriber( |
653 | 60 | self.product, "product-lifecycle", | 58 | self.product, "product-lifecycle", BugNotificationLevel.LIFECYCLE) |
652 | 61 | BugNotificationLevel.LIFECYCLE) | ||
654 | 62 | self.product_metadata_subscriber = self.newSubscriber( | 59 | self.product_metadata_subscriber = self.newSubscriber( |
657 | 63 | self.product, "product-metadata", | 60 | self.product, "product-metadata", BugNotificationLevel.METADATA) |
656 | 64 | BugNotificationLevel.METADATA) | ||
658 | 65 | 61 | ||
659 | 66 | self.saveOldChanges() | 62 | self.saveOldChanges() |
660 | 67 | 63 | ||
661 | @@ -226,8 +222,7 @@ | |||
662 | 226 | self.assertEqual(activity.target, None) | 222 | self.assertEqual(activity.target, None) |
663 | 227 | 223 | ||
664 | 228 | unsubscribe_activity = dict( | 224 | unsubscribe_activity = dict( |
667 | 229 | whatchanged='removed subscriber Arthur Dent', | 225 | whatchanged='removed subscriber Arthur Dent', person=self.user) |
666 | 230 | person=self.user) | ||
668 | 231 | self.assertRecordedChange(expected_activity=unsubscribe_activity) | 226 | self.assertRecordedChange(expected_activity=unsubscribe_activity) |
669 | 232 | 227 | ||
670 | 233 | def test_unsubscribe_private_bug(self): | 228 | def test_unsubscribe_private_bug(self): |
671 | @@ -242,8 +237,7 @@ | |||
672 | 242 | self.saveOldChanges(bug=bug) | 237 | self.saveOldChanges(bug=bug) |
673 | 243 | bug.unsubscribe(subscriber, subscriber) | 238 | bug.unsubscribe(subscriber, subscriber) |
674 | 244 | unsubscribe_activity = dict( | 239 | unsubscribe_activity = dict( |
677 | 245 | whatchanged=u'removed subscriber Mom', | 240 | whatchanged=u'removed subscriber Mom', person=subscriber) |
676 | 246 | person=subscriber) | ||
678 | 247 | self.assertRecordedChange( | 241 | self.assertRecordedChange( |
679 | 248 | expected_activity=unsubscribe_activity, bug=bug) | 242 | expected_activity=unsubscribe_activity, bug=bug) |
680 | 249 | 243 | ||
681 | @@ -562,77 +556,17 @@ | |||
682 | 562 | self.bug.unlinkBranch(branch, self.user) | 556 | self.bug.unlinkBranch(branch, self.user) |
683 | 563 | self.assertRecordedChange() | 557 | self.assertRecordedChange() |
684 | 564 | 558 | ||
685 | 565 | def test_make_private(self): | ||
686 | 566 | # Marking a bug as private adds items to the bug's activity log | ||
687 | 567 | # and notifications. | ||
688 | 568 | bug_before_modification = Snapshot( | ||
689 | 569 | self.bug, providing=providedBy(self.bug)) | ||
690 | 570 | self.bug.setPrivate(True, self.user) | ||
691 | 571 | notify(ObjectModifiedEvent( | ||
692 | 572 | self.bug, bug_before_modification, ['private'], user=self.user)) | ||
693 | 573 | |||
694 | 574 | visibility_change_activity = { | ||
695 | 575 | 'person': self.user, | ||
696 | 576 | 'whatchanged': 'visibility', | ||
697 | 577 | 'oldvalue': 'public', | ||
698 | 578 | 'newvalue': 'private', | ||
699 | 579 | } | ||
700 | 580 | |||
701 | 581 | visibility_change_notification = { | ||
702 | 582 | 'text': '** Visibility changed to: Private', | ||
703 | 583 | 'person': self.user, | ||
704 | 584 | } | ||
705 | 585 | |||
706 | 586 | self.assertRecordedChange( | ||
707 | 587 | expected_activity=visibility_change_activity, | ||
708 | 588 | expected_notification=visibility_change_notification) | ||
709 | 589 | |||
710 | 590 | def test_make_public(self): | ||
711 | 591 | # Marking a bug as public adds items to the bug's activity log | ||
712 | 592 | # and notifications. | ||
713 | 593 | private_bug = self.factory.makeBug( | ||
714 | 594 | information_type=InformationType.USERDATA) | ||
715 | 595 | self.saveOldChanges(private_bug) | ||
716 | 596 | self.assertTrue(private_bug.private) | ||
717 | 597 | bug_before_modification = Snapshot( | ||
718 | 598 | private_bug, providing=providedBy(private_bug)) | ||
719 | 599 | private_bug.transitionToInformationType( | ||
720 | 600 | InformationType.PUBLIC, self.user) | ||
721 | 601 | notify(ObjectModifiedEvent( | ||
722 | 602 | private_bug, bug_before_modification, ['private'], | ||
723 | 603 | user=self.user)) | ||
724 | 604 | |||
725 | 605 | visibility_change_activity = { | ||
726 | 606 | 'person': self.user, | ||
727 | 607 | 'whatchanged': 'visibility', | ||
728 | 608 | 'oldvalue': 'private', | ||
729 | 609 | 'newvalue': 'public', | ||
730 | 610 | } | ||
731 | 611 | |||
732 | 612 | visibility_change_notification = { | ||
733 | 613 | 'text': '** Visibility changed to: Public', | ||
734 | 614 | 'person': self.user, | ||
735 | 615 | } | ||
736 | 616 | |||
737 | 617 | self.assertRecordedChange( | ||
738 | 618 | expected_activity=visibility_change_activity, | ||
739 | 619 | expected_notification=visibility_change_notification, | ||
740 | 620 | bug=private_bug) | ||
741 | 621 | |||
742 | 622 | def test_change_information_type(self): | 559 | def test_change_information_type(self): |
743 | 623 | # Changing the information type of a bug adds items to the activity | 560 | # Changing the information type of a bug adds items to the activity |
744 | 624 | # log and notifications. | 561 | # log and notifications. |
745 | 625 | bug = self.factory.makeBug() | 562 | bug = self.factory.makeBug() |
746 | 626 | self.saveOldChanges(bug=bug) | 563 | self.saveOldChanges(bug=bug) |
747 | 627 | feature_flag = { | ||
748 | 628 | 'disclosure.information_type_notifications.enabled': 'on'} | ||
749 | 629 | bug_before_modification = Snapshot(bug, providing=providedBy(bug)) | 564 | bug_before_modification = Snapshot(bug, providing=providedBy(bug)) |
756 | 630 | with FeatureFixture(feature_flag): | 565 | bug.transitionToInformationType( |
757 | 631 | bug.transitionToInformationType( | 566 | InformationType.PRIVATESECURITY, self.user) |
758 | 632 | InformationType.PRIVATESECURITY, self.user) | 567 | notify(ObjectModifiedEvent( |
759 | 633 | notify(ObjectModifiedEvent( | 568 | bug, bug_before_modification, ['information_type'], |
760 | 634 | bug, bug_before_modification, ['information_type'], | 569 | user=self.user)) |
755 | 635 | user=self.user)) | ||
761 | 636 | 570 | ||
762 | 637 | information_type_change_activity = { | 571 | information_type_change_activity = { |
763 | 638 | 'person': self.user, | 572 | 'person': self.user, |
764 | @@ -656,13 +590,9 @@ | |||
765 | 656 | person = self.factory.makePerson() | 590 | person = self.factory.makePerson() |
766 | 657 | bug = self.factory.makeBug(owner=person) | 591 | bug = self.factory.makeBug(owner=person) |
767 | 658 | self.saveOldChanges(bug=bug) | 592 | self.saveOldChanges(bug=bug) |
768 | 659 | feature_flag = { | ||
769 | 660 | 'disclosure.information_type_notifications.enabled': 'on'} | ||
770 | 661 | webservice = launchpadlib_for('test', person) | 593 | webservice = launchpadlib_for('test', person) |
771 | 662 | lp_bug = webservice.load(api_url(bug)) | 594 | lp_bug = webservice.load(api_url(bug)) |
775 | 663 | with FeatureFixture(feature_flag): | 595 | lp_bug.transitionToInformationType(information_type='Private Security') |
773 | 664 | lp_bug.transitionToInformationType( | ||
774 | 665 | information_type='Private Security') | ||
776 | 666 | 596 | ||
777 | 667 | information_type_change_activity = { | 597 | information_type_change_activity = { |
778 | 668 | 'person': person, | 598 | 'person': person, |
779 | @@ -800,7 +730,7 @@ | |||
780 | 800 | # This checks the activity's attribute and target attributes. | 730 | # This checks the activity's attribute and target attributes. |
781 | 801 | activity = self.bug.activity[-1] | 731 | activity = self.bug.activity[-1] |
782 | 802 | self.assertEqual(activity.attribute, 'attachments') | 732 | self.assertEqual(activity.attribute, 'attachments') |
784 | 803 | self.assertEqual(activity.target, None) | 733 | self.assertIsNone(activity.target) |
785 | 804 | 734 | ||
786 | 805 | attachment_added_activity = { | 735 | attachment_added_activity = { |
787 | 806 | 'person': self.user, | 736 | 'person': self.user, |
788 | @@ -1686,8 +1616,7 @@ | |||
789 | 1686 | 1616 | ||
790 | 1687 | self.assertRecordedChange( | 1617 | self.assertRecordedChange( |
791 | 1688 | expected_activity=expected_activity, | 1618 | expected_activity=expected_activity, |
794 | 1689 | expected_notification=expected_notification, | 1619 | expected_notification=expected_notification, bug=duplicate_bug) |
793 | 1690 | bug=duplicate_bug) | ||
795 | 1691 | 1620 | ||
796 | 1692 | def test_convert_to_question_no_comment(self): | 1621 | def test_convert_to_question_no_comment(self): |
797 | 1693 | # When a bug task is converted to a question, its status is | 1622 | # When a bug task is converted to a question, its status is |
798 | @@ -1754,8 +1683,7 @@ | |||
799 | 1754 | 1683 | ||
800 | 1755 | self.assertRecordedChange( | 1684 | self.assertRecordedChange( |
801 | 1756 | expected_activity=expected_activity, | 1685 | expected_activity=expected_activity, |
804 | 1757 | expected_notification=expected_notification, | 1686 | expected_notification=expected_notification, bug=new_bug) |
803 | 1758 | bug=new_bug) | ||
805 | 1759 | 1687 | ||
806 | 1760 | def test_description_changed_no_self_email(self): | 1688 | def test_description_changed_no_self_email(self): |
807 | 1761 | # Users who have selfgenerated_bugnotifications set to False | 1689 | # Users who have selfgenerated_bugnotifications set to False |
808 | @@ -1805,9 +1733,9 @@ | |||
809 | 1805 | # If a person has a structural METADATA subscription, | 1733 | # If a person has a structural METADATA subscription, |
810 | 1806 | # and a direct LIFECYCLE subscription, they should | 1734 | # and a direct LIFECYCLE subscription, they should |
811 | 1807 | # get no emails for a non-LIFECYCLE change (bug 713382). | 1735 | # get no emails for a non-LIFECYCLE change (bug 713382). |
815 | 1808 | self.bug.subscribe(self.product_metadata_subscriber, | 1736 | self.bug.subscribe( |
816 | 1809 | self.product_metadata_subscriber, | 1737 | self.product_metadata_subscriber, self.product_metadata_subscriber, |
817 | 1810 | level=BugNotificationLevel.LIFECYCLE) | 1738 | level=BugNotificationLevel.LIFECYCLE) |
818 | 1811 | self.changeAttribute( | 1739 | self.changeAttribute( |
819 | 1812 | self.bug, 'description', 'New description') | 1740 | self.bug, 'description', 'New description') |
820 | 1813 | 1741 | ||
821 | 1814 | 1742 | ||
822 | === modified file 'lib/lp/services/features/flags.py' | |||
823 | --- lib/lp/services/features/flags.py 2012-10-04 23:15:35 +0000 | |||
824 | +++ lib/lp/services/features/flags.py 2012-10-15 03:36:20 +0000 | |||
825 | @@ -220,13 +220,6 @@ | |||
826 | 220 | '', | 220 | '', |
827 | 221 | '', | 221 | '', |
828 | 222 | ''), | 222 | ''), |
829 | 223 | ('disclosure.information_type_notifications.enabled', | ||
830 | 224 | 'boolean', | ||
831 | 225 | ('If true, calculate and store bugchange notifications to reference ' | ||
832 | 226 | 'information_type rather than private/security_related.'), | ||
833 | 227 | '', | ||
834 | 228 | '', | ||
835 | 229 | ''), | ||
836 | 230 | ('auditor.enabled', | 223 | ('auditor.enabled', |
837 | 231 | 'boolean', | 224 | 'boolean', |
838 | 232 | 'If true, send audit data to an auditor instance.', | 225 | 'If true, send audit data to an auditor instance.', |
Thank you.