Merge lp:~stevenk/launchpad/double-bugdelta-js into lp:launchpad

Proposed by Steve Kowalik on 2012-05-02
Status: Merged
Approved by: Steve Kowalik on 2012-05-02
Approved revision: no longer in the source branch.
Merged at revision: 15193
Proposed branch: lp:~stevenk/launchpad/double-bugdelta-js
Merge into: lp:launchpad
Diff against target: 237 lines (+67/-27)
5 files modified
lib/lp/bugs/browser/bug.py (+14/-2)
lib/lp/bugs/model/bug.py (+1/-4)
lib/lp/bugs/model/tests/test_bug.py (+0/-19)
lib/lp/bugs/tests/test_bugchanges.py (+50/-0)
lib/lp/bugs/tests/test_bugtaskflat_triggers.py (+2/-2)
To merge this branch: bzr merge lp:~stevenk/launchpad/double-bugdelta-js
Reviewer Review Type Date Requested Status
Ian Booth (community) 2012-05-02 Approve on 2012-05-02
Review via email: mp+104316@code.launchpad.net

Commit Message

Insist that IBug.transitionToInformationType() does not do notification.

Description of the Change

Currently, if IBug.transitionToInformationType() is called over the API, two notification events are fired -- one from lazr.restful via lazr.lifecycle, and one from transitionToInformationType() itself. This impacts the IChoiceSource that is used if the show_information_type_in_ui feature flag is enabled, since then the bug activity log shows two entires for the same change.

As a result, I have moved the notify() call into the submit method on Bug:+secrecy, like we do for everything else.

This did not impact the legacy code, since that overlay makes a submit call to Bug:+secrecy and does not make use of the API to change the privacy or security related-ness of a bug.

To post a comment you must log in.
Ian Booth (wallyworld) wrote :

Jolly good that you found this. Let's land the fucker and do more cleanup once legacy stuff is removed.

review: Approve
Ian Booth (wallyworld) wrote :

