Merge lp:~stevenk/launchpad/destroy-old-bugactivity into lp:launchpad

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
Reviewer Review Type Date Requested Status
Curtis Hovey (community) code Approve
Review via email: mp+129339@code.launchpad.net

Commit message

Destroy Bug{Security,Visibility}Change and only make use of BugInformationTypeChange.

Description of the change

Destroy Bug{Security,Visibility}Change and only make use of BugInformationTypeChange.

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/schema/Makefile -- it will now use the current year when regenerating sampledata, like update-copyright does.

To post a comment you must log in.
Revision history for this message
Curtis Hovey (sinzui) wrote :

Thank you.

review: Approve (code)

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