As discussed, please a a test before landing since the issue did not trigger any test failures.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/bugs/browser/bug.py'
2--- lib/lp/bugs/browser/bug.py 2012-04-23 09:28:45 +0000
3+++ lib/lp/bugs/browser/bug.py 2012-05-02 23:19:19 +0000
4@@ -854,8 +854,7 @@
5 # We handle duplicate changes by hand instead of leaving it to
6 # the usual machinery because we must use bug.markAsDuplicate().
7 bug = self.context.bug
8- bug_before_modification = Snapshot(
9- bug, providing=providedBy(bug))
10+ bug_before_modification = Snapshot(bug, providing=providedBy(bug))
11 duplicateof = data.pop('duplicateof')
12 bug.markAsDuplicate(duplicateof)
13 notify(
14@@ -864,6 +863,8 @@
15 self.updateBugFromData(data)
16
17
18+# XXX: This can move to using LaunchpadEditFormView when
19+# show_information_type_in_ui is removed.
20 class BugSecrecyEditView(LaunchpadFormView, BugSubscriptionPortletDetails):
21 """Form for marking a bug as a private/public."""
22
23@@ -942,12 +943,19 @@
24 """Update the bug."""
25 data = dict(data)
26 bug = self.context.bug
27+ bug_before_modification = Snapshot(bug, providing=providedBy(bug))
28 if bool(getFeatureFlag(
29 'disclosure.show_information_type_in_ui.enabled')):
30 information_type = data.pop('information_type')
31+ changed_fields = ['information_type']
32 else:
33+ changed_fields = []
34 private = data.pop('private', bug.private)
35+ if bug.private != private:
36+ changed_fields.append('private')
37 security_related = data.pop('security_related')
38+ if bug.security_related != security_related:
39+ changed_fields.append('security_related')
40 information_type = convert_to_information_type(
41 private, security_related)
42 user_will_be_subscribed = (
43@@ -957,6 +965,10 @@
44 information_type, self.user)
45 if changed:
46 self._handlePrivacyChanged(user_will_be_subscribed)
47+ notify(
48+ ObjectModifiedEvent(
49+ bug, bug_before_modification, changed_fields,
50+ user=self.user))
51 if self.request.is_ajax:
52 if changed:
53 return self._getSubscriptionDetails()
54
55=== modified file 'lib/lp/bugs/model/bug.py'
56--- lib/lp/bugs/model/bug.py 2012-04-25 21:55:08 +0000
57+++ lib/lp/bugs/model/bug.py 2012-05-02 23:19:19 +0000
58@@ -1726,7 +1726,6 @@
59 def transitionToInformationType(self, information_type, who,
60 from_api=False):
61 """See `IBug`."""
62- bug_before_modification = Snapshot(self, providing=providedBy(self))
63 if from_api and information_type == InformationType.PROPRIETARY:
64 raise BugCannotBePrivate(
65 "Cannot transition the information type to proprietary.")
66@@ -1749,7 +1748,6 @@
67 for attachment in self.attachments_unpopulated:
68 attachment.libraryfile.restricted = (
69 information_type in PRIVATE_INFORMATION_TYPES)
70- self.updateHeat()
71
72 # There are several people we need to ensure are subscribed.
73 # If the information type is userdata, we need to check for bug
74@@ -1785,12 +1783,11 @@
75 self.subscribe(s, who)
76
77 self.information_type = information_type
78+ self.updateHeat()
79 # Set the legacy attributes for now.
80 self._private = information_type in PRIVATE_INFORMATION_TYPES
81 self._security_related = (
82 information_type in SECURITY_INFORMATION_TYPES)
83- notify(ObjectModifiedEvent(
84- self, bug_before_modification, ['information_type'], user=who))
85 return True
86
87 def getRequiredSubscribers(self, information_type, who):
88
89=== modified file 'lib/lp/bugs/model/tests/test_bug.py'
90--- lib/lp/bugs/model/tests/test_bug.py 2012-04-29 22:54:49 +0000
91+++ lib/lp/bugs/model/tests/test_bug.py 2012-05-02 23:19:19 +0000
92@@ -813,25 +813,6 @@
93 )
94 [self.assertEqual(m[1], m[0].information_type) for m in mapping]
95
96- def test_information_type_modified_event(self):
97- # When a bug's information_type is changed, the expected object
98- # modified event is published.
99- self.event_edited_fields = []
100- self.event_object = None
101-
102- def event_callback(object, event):
103- self.event_edited_fields = event.edited_fields
104- self.event_object = event.object
105-
106- TestEventListener(IBug, IObjectModifiedEvent, event_callback)
107- owner = self.factory.makePerson()
108- bug = self.factory.makeBug(
109- private=True, security_related=True, owner=owner)
110- with person_logged_in(owner):
111- bug.transitionToInformationType(InformationType.PUBLIC, owner)
112- self.assertEqual(['information_type'], self.event_edited_fields)
113- self.assertEqual(bug, self.event_object)
114-
115 def test_private_to_public_information_type(self):
116 # A private bug transitioning to public has the correct information
117 # type.
118
119=== modified file 'lib/lp/bugs/tests/test_bugchanges.py'
120--- lib/lp/bugs/tests/test_bugchanges.py 2012-05-02 12:45:53 +0000
121+++ lib/lp/bugs/tests/test_bugchanges.py 2012-05-02 23:19:19 +0000
122@@ -30,7 +30,9 @@
123 from lp.services.webapp.interfaces import ILaunchBag
124 from lp.services.webapp.publisher import canonical_url
125 from lp.testing import (
126+ api_url,
127 celebrity_logged_in,
128+ launchpadlib_for,
129 login_person,
130 person_logged_in,
131 TestCaseWithFactory,
132@@ -561,7 +563,11 @@
133 def test_make_private(self):
134 # Marking a bug as private adds items to the bug's activity log
135 # and notifications.
136+ bug_before_modification = Snapshot(
137+ self.bug, providing=providedBy(self.bug))
138 self.bug.setPrivate(True, self.user)
139+ notify(ObjectModifiedEvent(
140+ self.bug, bug_before_modification, ['private'], user=self.user))
141
142 visibility_change_activity = {
143 'person': self.user,
144@@ -586,7 +592,12 @@
145 self.saveOldChanges(private_bug)
146 self.assertTrue(private_bug.private)
147
148+ bug_before_modification = Snapshot(
149+ private_bug, providing=providedBy(private_bug))
150 private_bug.setPrivate(False, self.user)
151+ notify(ObjectModifiedEvent(
152+ private_bug, bug_before_modification, ['private'],
153+ user=self.user))
154
155 visibility_change_activity = {
156 'person': self.user,
157@@ -612,9 +623,13 @@
158 self.saveOldChanges(bug=bug)
159 feature_flag = {
160 'disclosure.show_information_type_in_ui.enabled': 'on'}
161+ bug_before_modification = Snapshot(bug, providing=providedBy(bug))
162 with FeatureFixture(feature_flag):
163 bug.transitionToInformationType(
164 InformationType.EMBARGOEDSECURITY, self.user)
165+ notify(ObjectModifiedEvent(
166+ bug, bug_before_modification, ['information_type'],
167+ user=self.user))
168
169 information_type_change_activity = {
170 'person': self.user,
171@@ -641,9 +656,13 @@
172 feature_flags = {
173 'disclosure.show_information_type_in_ui.enabled': 'on',
174 'disclosure.display_userdata_as_private.enabled': 'on'}
175+ bug_before_modification = Snapshot(bug, providing=providedBy(bug))
176 with FeatureFixture(feature_flags):
177 bug.transitionToInformationType(
178 InformationType.USERDATA, self.user)
179+ notify(ObjectModifiedEvent(
180+ bug, bug_before_modification, ['information_type'],
181+ user=self.user))
182
183 information_type_change_activity = {
184 'person': self.user,
185@@ -660,6 +679,37 @@
186 expected_notification=information_type_change_notification,
187 bug=bug)
188
189+ def test_change_information_type_using_api(self):
190+ # Changing the information type of a bug adds items to the activity
191+ # log and notifications.
192+ person = self.factory.makePerson()
193+ bug = self.factory.makeBug(owner=person)
194+ self.saveOldChanges(bug=bug)
195+ feature_flag = {
196+ 'disclosure.show_information_type_in_ui.enabled': 'on'}
197+ webservice = launchpadlib_for('test', person)
198+ lp_bug = webservice.load(api_url(bug))
199+ with FeatureFixture(feature_flag):
200+ lp_bug.transitionToInformationType(
201+ information_type='Embargoed Security')
202+
203+ information_type_change_activity = {
204+ 'person': person,
205+ 'whatchanged': 'information type',
206+ 'oldvalue': 'Public',
207+ 'newvalue': 'Embargoed Security',
208+ }
209+ information_type_change_notification = {
210+ 'text': '** Information type changed from Public to Embargoed '
211+ 'Security',
212+ 'person': person,
213+ }
214+ with person_logged_in(person):
215+ self.assertRecordedChange(
216+ expected_activity=information_type_change_activity,
217+ expected_notification=information_type_change_notification,
218+ bug=bug)
219+
220 def test_tags_added(self):
221 # Adding tags to a bug will add BugActivity and BugNotification
222 # entries.
223
224=== modified file 'lib/lp/bugs/tests/test_bugtaskflat_triggers.py'
225--- lib/lp/bugs/tests/test_bugtaskflat_triggers.py 2012-04-03 06:14:09 +0000
226+++ lib/lp/bugs/tests/test_bugtaskflat_triggers.py 2012-05-02 23:19:19 +0000
227@@ -316,8 +316,8 @@
228 task = self.makeLoggedInTask(private=True)
229 with self.bugtaskflat_is_updated(
230 task, [
231- 'information_type', 'date_last_updated', 'heat',
232- 'access_policies', 'access_grants']):
233+ 'information_type', 'heat', 'access_policies',
234+ 'access_grants']):
235 task.bug.setPrivate(False, task.owner)
236
237 def test_bug_change_unflattened(self):