Merge lp:~stevenk/launchpad/drop-disclosure-feature-flags into lp:launchpad

Proposed by Steve Kowalik
Status: Merged
Approved by: Steve Kowalik
Approved revision: no longer in the source branch.
Merged at revision: 15869
Proposed branch: lp:~stevenk/launchpad/drop-disclosure-feature-flags
Merge into: lp:launchpad
Diff against target: 1942 lines (+289/-711)
28 files modified
lib/lp/app/browser/lazrjs.py (+1/-4)
lib/lp/app/browser/tests/test_inlineeditpickerwidget.py (+1/-11)
lib/lp/app/browser/tests/test_vocabulary.py (+11/-17)
lib/lp/app/javascript/picker/picker_patcher.js (+8/-13)
lib/lp/app/widgets/popup.py (+1/-9)
lib/lp/app/widgets/tests/test_popup.py (+2/-13)
lib/lp/bugs/doc/bugsubscription.txt (+6/-0)
lib/lp/bugs/model/bug.py (+4/-16)
lib/lp/bugs/model/bugtask.py (+5/-8)
lib/lp/bugs/model/tests/test_bug.py (+2/-2)
lib/lp/bugs/model/tests/test_bugsummary.py (+3/-6)
lib/lp/bugs/model/tests/test_bugtask.py (+0/-1)
lib/lp/bugs/model/tests/test_bugtasksearch.py (+0/-3)
lib/lp/code/model/branch.py (+4/-8)
lib/lp/code/model/tests/test_branchnamespace.py (+0/-6)
lib/lp/registry/browser/distribution.py (+1/-7)
lib/lp/registry/browser/pillar.py (+0/-27)
lib/lp/registry/browser/product.py (+1/-7)
lib/lp/registry/browser/tests/test_pillar_sharing.py (+128/-217)
lib/lp/registry/javascript/sharing/pillarsharingview.js (+3/-19)
lib/lp/registry/javascript/sharing/sharingdetailsview.js (+1/-15)
lib/lp/registry/javascript/sharing/tests/test_pillarsharingview.js (+0/-19)
lib/lp/registry/javascript/sharing/tests/test_sharingdetailsview.js (+0/-11)
lib/lp/registry/model/teammembership.py (+5/-8)
lib/lp/registry/services/sharingservice.py (+4/-28)
lib/lp/registry/services/tests/test_sharingservice.py (+97/-200)
lib/lp/registry/tests/test_teammembership.py (+1/-2)
lib/lp/services/features/flags.py (+0/-34)
To merge this branch: bzr merge lp:~stevenk/launchpad/drop-disclosure-feature-flags
Reviewer Review Type Date Requested Status
William Grant code Approve
Review via email: mp+121523@code.launchpad.net

Commit message

Destroy five disclosure feature flags.

Description of the change

Destroy all disclosure feature flags I can, namely:

* disclosure.add-team-person-picker.enabled
* disclosure.enhanced_sharing.enabled
* disclosure.enhanced_sharing_details.enabled
* disclosure.enhanced_sharing.writable
* disclosure.unsubscribe_jobs.enabled

There were a bunch of tests that tested that things didn't work or raised Unauthorized which I just removed. It seems like to me that the test changes in lib/lp/bugs/model/tests/test_bug.py were dependent on the unsubscription happening with the feature flag off, and I've changed the check calls to filter the results by who has access.

The bugsubscription.txt case seems to be more contrived. We subscribe Mark, and then switch the bug to private and check he isn't subscribed, and then flip the bug to public, and he still isn't subscribed.

To post a comment you must log in.
Revision history for this message
William Grant (wgrant) wrote :

69 @property
70 def enhanced_picker(self):
71 - flag = getFeatureFlag(
72 - "disclosure.add-team-person-picker.enabled")
73 - return flag and self.show_create_team_link
74 + return self.show_create_team_link

Can you get rid of enhanced_picker entirely?

I'd also like to see a deeper investigation/explanation of the bugsubscription.txt changes.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/app/browser/lazrjs.py'
2--- lib/lp/app/browser/lazrjs.py 2012-08-14 01:57:17 +0000
3+++ lib/lp/app/browser/lazrjs.py 2012-08-28 04:39:25 +0000
4@@ -40,7 +40,6 @@
5 get_person_picker_entry_metadata,
6 vocabulary_filters,
7 )
8-from lp.services.features import getFeatureFlag
9 from lp.services.propertycache import cachedproperty
10 from lp.services.webapp.interfaces import ILaunchBag
11 from lp.services.webapp.publisher import canonical_url
12@@ -423,9 +422,7 @@
13
14 @property
15 def show_create_team(self):
16- return (self._show_create_team
17- and getFeatureFlag(
18- "disclosure.add-team-person-picker.enabled"))
19+ return self._show_create_team
20
21 def getConfig(self):
22 config = super(InlinePersonEditPickerWidget, self).getConfig()
23
24=== modified file 'lib/lp/app/browser/tests/test_inlineeditpickerwidget.py'
25--- lib/lp/app/browser/tests/test_inlineeditpickerwidget.py 2012-06-21 06:50:10 +0000
26+++ lib/lp/app/browser/tests/test_inlineeditpickerwidget.py 2012-08-28 04:39:25 +0000
27@@ -15,7 +15,6 @@
28 InlineEditPickerWidget,
29 InlinePersonEditPickerWidget,
30 )
31-from lp.services.features.testing import FeatureFixture
32 from lp.testing import (
33 login_person,
34 TestCaseWithFactory,
35@@ -118,18 +117,9 @@
36 login_person(self.factory.makePerson())
37 self.assertFalse(widget.config['show_assign_me_button'])
38
39- def test_show_create_team_link_with_feature_flag(self):
40- with FeatureFixture(
41- {'disclosure.add-team-person-picker.enabled': 'true'}):
42- widget = self.getWidget(
43- None, vocabulary='ValidPersonOrTeam', required=True,
44- show_create_team=True)
45- login_person(self.factory.makePerson())
46- self.assertTrue(widget.config['show_create_team'])
47-
48 def test_show_create_team_link(self):
49 widget = self.getWidget(
50 None, vocabulary='ValidPersonOrTeam', required=True,
51 show_create_team=True)
52 login_person(self.factory.makePerson())
53- self.assertFalse(widget.config['show_create_team'])
54+ self.assertTrue(widget.config['show_create_team'])
55
56=== modified file 'lib/lp/app/browser/tests/test_vocabulary.py'
57--- lib/lp/app/browser/tests/test_vocabulary.py 2012-08-13 19:34:10 +0000
58+++ lib/lp/app/browser/tests/test_vocabulary.py 2012-08-28 04:39:25 +0000
59@@ -135,40 +135,35 @@
60 self.assertEqual('sprite person', entry.css)
61 self.assertEqual('sprite new-window', entry.link_css)
62
63- def test_PersonPickerEntrySourceAdapter_enhanced_picker_user(self):
64- # The enhanced person picker provides more information for users.
65+ def test_PersonPickerEntrySourceAdapter_user(self):
66+ # The person picker provides more information for users.
67 person = self.factory.makePerson(email='snarf@eg.dom', name='snarf')
68 creation_date = datetime(
69 2005, 01, 30, 0, 0, 0, 0, pytz.timezone('UTC'))
70 removeSecurityProxy(person).datecreated = creation_date
71 getUtility(IIrcIDSet).new(person, 'eg.dom', 'snarf')
72 getUtility(IIrcIDSet).new(person, 'ex.dom', 'pting')
73- entry = get_picker_entry(
74- person, None, enhanced_picker_enabled=True,
75- picker_expander_enabled=True)
76+ entry = get_picker_entry(person, None, picker_expander_enabled=True)
77 self.assertEqual('http://launchpad.dev/~snarf', entry.alt_title_link)
78 self.assertEqual(
79 ['snarf on eg.dom, pting on ex.dom', 'Member since 2005-01-30'],
80 entry.details)
81
82- def test_PersonPickerEntrySourceAdapter_enhanced_picker_team(self):
83- # The enhanced person picker provides more information for teams.
84+ def test_PersonPickerEntrySourceAdapter_team(self):
85+ # The person picker provides more information for teams.
86 team = self.factory.makeTeam(email='fnord@eg.dom', name='fnord')
87- entry = get_picker_entry(
88- team, None, enhanced_picker_enabled=True,
89- picker_expander_enabled=True)
90+ entry = get_picker_entry(team, None, picker_expander_enabled=True)
91 self.assertEqual('http://launchpad.dev/~fnord', entry.alt_title_link)
92 self.assertEqual(['Team members: 1'], entry.details)
93
94- def test_PersonPickerEntryAdapter_enhanced_picker_enabled_badges(self):
95- # The enhanced person picker provides affiliation information.
96+ def test_PersonPickerEntryAdapter_badges(self):
97+ # The person picker provides affiliation information.
98 person = self.factory.makePerson(email='snarf@eg.dom', name='snarf')
99 project = self.factory.makeProduct(
100 name='fnord', owner=person, bug_supervisor=person)
101 bugtask = self.factory.makeBugTask(target=project)
102 entry = get_picker_entry(
103- person, bugtask, enhanced_picker_enabled=True,
104- picker_expander_enabled=True,
105+ person, bugtask, picker_expander_enabled=True,
106 personpicker_affiliation_enabled=True)
107 self.assertEqual(3, len(entry.badges))
108 self.assertEqual('/@@/product-badge', entry.badges[0]['url'])
109@@ -182,13 +177,12 @@
110 self.assertEqual('bug supervisor', entry.badges[2]['role'])
111
112 def test_PersonPickerEntryAdapter_badges_without_IHasAffiliation(self):
113- # The enhanced person picker handles objects that do not support
114+ # The person picker handles objects that do not support
115 # IHasAffilliation.
116 person = self.factory.makePerson(email='snarf@eg.dom', name='snarf')
117 thing = object()
118 entry = get_picker_entry(
119- person, thing, enhanced_picker_enabled=True,
120- picker_expander_enabled=True,
121+ person, thing, picker_expander_enabled=True,
122 personpicker_affiliation_enabled=True)
123 self.assertIsNot(None, entry)
124
125
126=== modified file 'lib/lp/app/javascript/picker/picker_patcher.js'
127--- lib/lp/app/javascript/picker/picker_patcher.js 2012-07-07 14:00:30 +0000
128+++ lib/lp/app/javascript/picker/picker_patcher.js 2012-08-28 04:39:25 +0000
129@@ -25,19 +25,14 @@
130 return;
131 }
132 var picker_span = show_widget_node.get('parentNode');
133- if (config.enhanced_picker) {
134- var new_node = Y.Node.create('<span>(<a href="#"></a>)</span>');
135- show_widget_node = new_node.one('a');
136- show_widget_node
137- .set('id', show_widget_id)
138- .addClass('js-action')
139- .set('text', 'Choose\u2026');
140- picker_span.empty();
141- picker_span.appendChild(new_node);
142- } else {
143- show_widget_node.set('text', 'Choose\u2026');
144- show_widget_node.addClass('js-action');
145- }
146+ var new_node = Y.Node.create('<span>(<a href="#"></a>)</span>');
147+ show_widget_node = new_node.one('a');
148+ show_widget_node
149+ .set('id', show_widget_id)
150+ .addClass('js-action')
151+ .set('text', 'Choose\u2026');
152+ picker_span.empty();
153+ picker_span.appendChild(new_node);
154 picker_span.removeClass('hidden');
155 show_widget_node.on('click', function (e) {
156 if (picker === null) {
157
158=== modified file 'lib/lp/app/widgets/popup.py'
159--- lib/lp/app/widgets/popup.py 2012-07-07 14:00:30 +0000
160+++ lib/lp/app/widgets/popup.py 2012-08-28 04:39:25 +0000
161@@ -23,7 +23,6 @@
162 get_person_picker_entry_metadata,
163 vocabulary_filters,
164 )
165-from lp.services.features import getFeatureFlag
166 from lp.services.propertycache import cachedproperty
167 from lp.services.webapp import canonical_url
168
169@@ -58,12 +57,6 @@
170 # Defaults to self.vocabulary.displayname.
171 header = None
172
173- @property
174- def enhanced_picker(self):
175- flag = getFeatureFlag(
176- "disclosure.add-team-person-picker.enabled")
177- return flag and self.show_create_team_link
178-
179 @cachedproperty
180 def matches(self):
181 """Return a list of matches (as ITokenizedTerm) to whatever the
182@@ -152,8 +145,7 @@
183 vocabulary_filters=self.vocabulary_filters,
184 input_element=self.input_id,
185 show_widget_id=self.show_widget_id,
186- enhanced_picker=self.enhanced_picker,
187- show_create_team=self.enhanced_picker)
188+ show_create_team=self.show_create_team_link)
189
190 @property
191 def json_config(self):
192
193=== modified file 'lib/lp/app/widgets/tests/test_popup.py'
194--- lib/lp/app/widgets/tests/test_popup.py 2012-06-28 01:27:06 +0000
195+++ lib/lp/app/widgets/tests/test_popup.py 2012-08-28 04:39:25 +0000
196@@ -13,7 +13,6 @@
197 PersonPickerWidget,
198 VocabularyPickerWidget,
199 )
200-from lp.services.features.testing import FeatureFixture
201 from lp.services.webapp.servers import LaunchpadTestRequest
202 from lp.testing import TestCaseWithFactory
203 from lp.testing.layers import DatabaseFunctionalLayer
204@@ -170,24 +169,14 @@
205 self.assertFalse(person_picker_widget.config['show_remove_button'])
206
207 def test_create_team_link(self):
208- # The person picker widget shows a create team link if the feature flag
209- # is on.
210+ # The person picker widget shows a create team link.
211 field = ITest['test_valid.item']
212 bound_field = field.bind(self.context)
213
214- with FeatureFixture(
215- {'disclosure.add-team-person-picker.enabled': 'true'}):
216- picker_widget = PersonPickerWidget(
217- bound_field, self.vocabulary, self.request)
218- picker_widget.show_create_team_link = True
219- self.assertTrue(picker_widget.config['show_create_team'])
220- self.assertTrue(picker_widget.config['enhanced_picker'])
221-
222 picker_widget = PersonPickerWidget(
223 bound_field, self.vocabulary, self.request)
224 picker_widget.show_create_team_link = True
225- self.assertFalse(picker_widget.config['show_create_team'])
226- self.assertFalse(picker_widget.config['enhanced_picker'])
227+ self.assertTrue(picker_widget.config['show_create_team'])
228
229 def test_widget_personvalue_meta(self):
230 # The person picker has the correct meta value for a person value.
231
232=== modified file 'lib/lp/bugs/doc/bugsubscription.txt'
233--- lib/lp/bugs/doc/bugsubscription.txt 2012-08-22 23:02:40 +0000
234+++ lib/lp/bugs/doc/bugsubscription.txt 2012-08-28 04:39:25 +0000
235@@ -364,6 +364,7 @@
236
237 >>> print_displayname(linux_source_bug.getDirectSubscribers())
238 Foo Bar
239+ Mark Shuttleworth
240 Robert Collins
241
242 Direct subscriptions always take precedence over indirect subscriptions.
243@@ -375,6 +376,7 @@
244
245 >>> print_displayname(linux_source_bug.getDirectSubscribers())
246 Foo Bar
247+ Mark Shuttleworth
248 Robert Collins
249
250 >>> print_displayname(linux_source_bug.getIndirectSubscribers())
251@@ -398,6 +400,7 @@
252 >>> addresses = recipients.getEmails()
253 >>> [(address, recipients.getReason(address)[1]) for address in addresses]
254 [('foo.bar@canonical.com', 'Subscriber'),
255+ ('mark@example.com', 'Subscriber'),
256 ('no-priv@canonical.com', u'Subscriber (linux-source-2.6.15 in Ubuntu)'),
257 ('robertc@robertcollins.net', 'Subscriber'),
258 ('test@canonical.com', 'Assignee')]
259@@ -411,6 +414,7 @@
260 >>> addresses = recipients.getEmails()
261 >>> [(address, recipients.getReason(address)[1]) for address in addresses]
262 [('foo.bar@canonical.com', 'Subscriber'),
263+ ('mark@example.com', 'Subscriber'),
264 ('robertc@robertcollins.net', 'Subscriber'),
265 ('test@canonical.com', 'Assignee')]
266
267@@ -424,6 +428,7 @@
268 >>> addresses = recipients.getEmails()
269 >>> [(address, recipients.getReason(address)[1]) for address in addresses]
270 [('foo.bar@canonical.com', 'Subscriber'),
271+ ('mark@example.com', 'Subscriber'),
272 ('robertc@robertcollins.net', 'Subscriber'),
273 ('test@canonical.com', 'Assignee')]
274
275@@ -435,6 +440,7 @@
276 >>> addresses = recipients.getEmails()
277 >>> [(address, recipients.getReason(address)[1]) for address in addresses]
278 [('foo.bar@canonical.com', 'Subscriber'),
279+ ('mark@example.com', 'Subscriber'),
280 ('no-priv@canonical.com', u'Subscriber (linux-source-2.6.15 in Ubuntu)'),
281 ('robertc@robertcollins.net', 'Subscriber'),
282 ('test@canonical.com', 'Assignee')]
283
284=== modified file 'lib/lp/bugs/model/bug.py'
285--- lib/lp/bugs/model/bug.py 2012-08-23 04:20:48 +0000
286+++ lib/lp/bugs/model/bug.py 2012-08-28 04:39:25 +0000
287@@ -200,7 +200,6 @@
288 sqlvalues,
289 )
290 from lp.services.database.stormbase import StormBase
291-from lp.services.features import getFeatureFlag
292 from lp.services.fields import DuplicateBug
293 from lp.services.helpers import shortlist
294 from lp.services.librarian.interfaces import ILibraryFileAliasSet
295@@ -1766,18 +1765,10 @@
296 if pillar.driver in subscribers and pillar != ubuntu:
297 required_subscribers.add(pillar.driver)
298 service = getUtility(IService, 'sharing')
299- subscribers_to_remove = set(service.getPeopleWithoutAccess(
300- self, subscribers)).difference(required_subscribers)
301 if len(required_subscribers):
302 service.ensureAccessGrants(
303 required_subscribers, who, bugs=[self],
304 ignore_permissions=True)
305- # There is a job to do the unsubscribe, but it's behind a
306- # flag. If that flag is not set, do it manually.
307- if len(subscribers_to_remove) and not bool(
308- getFeatureFlag('disclosure.unsubscribe_jobs.enabled')):
309- for s in subscribers_to_remove:
310- self.unsubscribe(s, who, ignore_permissions=True)
311
312 # Add the required subscribers, but not if they are all already
313 # subscribed via a team.
314@@ -1788,13 +1779,10 @@
315
316 self.updateHeat()
317
318- flag = 'disclosure.unsubscribe_jobs.enabled'
319- if bool(getFeatureFlag(flag)):
320- # As a result of the transition, some subscribers may no longer
321- # have access to the bug. We need to run a job to remove any such
322- # subscriptions.
323- getUtility(IRemoveArtifactSubscriptionsJobSource).create(
324- who, [self])
325+ # As a result of the transition, some subscribers may no longer
326+ # have access to the bug. We need to run a job to remove any such
327+ # subscriptions.
328+ getUtility(IRemoveArtifactSubscriptionsJobSource).create(who, [self])
329
330 return True
331
332
333=== modified file 'lib/lp/bugs/model/bugtask.py'
334--- lib/lp/bugs/model/bugtask.py 2012-08-24 01:17:35 +0000
335+++ lib/lp/bugs/model/bugtask.py 2012-08-28 04:39:25 +0000
336@@ -141,7 +141,6 @@
337 SQLBase,
338 sqlvalues,
339 )
340-from lp.services.features import getFeatureFlag
341 from lp.services.helpers import shortlist
342 from lp.services.propertycache import get_property_cache
343 from lp.services.searchbuilder import any
344@@ -1140,13 +1139,11 @@
345 self.maybeConfirm()
346 # END TEMPORARY BIT FOR BUGTASK AUTOCONFIRM FEATURE FLAG.
347
348- flag = 'disclosure.unsubscribe_jobs.enabled'
349- if bool(getFeatureFlag(flag)):
350- # As a result of the transition, some subscribers may no longer
351- # have access to the parent bug. We need to run a job to remove any
352- # such subscriptions.
353- getUtility(IRemoveArtifactSubscriptionsJobSource).create(
354- user, [self.bug], pillar=target_before_change.pillar)
355+ # As a result of the transition, some subscribers may no longer
356+ # have access to the parent bug. We need to run a job to remove any
357+ # such subscriptions.
358+ getUtility(IRemoveArtifactSubscriptionsJobSource).create(
359+ user, [self.bug], pillar=target_before_change.pillar)
360
361 def updateTargetNameCache(self, newtarget=None):
362 """See `IBugTask`."""
363
364=== modified file 'lib/lp/bugs/model/tests/test_bug.py'
365--- lib/lp/bugs/model/tests/test_bug.py 2012-08-23 04:20:48 +0000
366+++ lib/lp/bugs/model/tests/test_bug.py 2012-08-28 04:39:25 +0000
367@@ -639,7 +639,7 @@
368 who = self.factory.makePerson(name='who')
369 bug.transitionToInformationType(
370 InformationType.PRIVATESECURITY, who=who)
371- subscribers = bug.getDirectSubscribers()
372+ subscribers = bug.getDirectSubscribers(filter_visible=True)
373 expected_subscribers = set((
374 default_bugtask.pillar.driver, bug_owner, who))
375 self.assertContentEqual(expected_subscribers, subscribers)
376@@ -662,7 +662,7 @@
377 bug.subscribe(subscriber, bug_owner)
378 who = self.factory.makePerson(name='who')
379 bug.transitionToInformationType(InformationType.USERDATA, who)
380- subscribers = bug.getDirectSubscribers()
381+ subscribers = bug.getDirectSubscribers(filter_visible=True)
382 expected_subscribers = set((
383 default_bugtask.pillar.bug_supervisor,
384 default_bugtask.pillar.driver,
385
386=== modified file 'lib/lp/bugs/model/tests/test_bugsummary.py'
387--- lib/lp/bugs/model/tests/test_bugsummary.py 2012-08-08 11:48:29 +0000
388+++ lib/lp/bugs/model/tests/test_bugsummary.py 2012-08-28 04:39:25 +0000
389@@ -28,7 +28,6 @@
390 SharingPermission,
391 )
392 from lp.services.database.lpstorm import IMasterStore
393-from lp.services.features.testing import FeatureFixture
394 from lp.testing import TestCaseWithFactory
395 from lp.testing.dbuser import switch_dbuser
396 from lp.testing.layers import LaunchpadZopelessLayer
397@@ -192,11 +191,9 @@
398 person_b = self.factory.makePerson()
399 person_c = self.factory.makePerson()
400 product = self.factory.makeProduct()
401- with FeatureFixture(
402- {'disclosure.enhanced_sharing.writable': 'true'}):
403- getUtility(IService, 'sharing').sharePillarInformation(
404- product, person_c, product.owner,
405- {InformationType.USERDATA: SharingPermission.ALL})
406+ getUtility(IService, 'sharing').sharePillarInformation(
407+ product, person_c, product.owner,
408+ {InformationType.USERDATA: SharingPermission.ALL})
409 bug = self.factory.makeBug(target=product, owner=person_b)
410
411 bug.subscribe(person=person_a, subscribed_by=person_a)
412
413=== modified file 'lib/lp/bugs/model/tests/test_bugtask.py'
414--- lib/lp/bugs/model/tests/test_bugtask.py 2012-08-27 23:58:18 +0000
415+++ lib/lp/bugs/model/tests/test_bugtask.py 2012-08-28 04:39:25 +0000
416@@ -2678,7 +2678,6 @@
417
418 def setUp(self):
419 self.useFixture(FeatureFixture({
420- 'disclosure.unsubscribe_jobs.enabled': 'true',
421 'jobs.celery.enabled_classes': 'RemoveArtifactSubscriptionsJob',
422 }))
423 super(TestTransitionsRemovesSubscribersJob, self).setUp()
424
425=== modified file 'lib/lp/bugs/model/tests/test_bugtasksearch.py'
426--- lib/lp/bugs/model/tests/test_bugtasksearch.py 2012-08-16 05:18:54 +0000
427+++ lib/lp/bugs/model/tests/test_bugtasksearch.py 2012-08-28 04:39:25 +0000
428@@ -67,7 +67,6 @@
429 from lp.registry.model.person import Person
430 from lp.services.database.lpstorm import IStore
431 from lp.services.database.sqlbase import convert_storm_clause_to_string
432-from lp.services.features.testing import FeatureFixture
433 from lp.services.searchbuilder import (
434 all,
435 any,
436@@ -2410,8 +2409,6 @@
437 # People and teams with AccessPolicyGrants can see the bug.
438 self.makePrivacyScenario()
439
440- self.useFixture(FeatureFixture(
441- {'disclosure.enhanced_sharing.writable': 'true'}))
442 with admin_logged_in():
443 for princ in (self.grantee_team, self.grantee_person):
444 getUtility(IService, 'sharing').sharePillarInformation(
445
446=== modified file 'lib/lp/code/model/branch.py'
447--- lib/lp/code/model/branch.py 2012-08-07 02:31:56 +0000
448+++ lib/lp/code/model/branch.py 2012-08-28 04:39:25 +0000
449@@ -171,7 +171,6 @@
450 ArrayAgg,
451 ArrayIntersects,
452 )
453-from lp.services.features import getFeatureFlag
454 from lp.services.helpers import shortlist
455 from lp.services.job.interfaces.job import JobStatus
456 from lp.services.job.model.job import Job
457@@ -272,13 +271,10 @@
458 service.ensureAccessGrants(
459 blind_subscribers, who, branches=[self],
460 ignore_permissions=True)
461- flag = 'disclosure.unsubscribe_jobs.enabled'
462- if bool(getFeatureFlag(flag)):
463- # As a result of the transition, some subscribers may no longer
464- # have access to the branch. We need to run a job to remove any
465- # such subscriptions.
466- getUtility(IRemoveArtifactSubscriptionsJobSource).create(
467- who, [self])
468+ # As a result of the transition, some subscribers may no longer
469+ # have access to the branch. We need to run a job to remove any
470+ # such subscriptions.
471+ getUtility(IRemoveArtifactSubscriptionsJobSource).create(who, [self])
472
473 registrant = ForeignKey(
474 dbName='registrant', foreignKey='Person',
475
476=== modified file 'lib/lp/code/model/tests/test_branchnamespace.py'
477--- lib/lp/code/model/tests/test_branchnamespace.py 2012-08-22 14:23:12 +0000
478+++ lib/lp/code/model/tests/test_branchnamespace.py 2012-08-28 04:39:25 +0000
479@@ -57,7 +57,6 @@
480 )
481 from lp.registry.interfaces.product import NoSuchProduct
482 from lp.registry.model.sourcepackage import SourcePackage
483-from lp.services.features.testing import FeatureFixture
484 from lp.testing import (
485 person_logged_in,
486 TestCaseWithFactory,
487@@ -458,11 +457,6 @@
488
489 layer = DatabaseFunctionalLayer
490
491- def setUp(self):
492- super(TestProductNamespacePrivacyWithInformationType, self).setUp()
493- self.useFixture(FeatureFixture(
494- {'disclosure.enhanced_sharing.writable': 'true'}))
495-
496 def makeProductNamespace(self, sharing_policy, person=None):
497 if person is None:
498 person = self.factory.makePerson()
499
500=== modified file 'lib/lp/registry/browser/distribution.py'
501--- lib/lp/registry/browser/distribution.py 2012-08-21 00:34:02 +0000
502+++ lib/lp/registry/browser/distribution.py 2012-08-28 04:39:25 +0000
503@@ -108,7 +108,6 @@
504 )
505 from lp.registry.interfaces.series import SeriesStatus
506 from lp.services.database.decoratedresultset import DecoratedResultSet
507-from lp.services.features import getFeatureFlag
508 from lp.services.feeds.browser import FeedsMixin
509 from lp.services.geoip.helpers import (
510 ipaddress_from_request,
511@@ -313,12 +312,7 @@
512
513 @enabled_with_permission('launchpad.Driver')
514 def sharing(self):
515- text = 'Sharing'
516- enabled_readonly_flag = 'disclosure.enhanced_sharing.enabled'
517- enabled_writable_flag = 'disclosure.enhanced_sharing.writable'
518- enabled = (bool(getFeatureFlag(enabled_readonly_flag))
519- or bool(getFeatureFlag(enabled_writable_flag)))
520- return Link('+sharing', text, icon='edit', enabled=enabled)
521+ return Link('+sharing', 'Sharing', icon='edit')
522
523 @cachedproperty
524 def links(self):
525
526=== modified file 'lib/lp/registry/browser/pillar.py'
527--- lib/lp/registry/browser/pillar.py 2012-08-23 04:42:37 +0000
528+++ lib/lp/registry/browser/pillar.py 2012-08-28 04:39:25 +0000
529@@ -31,7 +31,6 @@
530 getVocabularyRegistry,
531 SimpleVocabulary,
532 )
533-from zope.security.interfaces import Unauthorized
534 from zope.traversing.browser.absoluteurl import absoluteURL
535
536 from lp.app.browser.launchpad import iter_view_registrations
537@@ -60,9 +59,7 @@
538 from lp.registry.interfaces.projectgroup import IProjectGroup
539 from lp.registry.model.pillar import PillarPerson
540 from lp.services.config import config
541-from lp.services.features import getFeatureFlag
542 from lp.services.propertycache import cachedproperty
543-from lp.services.webapp.authorization import check_permission
544 from lp.services.webapp.batching import (
545 BatchNavigator,
546 StormRangeFactory,
547@@ -278,11 +275,6 @@
548
549 sharing_vocabulary_name = 'NewPillarGrantee'
550
551- related_features = (
552- 'disclosure.enhanced_sharing.enabled',
553- 'disclosure.enhanced_sharing.writable',
554- )
555-
556 _batch_navigator = None
557
558 def _getSharingService(self):
559@@ -348,16 +340,7 @@
560
561 def initialize(self):
562 super(PillarSharingView, self).initialize()
563- enabled_readonly_flag = 'disclosure.enhanced_sharing.enabled'
564- enabled_writable_flag = (
565- 'disclosure.enhanced_sharing.writable')
566- enabled = bool(getFeatureFlag(enabled_readonly_flag))
567- write_flag_enabled = bool(getFeatureFlag(enabled_writable_flag))
568- if not enabled and not write_flag_enabled:
569- raise Unauthorized("This feature is not yet available.")
570 cache = IJSONRequestCache(self.request)
571- cache.objects['sharing_write_enabled'] = (write_flag_enabled
572- and check_permission('launchpad.Edit', self.context))
573 cache.objects['information_types'] = self.information_types
574 cache.objects['sharing_permissions'] = self.sharing_permissions
575 cache.objects['bug_sharing_policies'] = self.bug_sharing_policies
576@@ -402,11 +385,6 @@
577 label = "Information shared with person or team"
578
579 def initialize(self):
580- enabled_flag = 'disclosure.enhanced_sharing_details.enabled'
581- enabled = bool(getFeatureFlag(enabled_flag))
582- if not enabled:
583- raise Unauthorized("This feature is not yet available.")
584-
585 self.pillar = self.context.pillar
586 self.person = self.context.person
587
588@@ -431,11 +409,6 @@
589 cache.objects['pillar'] = pillar_data
590 cache.objects['bugs'] = bug_data
591 cache.objects['branches'] = branch_data
592- enabled_writable_flag = (
593- 'disclosure.enhanced_sharing.writable')
594- write_flag_enabled = bool(getFeatureFlag(enabled_writable_flag))
595- cache.objects['sharing_write_enabled'] = (write_flag_enabled
596- and check_permission('launchpad.Edit', self.pillar))
597
598 def _loadSharedArtifacts(self):
599 # As a concrete can by linked via more than one policy, we use sets to
600
601=== modified file 'lib/lp/registry/browser/product.py'
602--- lib/lp/registry/browser/product.py 2012-08-23 04:42:37 +0000
603+++ lib/lp/registry/browser/product.py 2012-08-28 04:39:25 +0000
604@@ -171,7 +171,6 @@
605 from lp.registry.interfaces.sourcepackagename import ISourcePackageNameSet
606 from lp.services.config import config
607 from lp.services.database.decoratedresultset import DecoratedResultSet
608-from lp.services.features import getFeatureFlag
609 from lp.services.feeds.browser import FeedsMixin
610 from lp.services.fields import (
611 PillarAliases,
612@@ -500,12 +499,7 @@
613
614 @enabled_with_permission('launchpad.Driver')
615 def sharing(self):
616- text = 'Sharing'
617- enabled_readonly_flag = 'disclosure.enhanced_sharing.enabled'
618- enabled_writable_flag = 'disclosure.enhanced_sharing.writable'
619- enabled = (bool(getFeatureFlag(enabled_readonly_flag))
620- or bool(getFeatureFlag(enabled_writable_flag)))
621- return Link('+sharing', text, icon='edit', enabled=enabled)
622+ return Link('+sharing', 'Sharing', icon='edit')
623
624
625 class IProductEditMenu(Interface):
626
627=== modified file 'lib/lp/registry/browser/tests/test_pillar_sharing.py'
628--- lib/lp/registry/browser/tests/test_pillar_sharing.py 2012-08-14 04:48:36 +0000
629+++ lib/lp/registry/browser/tests/test_pillar_sharing.py 2012-08-28 04:39:25 +0000
630@@ -17,7 +17,6 @@
631 Raises,
632 )
633 from zope.component import getUtility
634-from zope.security.interfaces import Unauthorized
635 from zope.traversing.browser.absoluteurl import absoluteURL
636
637 from lp.app.interfaces.services import IService
638@@ -30,7 +29,6 @@
639 from lp.registry.model.pillar import PillarPerson
640 from lp.services.config import config
641 from lp.services.database.lpstorm import IStore
642-from lp.services.features.testing import FeatureFixture
643 from lp.services.webapp.interfaces import StormRangeFactoryError
644 from lp.services.webapp.publisher import canonical_url
645 from lp.testing import (
646@@ -49,14 +47,6 @@
647 )
648
649
650-DETAILS_ENABLED_FLAG = {'disclosure.enhanced_sharing_details.enabled': 'true'}
651-DETAILS_WRITE_FLAG = {
652- 'disclosure.enhanced_sharing_details.enabled': 'true',
653- 'disclosure.enhanced_sharing.writable': 'true'}
654-ENABLED_FLAG = {'disclosure.enhanced_sharing.enabled': 'true'}
655-WRITE_FLAG = {'disclosure.enhanced_sharing.writable': 'true'}
656-
657-
658 class SharingBaseTestCase(TestCaseWithFactory):
659
660 layer = DatabaseFunctionalLayer
661@@ -146,124 +136,94 @@
662 # There are bugs in the sharingdetails view that not everyone with
663 # `launchpad.Driver` -- the permission level for the page -- should be
664 # able to see.
665- with FeatureFixture(DETAILS_ENABLED_FLAG):
666- pillarperson = self.getPillarPerson(security=True)
667- logout()
668- login_person(self.driver)
669- view = create_initialized_view(pillarperson, '+index')
670- # The page loads
671- self.assertEqual(pillarperson.person.displayname, view.page_title)
672- # The bug, which is not shared with the driver, is not included.
673- self.assertEqual(0, view.shared_bugs_count)
674+ pillarperson = self.getPillarPerson(security=True)
675+ logout()
676+ login_person(self.driver)
677+ view = create_initialized_view(pillarperson, '+index')
678+ # The page loads
679+ self.assertEqual(pillarperson.person.displayname, view.page_title)
680+ # The bug, which is not shared with the driver, is not included.
681+ self.assertEqual(0, view.shared_bugs_count)
682
683 def test_view_traverses_plus_sharingdetails(self):
684 # The traversed url in the app is pillar/+sharing/person
685- with FeatureFixture(DETAILS_ENABLED_FLAG):
686- # We have to do some fun url hacking to force the traversal a user
687- # encounters.
688- pillarperson = self.getPillarPerson()
689- expected = "Sharing details for %s : Sharing : %s" % (
690- pillarperson.person.displayname,
691- pillarperson.pillar.displayname)
692- url = 'http://launchpad.dev/%s/+sharing/%s' % (
693- pillarperson.pillar.name, pillarperson.person.name)
694- browser = self.getUserBrowser(user=self.owner, url=url)
695- self.assertEqual(expected, browser.title)
696+ # We have to do some fun url hacking to force the traversal a user
697+ # encounters.
698+ pillarperson = self.getPillarPerson()
699+ expected = "Sharing details for %s : Sharing : %s" % (
700+ pillarperson.person.displayname,
701+ pillarperson.pillar.displayname)
702+ url = 'http://launchpad.dev/%s/+sharing/%s' % (
703+ pillarperson.pillar.name, pillarperson.person.name)
704+ browser = self.getUserBrowser(user=self.owner, url=url)
705+ self.assertEqual(expected, browser.title)
706
707 def test_no_sharing_message(self):
708 # If there is no sharing between pillar and person, a suitable message
709 # is displayed.
710- with FeatureFixture(DETAILS_ENABLED_FLAG):
711- # We have to do some fun url hacking to force the traversal a user
712- # encounters.
713- pillarperson = PillarPerson(
714- self.pillar, self.factory.makePerson())
715- url = 'http://launchpad.dev/%s/+sharing/%s' % (
716- pillarperson.pillar.name, pillarperson.person.name)
717- browser = self.getUserBrowser(user=self.owner, url=url)
718- self.assertIn(
719- 'There are no shared bugs or branches.',
720- browser.contents)
721-
722- def test_init_without_feature_flag(self):
723- # We need a feature flag to enable the view.
724- pillarperson = self.getPillarPerson()
725- self.assertRaises(
726- Unauthorized, create_initialized_view, pillarperson, '+index')
727-
728- def test_init_with_feature_flag(self):
729+ # We have to do some fun url hacking to force the traversal a user
730+ # encounters.
731+ pillarperson = PillarPerson(
732+ self.pillar, self.factory.makePerson())
733+ url = 'http://launchpad.dev/%s/+sharing/%s' % (
734+ pillarperson.pillar.name, pillarperson.person.name)
735+ browser = self.getUserBrowser(user=self.owner, url=url)
736+ self.assertIn(
737+ 'There are no shared bugs or branches.', browser.contents)
738+
739+ def test_init_works(self):
740 # The view works with a feature flag.
741- with FeatureFixture(DETAILS_ENABLED_FLAG):
742- pillarperson = self.getPillarPerson()
743- view = create_initialized_view(pillarperson, '+index')
744- self.assertEqual(pillarperson.person.displayname, view.page_title)
745- self.assertEqual(1, view.shared_bugs_count)
746+ pillarperson = self.getPillarPerson()
747+ view = create_initialized_view(pillarperson, '+index')
748+ self.assertEqual(pillarperson.person.displayname, view.page_title)
749+ self.assertEqual(1, view.shared_bugs_count)
750
751 def test_view_data_model(self):
752 # Test that the json request cache contains the view data model.
753- with FeatureFixture(DETAILS_ENABLED_FLAG):
754- pillarperson = self.getPillarPerson()
755- view = create_initialized_view(pillarperson, '+index')
756- bugtask = list(view.bugtasks)[0]
757- bug = bugtask.bug
758- cache = IJSONRequestCache(view.request)
759- request = get_current_web_service_request()
760- self.assertEqual({
761- 'self_link': absoluteURL(pillarperson.person, request),
762- 'displayname': pillarperson.person.displayname
763- }, cache.objects.get('grantee'))
764- self.assertEqual({
765- 'self_link': absoluteURL(pillarperson.pillar, request),
766- }, cache.objects.get('pillar'))
767- self.assertEqual({
768- 'bug_id': bug.id,
769- 'bug_summary': bug.title,
770- 'bug_importance': bugtask.importance.title.lower(),
771- 'information_type': bug.information_type.title,
772- 'web_link': canonical_url(
773- bugtask, path_only_if_possible=True),
774- 'self_link': absoluteURL(bug, request),
775- }, cache.objects.get('bugs')[0])
776- if self.pillar_type == 'product':
777- branch = list(view.branches)[0]
778- self.assertEqual({
779- 'branch_id': branch.id,
780- 'branch_name': branch.unique_name,
781- 'information_type': InformationType.USERDATA.title,
782- 'web_link': canonical_url(
783- branch, path_only_if_possible=True),
784- 'self_link': absoluteURL(branch, request),
785- }, cache.objects.get('branches')[0])
786+ pillarperson = self.getPillarPerson()
787+ view = create_initialized_view(pillarperson, '+index')
788+ bugtask = list(view.bugtasks)[0]
789+ bug = bugtask.bug
790+ cache = IJSONRequestCache(view.request)
791+ request = get_current_web_service_request()
792+ self.assertEqual({
793+ 'self_link': absoluteURL(pillarperson.person, request),
794+ 'displayname': pillarperson.person.displayname
795+ }, cache.objects.get('grantee'))
796+ self.assertEqual({
797+ 'self_link': absoluteURL(pillarperson.pillar, request),
798+ }, cache.objects.get('pillar'))
799+ self.assertEqual({
800+ 'bug_id': bug.id,
801+ 'bug_summary': bug.title,
802+ 'bug_importance': bugtask.importance.title.lower(),
803+ 'information_type': bug.information_type.title,
804+ 'web_link': canonical_url(
805+ bugtask, path_only_if_possible=True),
806+ 'self_link': absoluteURL(bug, request),
807+ }, cache.objects.get('bugs')[0])
808+ if self.pillar_type == 'product':
809+ branch = list(view.branches)[0]
810+ self.assertEqual({
811+ 'branch_id': branch.id,
812+ 'branch_name': branch.unique_name,
813+ 'information_type': InformationType.USERDATA.title,
814+ 'web_link': canonical_url(branch, path_only_if_possible=True),
815+ 'self_link': absoluteURL(branch, request),
816+ }, cache.objects.get('branches')[0])
817
818 def test_view_query_count(self):
819 # Test that the view bulk loads artifacts.
820- with FeatureFixture(DETAILS_ENABLED_FLAG):
821- person = self.factory.makePerson()
822- for x in range(0, 15):
823- self.makeArtifactGrantee(person, True, True, False)
824- pillarperson = PillarPerson(self.pillar, person)
825-
826- # Invalidate the Storm cache and check the query count.
827- IStore(self.pillar).invalidate()
828- with StormStatementRecorder() as recorder:
829- create_initialized_view(pillarperson, '+index')
830- self.assertThat(recorder, HasQueryCount(LessThan(12)))
831-
832- def test_view_write_enabled_without_feature_flag(self):
833- # Test that sharing_write_enabled is not set without the feature flag.
834- with FeatureFixture(DETAILS_ENABLED_FLAG):
835- pillarperson = self.getPillarPerson()
836- view = create_initialized_view(pillarperson, '+index')
837- cache = IJSONRequestCache(view.request)
838- self.assertFalse(cache.objects.get('sharing_write_enabled'))
839-
840- def test_view_write_enabled_with_feature_flag(self):
841- # Test that sharing_write_enabled is set when required.
842- with FeatureFixture(DETAILS_WRITE_FLAG):
843- pillarperson = self.getPillarPerson()
844- view = create_initialized_view(pillarperson, '+index')
845- cache = IJSONRequestCache(view.request)
846- self.assertTrue(cache.objects.get('sharing_write_enabled'))
847+ person = self.factory.makePerson()
848+ for x in range(0, 15):
849+ self.makeArtifactGrantee(person, True, True, False)
850+ pillarperson = PillarPerson(self.pillar, person)
851+
852+ # Invalidate the Storm cache and check the query count.
853+ IStore(self.pillar).invalidate()
854+ with StormStatementRecorder() as recorder:
855+ create_initialized_view(pillarperson, '+index')
856+ self.assertThat(recorder, HasQueryCount(LessThan(12)))
857
858
859 class TestProductSharingDetailsView(
860@@ -289,132 +249,83 @@
861 class PillarSharingViewTestMixin:
862 """Test the PillarSharingView."""
863
864- def test_init_without_feature_flag(self):
865- # We need a feature flag to enable the view.
866- self.assertRaises(
867- Unauthorized, create_initialized_view, self.pillar, '+sharing')
868-
869- def test_init_with_feature_flag(self):
870- # The view works with a feature flag.
871- with FeatureFixture(ENABLED_FLAG):
872- view = create_initialized_view(self.pillar, '+sharing')
873- self.assertEqual('Sharing', view.page_title)
874-
875- def test_sharing_menu_without_feature_flag(self):
876+ def test_sharing_menu(self):
877 url = canonical_url(self.pillar)
878 browser = setupBrowserForUser(user=self.driver)
879 browser.open(url)
880 soup = BeautifulSoup(browser.contents)
881- sharing_menu = soup.find('a', {'class': 'menu-link-sharing'})
882- self.assertIsNone(sharing_menu)
883-
884- def test_sharing_menu_with_feature_flag(self):
885- with FeatureFixture(ENABLED_FLAG):
886- url = canonical_url(self.pillar)
887- browser = setupBrowserForUser(user=self.driver)
888- browser.open(url)
889- soup = BeautifulSoup(browser.contents)
890- sharing_url = canonical_url(self.pillar, view_name='+sharing')
891- sharing_menu = soup.find('a', {'href': sharing_url})
892- self.assertIsNotNone(sharing_menu)
893+ sharing_url = canonical_url(self.pillar, view_name='+sharing')
894+ sharing_menu = soup.find('a', {'href': sharing_url})
895+ self.assertIsNotNone(sharing_menu)
896
897 def test_picker_config(self):
898 # Test the config passed to the disclosure sharing picker.
899- with FeatureFixture(ENABLED_FLAG):
900- view = create_view(self.pillar, name='+sharing')
901- picker_config = simplejson.loads(view.json_sharing_picker_config)
902- self.assertTrue('vocabulary_filters' in picker_config)
903- self.assertEqual(
904- 'Share project information',
905- picker_config['header'])
906- self.assertEqual(
907- 'Search for user or exclusive team with whom to share',
908- picker_config['steptitle'])
909- self.assertEqual(
910- 'NewPillarGrantee', picker_config['vocabulary'])
911+ view = create_view(self.pillar, name='+sharing')
912+ picker_config = simplejson.loads(view.json_sharing_picker_config)
913+ self.assertTrue('vocabulary_filters' in picker_config)
914+ self.assertEqual('Share project information', picker_config['header'])
915+ self.assertEqual(
916+ 'Search for user or exclusive team with whom to share',
917+ picker_config['steptitle'])
918+ self.assertEqual('NewPillarGrantee', picker_config['vocabulary'])
919
920 def test_view_data_model(self):
921 # Test that the json request cache contains the view data model.
922- with FeatureFixture(ENABLED_FLAG):
923- view = create_initialized_view(self.pillar, name='+sharing')
924- cache = IJSONRequestCache(view.request)
925- self.assertIsNotNone(cache.objects.get('information_types'))
926- self.assertIsNotNone(
927- cache.objects.get('branch_sharing_policies'))
928- self.assertIsNotNone(cache.objects.get('bug_sharing_policies'))
929- self.assertIsNotNone(cache.objects.get('sharing_permissions'))
930- batch_size = config.launchpad.default_batch_size
931- apgfs = getUtility(IAccessPolicyGrantFlatSource)
932- grantees = apgfs.findGranteePermissionsByPolicy(
933- [self.access_policy], self.grantees[:batch_size])
934- sharing_service = getUtility(IService, 'sharing')
935- grantee_data = sharing_service.jsonGranteeData(grantees)
936- self.assertContentEqual(
937- grantee_data, cache.objects.get('grantee_data'))
938+ view = create_initialized_view(self.pillar, name='+sharing')
939+ cache = IJSONRequestCache(view.request)
940+ self.assertIsNotNone(cache.objects.get('information_types'))
941+ self.assertIsNotNone(cache.objects.get('branch_sharing_policies'))
942+ self.assertIsNotNone(cache.objects.get('bug_sharing_policies'))
943+ self.assertIsNotNone(cache.objects.get('sharing_permissions'))
944+ batch_size = config.launchpad.default_batch_size
945+ apgfs = getUtility(IAccessPolicyGrantFlatSource)
946+ grantees = apgfs.findGranteePermissionsByPolicy(
947+ [self.access_policy], self.grantees[:batch_size])
948+ sharing_service = getUtility(IService, 'sharing')
949+ grantee_data = sharing_service.jsonGranteeData(grantees)
950+ self.assertContentEqual(
951+ grantee_data, cache.objects.get('grantee_data'))
952
953 def test_view_batch_data(self):
954 # Test the expected batching data is in the json request cache.
955- with FeatureFixture(ENABLED_FLAG):
956- view = create_initialized_view(self.pillar, name='+sharing')
957- cache = IJSONRequestCache(view.request)
958- # Test one expected data value (there are many).
959- next_batch = view.grantees().batch.nextBatch()
960- self.assertContentEqual(
961- next_batch.range_memo, cache.objects.get('next')['memo'])
962+ view = create_initialized_view(self.pillar, name='+sharing')
963+ cache = IJSONRequestCache(view.request)
964+ # Test one expected data value (there are many).
965+ next_batch = view.grantees().batch.nextBatch()
966+ self.assertContentEqual(
967+ next_batch.range_memo, cache.objects.get('next')['memo'])
968
969 def test_view_range_factory(self):
970 # Test the view range factory is properly configured.
971- with FeatureFixture(ENABLED_FLAG):
972- view = create_initialized_view(self.pillar, name='+sharing')
973- range_factory = view.grantees().batch.range_factory
974-
975- def test_range_factory():
976- row = range_factory.resultset.get_plain_result_set()[0]
977- range_factory.getOrderValuesFor(row)
978-
979- self.assertThat(
980- test_range_factory,
981- Not(Raises(MatchesException(StormRangeFactoryError))))
982+ view = create_initialized_view(self.pillar, name='+sharing')
983+ range_factory = view.grantees().batch.range_factory
984+
985+ def test_range_factory():
986+ row = range_factory.resultset.get_plain_result_set()[0]
987+ range_factory.getOrderValuesFor(row)
988+
989+ self.assertThat(
990+ test_range_factory,
991+ Not(Raises(MatchesException(StormRangeFactoryError))))
992
993 def test_view_query_count(self):
994 # Test the query count is within expected limit.
995- with FeatureFixture(ENABLED_FLAG):
996- view = create_view(self.pillar, name='+sharing')
997- with StormStatementRecorder() as recorder:
998- view.initialize()
999- self.assertThat(recorder, HasQueryCount(LessThan(9)))
1000-
1001- def test_view_write_enabled_without_feature_flag(self):
1002- # Test that sharing_write_enabled is not set without the feature flag.
1003- with FeatureFixture(ENABLED_FLAG):
1004- login_person(self.owner)
1005- view = create_initialized_view(self.pillar, name='+sharing')
1006- cache = IJSONRequestCache(view.request)
1007- self.assertFalse(cache.objects.get('sharing_write_enabled'))
1008-
1009- def test_view_write_enabled_with_feature_flag(self):
1010- # Test that sharing_write_enabled is set when required.
1011- with FeatureFixture(WRITE_FLAG):
1012- view = create_initialized_view(self.pillar, name='+sharing')
1013- cache = IJSONRequestCache(view.request)
1014- self.assertFalse(cache.objects.get('sharing_write_enabled'))
1015- login_person(self.owner)
1016- view = create_initialized_view(self.pillar, name='+sharing')
1017- cache = IJSONRequestCache(view.request)
1018- self.assertTrue(cache.objects.get('sharing_write_enabled'))
1019+ view = create_view(self.pillar, name='+sharing')
1020+ with StormStatementRecorder() as recorder:
1021+ view.initialize()
1022+ self.assertThat(recorder, HasQueryCount(LessThan(9)))
1023
1024 def test_view_invisible_information_types(self):
1025 # Test the expected invisible information type data is in the
1026 # json request cache.
1027- with FeatureFixture(WRITE_FLAG):
1028- with person_logged_in(self.pillar.owner):
1029- getUtility(IService, 'sharing').deletePillarGrantee(
1030- self.pillar, self.pillar.owner, self.pillar.owner)
1031- view = create_initialized_view(self.pillar, name='+sharing')
1032- cache = IJSONRequestCache(view.request)
1033- self.assertContentEqual(
1034- ['Private Security', 'Private'],
1035- cache.objects.get('invisible_information_types'))
1036+ with person_logged_in(self.pillar.owner):
1037+ getUtility(IService, 'sharing').deletePillarGrantee(
1038+ self.pillar, self.pillar.owner, self.pillar.owner)
1039+ view = create_initialized_view(self.pillar, name='+sharing')
1040+ cache = IJSONRequestCache(view.request)
1041+ self.assertContentEqual(
1042+ ['Private Security', 'Private'],
1043+ cache.objects.get('invisible_information_types'))
1044
1045
1046 class TestProductSharingView(PillarSharingViewTestMixin,
1047
1048=== modified file 'lib/lp/registry/javascript/sharing/pillarsharingview.js'
1049--- lib/lp/registry/javascript/sharing/pillarsharingview.js 2012-08-23 00:35:25 +0000
1050+++ lib/lp/registry/javascript/sharing/pillarsharingview.js 2012-08-28 04:39:25 +0000
1051@@ -19,10 +19,6 @@
1052 value: new Y.lp.client.Launchpad()
1053 },
1054
1055- write_enabled: {
1056- value: false
1057- },
1058-
1059 grantee_picker: {
1060 value: null
1061 },
1062@@ -61,12 +57,6 @@
1063 this.set(
1064 'sharing_permissions_by_value', sharing_permissions_by_value);
1065
1066- // No need to do anything else if we are read only.
1067- if (LP.cache.sharing_write_enabled !== true) {
1068- return;
1069- }
1070- this.set('write_enabled', true);
1071-
1072 var vocab;
1073 var header;
1074 var steptitle;
1075@@ -125,13 +115,11 @@
1076 sharing_permissions:
1077 this.get('sharing_permissions_by_value'),
1078 information_types: this.get('information_types_by_value'),
1079- write_enabled: this.get('write_enabled')
1080+ write_enabled: true
1081 });
1082 this.set('grantee_table', grantee_table);
1083 grantee_table.render();
1084- if (this.get('write_enabled')) {
1085- Y.one('#add-grantee-link').removeClass('hidden');
1086- }
1087+ Y.one('#add-grantee-link').removeClass('hidden');
1088 this.bug_sharing_policy_widget
1089 = this._render_sharing_policy('bug', 'Bug');
1090 this.branch_sharing_policy_widget
1091@@ -164,8 +152,7 @@
1092 }
1093 choice_items.push.apply(
1094 choice_items, this.getSharingPolicyInformation(artifact_type));
1095- var editable = LP.cache.sharing_write_enabled
1096- && choice_items.length > 1;
1097+ var editable = choice_items.length > 1;
1098 var policy_edit = new Y.ChoiceSource({
1099 flashEnabled: false,
1100 clickable_content: editable,
1101@@ -186,9 +173,6 @@
1102 },
1103
1104 bindUI: function() {
1105- if (!this.get('write_enabled')) {
1106- return;
1107- }
1108 var self = this;
1109 var share_link = Y.one('#add-grantee-link');
1110 share_link.on('click', function(e) {
1111
1112=== modified file 'lib/lp/registry/javascript/sharing/sharingdetailsview.js'
1113--- lib/lp/registry/javascript/sharing/sharingdetailsview.js 2012-07-21 03:04:06 +0000
1114+++ lib/lp/registry/javascript/sharing/sharingdetailsview.js 2012-08-28 04:39:25 +0000
1115@@ -19,10 +19,6 @@
1116 value: new Y.lp.client.Launchpad()
1117 },
1118
1119- write_enabled: {
1120- value: false
1121- },
1122-
1123 sharing_details_table: {
1124 value: null
1125 }
1126@@ -30,29 +26,19 @@
1127
1128 Y.extend(SharingDetailsView, Y.Widget, {
1129
1130- initializer: function(config) {
1131- if (LP.cache.sharing_write_enabled !== true) {
1132- return;
1133- }
1134- this.set('write_enabled', true);
1135- },
1136-
1137 renderUI: function() {
1138 var ns = Y.lp.registry.sharing.sharingdetails;
1139 var details_table = new ns.SharingDetailsTable({
1140 bugs: LP.cache.bugs,
1141 branches: LP.cache.branches,
1142 person_name: LP.cache.grantee.displayname,
1143- write_enabled: this.get('write_enabled')
1144+ write_enabled: true
1145 });
1146 this.set('sharing_details_table', details_table);
1147 details_table.render();
1148 },
1149
1150 bindUI: function() {
1151- if (!this.get('write_enabled')) {
1152- return;
1153- }
1154 var self = this;
1155 var sharing_details_table = this.get('sharing_details_table');
1156 var ns = Y.lp.registry.sharing.sharingdetails;
1157
1158=== modified file 'lib/lp/registry/javascript/sharing/tests/test_pillarsharingview.js'
1159--- lib/lp/registry/javascript/sharing/tests/test_pillarsharingview.js 2012-08-16 00:19:42 +0000
1160+++ lib/lp/registry/javascript/sharing/tests/test_pillarsharingview.js 2012-08-28 04:39:25 +0000
1161@@ -56,7 +56,6 @@
1162 title: 'Branch Policy 1',
1163 description: 'Branch Policy 1 description'}
1164 ],
1165- sharing_write_enabled: true
1166 }
1167 };
1168 this.mockio = new Y.lp.testing.mockio.MockIo();
1169@@ -119,16 +118,6 @@
1170 Y.Assert.isNotNull(Y.one('.yui3-grantee_picker'));
1171 },
1172
1173- // Read only mode disables the correct things.
1174- test_readonly: function() {
1175- window.LP.cache.sharing_write_enabled = false;
1176- this.view = this._create_Widget();
1177- this.view.render();
1178- Y.Assert.isTrue(Y.one('#add-grantee-link').hasClass('hidden'));
1179- Y.Assert.isFalse(
1180- this.view.get('grantee_table').get('write_enabled'));
1181- },
1182-
1183 // Clicking a update grantee grantee link calls
1184 // the update_grantee_interaction method with the correct parameters.
1185 test_update_grantee_click: function() {
1186@@ -547,14 +536,6 @@
1187 'Bug Policy 1', value_node.get('text').trim());
1188 },
1189
1190- // If the view is readonly, no edit links are available.
1191- test_sharing_policy_render_read_only: function() {
1192- window.LP.cache.sharing_write_enabled = false;
1193- this.view = this._create_Widget();
1194- this.view.render();
1195- this._assert_sharing_policies_editable(false);
1196- },
1197-
1198 // If there is only one policy choice, no edit links are available.
1199 test_sharing_policy_render_only_one_choice: function() {
1200 // Add a model value so the legacy choice is not used.
1201
1202=== modified file 'lib/lp/registry/javascript/sharing/tests/test_sharingdetailsview.js'
1203--- lib/lp/registry/javascript/sharing/tests/test_sharingdetailsview.js 2012-07-20 03:15:04 +0000
1204+++ lib/lp/registry/javascript/sharing/tests/test_sharingdetailsview.js 2012-08-28 04:39:25 +0000
1205@@ -37,7 +37,6 @@
1206 pillar: {
1207 self_link: '/pillar'
1208 },
1209- sharing_write_enabled: true
1210 }
1211 };
1212 this.fixture = Y.one('#fixture');
1213@@ -79,16 +78,6 @@
1214 Y.one('#sharing-table-body tr[id=shared-bug-2]'));
1215 },
1216
1217- // Read only mode disables the correct things.
1218- test_readonly: function() {
1219- window.LP.cache.sharing_write_enabled = false;
1220- this.view = this._create_Widget();
1221- this.view.render();
1222- Y.Assert.isFalse(
1223- this.view.get('sharing_details_table')
1224- .get('write_enabled'));
1225- },
1226-
1227 // Clicking a bug remove link calls the confirm_grant_removal
1228 // method with the correct parameters.
1229 test_remove_bug_grant_click: function() {
1230
1231=== modified file 'lib/lp/registry/model/teammembership.py'
1232--- lib/lp/registry/model/teammembership.py 2012-08-14 23:27:07 +0000
1233+++ lib/lp/registry/model/teammembership.py 2012-08-28 04:39:25 +0000
1234@@ -65,7 +65,6 @@
1235 SQLBase,
1236 sqlvalues,
1237 )
1238-from lp.services.features import getFeatureFlag
1239 from lp.services.mail.helpers import (
1240 get_contact_email_addresses,
1241 get_email_template,
1242@@ -343,13 +342,11 @@
1243 _fillTeamParticipation(self.person, self.team)
1244 elif old_status in ACTIVE_STATES:
1245 _cleanTeamParticipation(self.person, self.team)
1246- flag = 'disclosure.unsubscribe_jobs.enabled'
1247- if bool(getFeatureFlag(flag)):
1248- # A person has left the team so they may no longer have access
1249- # to some artifacts shared with the team. We need to run a job
1250- # to remove any subscriptions to such artifacts.
1251- getUtility(IRemoveArtifactSubscriptionsJobSource).create(
1252- user, grantee=self.person)
1253+ # A person has left the team so they may no longer have access
1254+ # to some artifacts shared with the team. We need to run a job
1255+ # to remove any subscriptions to such artifacts.
1256+ getUtility(IRemoveArtifactSubscriptionsJobSource).create(
1257+ user, grantee=self.person)
1258 else:
1259 # Changed from an inactive state to another inactive one, so no
1260 # need to fill/clean the TeamParticipation table.
1261
1262=== modified file 'lib/lp/registry/services/sharingservice.py'
1263--- lib/lp/registry/services/sharingservice.py 2012-08-16 06:06:36 +0000
1264+++ lib/lp/registry/services/sharingservice.py 2012-08-28 04:39:25 +0000
1265@@ -59,7 +59,6 @@
1266 from lp.registry.model.teammembership import TeamParticipation
1267 from lp.services.database.lpstorm import IStore
1268 from lp.services.database.stormexpr import ColumnSelect
1269-from lp.services.features import getFeatureFlag
1270 from lp.services.searchbuilder import any
1271 from lp.services.webapp.authorization import (
1272 available_with_permission,
1273@@ -81,12 +80,6 @@
1274 """See `IService`."""
1275 return 'sharing'
1276
1277- @property
1278- def write_enabled(self):
1279- return (
1280- bool(getFeatureFlag(
1281- 'disclosure.enhanced_sharing.writable')))
1282-
1283 def checkPillarAccess(self, pillar, information_type, person):
1284 """See `ISharingService`."""
1285 policy = getUtility(IAccessPolicySource).find(
1286@@ -350,15 +343,12 @@
1287 result = []
1288 request = get_current_web_service_request()
1289 browser_request = IWebBrowserOriginatingRequest(request)
1290- details_enabled = bool((getFeatureFlag(
1291- 'disclosure.enhanced_sharing_details.enabled')))
1292 # We need to precache icon and validity information for the batch.
1293 grantee_ids = [grantee[0].id for grantee in grant_permissions]
1294 list(getUtility(IPersonSet).getPrecachedPersonsFromIDs(
1295 grantee_ids, need_icon=True, need_validity=True))
1296 for (grantee, permissions, shared_artifact_types) in grant_permissions:
1297- some_things_shared = (
1298- details_enabled and len(shared_artifact_types) > 0)
1299+ some_things_shared = len(shared_artifact_types) > 0
1300 grantee_permissions = {}
1301 for (policy, permission) in permissions.iteritems():
1302 grantee_permissions[policy.type.name] = permission.name
1303@@ -386,9 +376,6 @@
1304 # We do not support adding grantees to project groups.
1305 assert not IProjectGroup.providedBy(pillar)
1306
1307- if not self.write_enabled:
1308- raise Unauthorized("This feature is not yet enabled.")
1309-
1310 # Separate out the info types according to permission.
1311 information_types = permissions.keys()
1312 info_types_for_all = [
1313@@ -463,9 +450,6 @@
1314 information_types=None):
1315 """See `ISharingService`."""
1316
1317- if not self.write_enabled:
1318- raise Unauthorized("This feature is not yet enabled.")
1319-
1320 policy_source = getUtility(IAccessPolicySource)
1321 if information_types is None:
1322 # We delete all policy grants for the pillar.
1323@@ -491,9 +475,8 @@
1324 to_delete = list(ap_grant_flat.findArtifactsByGrantee(
1325 grantee, pillar_policies))
1326 if len(to_delete) > 0:
1327- accessartifact_grant_source = getUtility(
1328- IAccessArtifactGrantSource)
1329- accessartifact_grant_source.revokeByArtifact(to_delete, [grantee])
1330+ getUtility(IAccessArtifactGrantSource).revokeByArtifact(
1331+ to_delete, [grantee])
1332
1333 # Create a job to remove subscriptions for artifacts the grantee can no
1334 # longer see.
1335@@ -512,9 +495,6 @@
1336 bugs=None):
1337 """See `ISharingService`."""
1338
1339- if not self.write_enabled:
1340- raise Unauthorized("This feature is not yet enabled.")
1341-
1342 artifacts = []
1343 if branches:
1344 artifacts.extend(branches)
1345@@ -524,8 +504,7 @@
1346 accessartifact_source = getUtility(IAccessArtifactSource)
1347 artifacts_to_delete = accessartifact_source.find(artifacts)
1348 # Revoke access to bugs/branches for the specified grantee.
1349- accessartifact_grant_source = getUtility(IAccessArtifactGrantSource)
1350- accessartifact_grant_source.revokeByArtifact(
1351+ getUtility(IAccessArtifactGrantSource).revokeByArtifact(
1352 artifacts_to_delete, [grantee])
1353
1354 # Create a job to remove subscriptions for artifacts the grantee can no
1355@@ -537,9 +516,6 @@
1356 ignore_permissions=False):
1357 """See `ISharingService`."""
1358
1359- if not ignore_permissions and not self.write_enabled:
1360- raise Unauthorized("This feature is not yet enabled.")
1361-
1362 artifacts = []
1363 if branches:
1364 artifacts.extend(branches)
1365
1366=== modified file 'lib/lp/registry/services/tests/test_sharingservice.py'
1367--- lib/lp/registry/services/tests/test_sharingservice.py 2012-08-16 06:06:36 +0000
1368+++ lib/lp/registry/services/tests/test_sharingservice.py 2012-08-28 04:39:25 +0000
1369@@ -56,13 +56,6 @@
1370 from lp.testing.pages import LaunchpadWebServiceCaller
1371
1372
1373-WRITE_FLAG = {
1374- 'disclosure.enhanced_sharing.writable': 'true',
1375- 'disclosure.enhanced_sharing_details.enabled': 'true',
1376- 'jobs.celery.enabled_classes': 'RemoveArtifactSubscriptionsJob'}
1377-DETAILS_FLAG = {'disclosure.enhanced_sharing_details.enabled': 'true'}
1378-
1379-
1380 class TestSharingService(TestCaseWithFactory):
1381 """Tests for the SharingService."""
1382
1383@@ -71,6 +64,9 @@
1384 def setUp(self):
1385 super(TestSharingService, self).setUp()
1386 self.service = getUtility(IService, 'sharing')
1387+ self.useFixture(FeatureFixture({
1388+ 'jobs.celery.enabled_classes': 'RemoveArtifactSubscriptionsJob',
1389+ }))
1390
1391 def _makeGranteeData(self, grantee, policy_permissions,
1392 shared_artifact_types):
1393@@ -234,12 +230,11 @@
1394 [policy1, policy2] = getUtility(IAccessPolicySource).findByPillar(
1395 [product])
1396 grantee = self.factory.makePerson()
1397- with FeatureFixture(DETAILS_FLAG):
1398- grantees = self.service.jsonGranteeData(
1399- [(grantee, {
1400- policy1: SharingPermission.ALL,
1401- policy2: SharingPermission.SOME},
1402- [policy1.type, policy2.type])])
1403+ grantees = self.service.jsonGranteeData(
1404+ [(grantee, {
1405+ policy1: SharingPermission.ALL,
1406+ policy2: SharingPermission.SOME},
1407+ [policy1.type, policy2.type])])
1408 expected_data = self._makeGranteeData(
1409 grantee,
1410 [(policy1.type, SharingPermission.ALL),
1411@@ -247,24 +242,6 @@
1412 [policy1.type, policy2.type])
1413 self.assertContentEqual([expected_data], grantees)
1414
1415- def test_jsonGranteeData_with_Some_without_flag(self):
1416- # jsonGranteeData returns the expected data for a grantee with
1417- # permissions which include SOME and the feature flag not set.
1418- product = self.factory.makeProduct()
1419- [policy1, policy2] = getUtility(IAccessPolicySource).findByPillar(
1420- [product])
1421- grantee = self.factory.makePerson()
1422- grantees = self.service.jsonGranteeData(
1423- [(grantee, {
1424- policy1: SharingPermission.ALL,
1425- policy2: SharingPermission.SOME}, [policy2.type])])
1426- expected_data = self._makeGranteeData(
1427- grantee,
1428- [(policy1.type, SharingPermission.ALL),
1429- (policy2.type, SharingPermission.SOME)], [policy2.type])
1430- expected_data['shared_items_exist'] = False
1431- self.assertContentEqual([expected_data], grantees)
1432-
1433 def test_jsonGranteeData_without_Some(self):
1434 # jsonGranteeData returns the expected data for a grantee with only ALL
1435 # permissions.
1436@@ -272,10 +249,8 @@
1437 [policy1, policy2] = getUtility(IAccessPolicySource).findByPillar(
1438 [product])
1439 grantee = self.factory.makePerson()
1440- with FeatureFixture(DETAILS_FLAG):
1441- grantees = self.service.jsonGranteeData(
1442- [(grantee, {
1443- policy1: SharingPermission.ALL}, [])])
1444+ grantees = self.service.jsonGranteeData(
1445+ [(grantee, {policy1: SharingPermission.ALL}, [])])
1446 expected_data = self._makeGranteeData(
1447 grantee,
1448 [(policy1.type, SharingPermission.ALL)], [])
1449@@ -290,10 +265,8 @@
1450 icon = self.factory.makeLibraryFileAlias(
1451 filename='smurf.png', content_type='image/png')
1452 grantee = self.factory.makeTeam(icon=icon)
1453- with FeatureFixture(DETAILS_FLAG):
1454- grantees = self.service.jsonGranteeData(
1455- [(grantee, {
1456- policy1: SharingPermission.ALL}, [])])
1457+ grantees = self.service.jsonGranteeData(
1458+ [(grantee, {policy1: SharingPermission.ALL}, [])])
1459 expected_data = self._makeGranteeData(
1460 grantee,
1461 [(policy1.type, SharingPermission.ALL)], [])
1462@@ -312,8 +285,7 @@
1463 self.factory.makeAccessPolicyArtifact(
1464 artifact=artifact_grant.abstract_artifact, policy=access_policy)
1465
1466- with FeatureFixture(DETAILS_FLAG):
1467- grantees = self.service.getPillarGranteeData(pillar)
1468+ grantees = self.service.getPillarGranteeData(pillar)
1469 expected_grantees = [
1470 self._makeGranteeData(
1471 grantee,
1472@@ -540,9 +512,8 @@
1473 InformationType.PRIVATESECURITY: SharingPermission.ALL,
1474 InformationType.USERDATA: SharingPermission.SOME,
1475 InformationType.PROPRIETARY: SharingPermission.NOTHING}
1476- with FeatureFixture(WRITE_FLAG):
1477- grantee_data = self.service.sharePillarInformation(
1478- pillar, grantee, grantor, permissions)
1479+ grantee_data = self.service.sharePillarInformation(
1480+ pillar, grantee, grantor, permissions)
1481 policies = getUtility(IAccessPolicySource).findByPillar([pillar])
1482 policy_grant_source = getUtility(IAccessPolicyGrantSource)
1483 grants = policy_grant_source.findByPolicy(policies)
1484@@ -619,9 +590,8 @@
1485
1486 permissions = {
1487 grant.policy.type: SharingPermission.SOME}
1488- with FeatureFixture(WRITE_FLAG):
1489- grantee_data = self.service.sharePillarInformation(
1490- pillar, grantee, self.factory.makePerson(), permissions)
1491+ grantee_data = self.service.sharePillarInformation(
1492+ pillar, grantee, self.factory.makePerson(), permissions)
1493 self.assertIsNone(grantee_data['grantee_entry'])
1494
1495 def test_granteePillarInformationInvisibleInformationTypes(self):
1496@@ -629,13 +599,12 @@
1497 # information types.
1498 product = self.factory.makeProduct()
1499 grantee = self.factory.makePerson()
1500- with FeatureFixture(WRITE_FLAG):
1501- with admin_logged_in():
1502- self.service.deletePillarGrantee(
1503- product, product.owner, product.owner)
1504- result_data = self.service.sharePillarInformation(
1505- product, grantee, product.owner,
1506- {InformationType.USERDATA: SharingPermission.ALL})
1507+ with admin_logged_in():
1508+ self.service.deletePillarGrantee(
1509+ product, product.owner, product.owner)
1510+ result_data = self.service.sharePillarInformation(
1511+ product, grantee, product.owner,
1512+ {InformationType.USERDATA: SharingPermission.ALL})
1513 # The owner is granted access on product creation. So we need to allow
1514 # for that in the check below.
1515 self.assertContentEqual(
1516@@ -645,42 +614,27 @@
1517 def _assert_sharePillarInformationUnauthorized(self, pillar):
1518 # sharePillarInformation raises an Unauthorized exception if the user
1519 # is not permitted to do so.
1520- with FeatureFixture(WRITE_FLAG):
1521- grantee = self.factory.makePerson()
1522- user = self.factory.makePerson()
1523- self.assertRaises(
1524- Unauthorized, self.service.sharePillarInformation,
1525- pillar, grantee, user,
1526- {InformationType.USERDATA: SharingPermission.ALL})
1527+ grantee = self.factory.makePerson()
1528+ user = self.factory.makePerson()
1529+ self.assertRaises(
1530+ Unauthorized, self.service.sharePillarInformation,
1531+ pillar, grantee, user,
1532+ {InformationType.USERDATA: SharingPermission.ALL})
1533
1534 def test_sharePillarInformationAnonymous(self):
1535 # Anonymous users are not allowed.
1536- with FeatureFixture(WRITE_FLAG):
1537- product = self.factory.makeProduct()
1538- login(ANONYMOUS)
1539- self._assert_sharePillarInformationUnauthorized(product)
1540+ product = self.factory.makeProduct()
1541+ login(ANONYMOUS)
1542+ self._assert_sharePillarInformationUnauthorized(product)
1543
1544 def test_sharePillarInformationAnyone(self):
1545 # Unauthorized users are not allowed.
1546- with FeatureFixture(WRITE_FLAG):
1547- product = self.factory.makeProduct()
1548- login_person(self.factory.makePerson())
1549- self._assert_sharePillarInformationUnauthorized(product)
1550-
1551- def test_sharePillarInformation_without_flag(self):
1552- # The feature flag needs to be enabled.
1553- owner = self.factory.makePerson()
1554- product = self.factory.makeProduct(owner=owner)
1555- login_person(owner)
1556- grantee = self.factory.makePerson()
1557- user = self.factory.makePerson()
1558- self.assertRaises(
1559- Unauthorized, self.service.sharePillarInformation,
1560- product, grantee, user,
1561- {InformationType.USERDATA: SharingPermission.ALL})
1562-
1563- def _assert_deletePillarGrantee(
1564- self, pillar, types_to_delete=None, pillar_type=None):
1565+ product = self.factory.makeProduct()
1566+ login_person(self.factory.makePerson())
1567+ self._assert_sharePillarInformationUnauthorized(product)
1568+
1569+ def _assert_deletePillarGrantee(self, pillar, types_to_delete=None,
1570+ pillar_type=None):
1571 access_policies = getUtility(IAccessPolicySource).findByPillar(
1572 (pillar,))
1573 information_types = [ap.type for ap in access_policies]
1574@@ -701,9 +655,8 @@
1575 self.factory.makeAccessPolicyArtifact(
1576 artifact=artifact, policy=access_policy)
1577 # Delete data for a specific information type.
1578- with FeatureFixture(WRITE_FLAG):
1579- self.service.deletePillarGrantee(
1580- pillar, grantee, pillar.owner, types_to_delete)
1581+ self.service.deletePillarGrantee(
1582+ pillar, grantee, pillar.owner, types_to_delete)
1583 # Assemble the expected data for the remaining access grants for
1584 # grantee.
1585 expected_data = []
1586@@ -768,43 +721,30 @@
1587 def test_deletePillarGranteeInvisibleInformationTypes(self):
1588 # Deleting a pillar grantee returns the resulting invisible info types.
1589 product = self.factory.makeProduct()
1590- with FeatureFixture(WRITE_FLAG):
1591- with admin_logged_in():
1592- invisible_information_types = self.service.deletePillarGrantee(
1593- product, product.owner, product.owner)
1594+ with admin_logged_in():
1595+ invisible_information_types = self.service.deletePillarGrantee(
1596+ product, product.owner, product.owner)
1597 self.assertContentEqual(
1598 ['Private', 'Private Security'], invisible_information_types)
1599
1600 def _assert_deletePillarGranteeUnauthorized(self, pillar):
1601 # deletePillarGrantee raises an Unauthorized exception if the user
1602 # is not permitted to do so.
1603- with FeatureFixture(WRITE_FLAG):
1604- self.assertRaises(
1605- Unauthorized, self.service.deletePillarGrantee,
1606- pillar, pillar.owner, pillar.owner, [InformationType.USERDATA])
1607+ self.assertRaises(
1608+ Unauthorized, self.service.deletePillarGrantee,
1609+ pillar, pillar.owner, pillar.owner, [InformationType.USERDATA])
1610
1611 def test_deletePillarGranteeAnonymous(self):
1612 # Anonymous users are not allowed.
1613- with FeatureFixture(WRITE_FLAG):
1614- product = self.factory.makeProduct()
1615- login(ANONYMOUS)
1616- self._assert_deletePillarGranteeUnauthorized(product)
1617+ product = self.factory.makeProduct()
1618+ login(ANONYMOUS)
1619+ self._assert_deletePillarGranteeUnauthorized(product)
1620
1621 def test_deletePillarGranteeAnyone(self):
1622 # Unauthorized users are not allowed.
1623- with FeatureFixture(WRITE_FLAG):
1624- product = self.factory.makeProduct()
1625- login_person(self.factory.makePerson())
1626- self._assert_deletePillarGranteeUnauthorized(product)
1627-
1628- def test_deletePillarGrantee_without_flag(self):
1629- # The feature flag needs to be enabled.
1630- owner = self.factory.makePerson()
1631- product = self.factory.makeProduct(owner=owner)
1632- login_person(owner)
1633- self.assertRaises(
1634- Unauthorized, self.service.deletePillarGrantee,
1635- product, product.owner, product.owner, [InformationType.USERDATA])
1636+ product = self.factory.makeProduct()
1637+ login_person(self.factory.makePerson())
1638+ self._assert_deletePillarGranteeUnauthorized(product)
1639
1640 def _assert_deleteGranteeRemoveSubscriptions(self,
1641 types_to_delete=None):
1642@@ -839,9 +779,8 @@
1643 bug.subscribe(person, product.owner)
1644
1645 # Delete data for specified information types or all.
1646- with FeatureFixture(WRITE_FLAG):
1647- self.service.deletePillarGrantee(
1648- product, grantee, product.owner, types_to_delete)
1649+ self.service.deletePillarGrantee(
1650+ product, grantee, product.owner, types_to_delete)
1651 with block_on_job(self):
1652 transaction.commit()
1653
1654@@ -907,9 +846,8 @@
1655 apgfs = getUtility(IAccessPolicyGrantFlatSource)
1656 self.assertEqual(1, grants.count())
1657
1658- with FeatureFixture(WRITE_FLAG):
1659- self.service.revokeAccessGrants(
1660- pillar, grantee, pillar.owner, bugs=bugs, branches=branches)
1661+ self.service.revokeAccessGrants(
1662+ pillar, grantee, pillar.owner, bugs=bugs, branches=branches)
1663 with block_on_job(self):
1664 transaction.commit()
1665
1666@@ -993,10 +931,8 @@
1667 for bug in bugs or []:
1668 self.assertIn(person, bug.getDirectSubscribers())
1669
1670- with FeatureFixture(WRITE_FLAG):
1671- self.service.revokeAccessGrants(
1672- pillar, team_grantee, pillar.owner,
1673- bugs=bugs, branches=branches)
1674+ self.service.revokeAccessGrants(
1675+ pillar, team_grantee, pillar.owner, bugs=bugs, branches=branches)
1676 with block_on_job(self):
1677 transaction.commit()
1678
1679@@ -1042,43 +978,27 @@
1680 bug = self.factory.makeBug(
1681 target=product, information_type=InformationType.USERDATA)
1682 grantee = self.factory.makePerson()
1683- with FeatureFixture(WRITE_FLAG):
1684- self.assertRaises(
1685- Unauthorized, self.service.revokeAccessGrants,
1686- product, grantee, product.owner, bugs=[bug])
1687+ self.assertRaises(
1688+ Unauthorized, self.service.revokeAccessGrants,
1689+ product, grantee, product.owner, bugs=[bug])
1690
1691 def test_revokeAccessGrantsAnonymous(self):
1692 # Anonymous users are not allowed.
1693- with FeatureFixture(WRITE_FLAG):
1694- login(ANONYMOUS)
1695- self._assert_revokeAccessGrantsUnauthorized()
1696+ login(ANONYMOUS)
1697+ self._assert_revokeAccessGrantsUnauthorized()
1698
1699 def test_revokeAccessGrantsAnyone(self):
1700 # Unauthorized users are not allowed.
1701- with FeatureFixture(WRITE_FLAG):
1702- login_person(self.factory.makePerson())
1703- self._assert_revokeAccessGrantsUnauthorized()
1704-
1705- def test_revokeAccessGrants_without_flag(self):
1706- # The feature flag needs to be enabled.
1707- owner = self.factory.makePerson()
1708- product = self.factory.makeProduct(owner=owner)
1709- bug = self.factory.makeBug(
1710- target=product, information_type=InformationType.USERDATA)
1711- grantee = self.factory.makePerson()
1712- login_person(owner)
1713- self.assertRaises(
1714- Unauthorized, self.service.revokeAccessGrants,
1715- product, grantee, product.owner, bugs=[bug])
1716+ login_person(self.factory.makePerson())
1717+ self._assert_revokeAccessGrantsUnauthorized()
1718
1719 def _assert_ensureAccessGrants(self, user, bugs, branches,
1720 grantee=None):
1721 # Creating access grants works as expected.
1722 if not grantee:
1723 grantee = self.factory.makePerson()
1724- with FeatureFixture(WRITE_FLAG):
1725- self.service.ensureAccessGrants(
1726- [grantee], user, bugs=bugs, branches=branches)
1727+ self.service.ensureAccessGrants(
1728+ [grantee], user, bugs=bugs, branches=branches)
1729
1730 # Check that grantee has expected access grants.
1731 shared_bugs = []
1732@@ -1133,8 +1053,7 @@
1733 information_type=InformationType.USERDATA)
1734 # Create an existing access grant.
1735 grantee = self.factory.makePerson()
1736- with FeatureFixture(WRITE_FLAG):
1737- self.service.ensureAccessGrants([grantee], owner, bugs=[bug])
1738+ self.service.ensureAccessGrants([grantee], owner, bugs=[bug])
1739 # Test with a new bug as well as the one for which access is already
1740 # granted.
1741 self._assert_ensureAccessGrants(owner, [bug, bug2], None, grantee)
1742@@ -1146,35 +1065,20 @@
1743 bug = self.factory.makeBug(
1744 target=product, information_type=InformationType.USERDATA)
1745 grantee = self.factory.makePerson()
1746- with FeatureFixture(WRITE_FLAG):
1747- self.assertRaises(
1748- Unauthorized, self.service.ensureAccessGrants,
1749- [grantee], user, bugs=[bug])
1750+ self.assertRaises(
1751+ Unauthorized, self.service.ensureAccessGrants, [grantee], user,
1752+ bugs=[bug])
1753
1754 def test_ensureAccessGrantsAnonymous(self):
1755 # Anonymous users are not allowed.
1756- with FeatureFixture(WRITE_FLAG):
1757- login(ANONYMOUS)
1758- self._assert_ensureAccessGrantsUnauthorized(ANONYMOUS)
1759+ login(ANONYMOUS)
1760+ self._assert_ensureAccessGrantsUnauthorized(ANONYMOUS)
1761
1762 def test_ensureAccessGrantsAnyone(self):
1763 # Unauthorized users are not allowed.
1764- with FeatureFixture(WRITE_FLAG):
1765- anyone = self.factory.makePerson()
1766- login_person(anyone)
1767- self._assert_ensureAccessGrantsUnauthorized(anyone)
1768-
1769- def test_ensureAccessGrants_without_flag(self):
1770- # The feature flag needs to be enabled.
1771- owner = self.factory.makePerson()
1772- product = self.factory.makeProduct(owner=owner)
1773- bug = self.factory.makeBug(
1774- target=product, information_type=InformationType.USERDATA)
1775- grantee = self.factory.makePerson()
1776- login_person(owner)
1777- self.assertRaises(
1778- Unauthorized, self.service.ensureAccessGrants,
1779- [grantee], product.owner, bugs=[bug])
1780+ anyone = self.factory.makePerson()
1781+ login_person(anyone)
1782+ self._assert_ensureAccessGrantsUnauthorized(anyone)
1783
1784 def test_getSharedArtifacts(self):
1785 # Test the getSharedArtifacts method.
1786@@ -1385,14 +1289,13 @@
1787 right_person = self.factory.makePerson()
1788 right_team = self.factory.makeTeam(members=[right_person])
1789 wrong_person = self.factory.makePerson()
1790- with FeatureFixture(WRITE_FLAG):
1791- with admin_logged_in():
1792- self.service.sharePillarInformation(
1793- product, right_team, product.owner,
1794- {InformationType.USERDATA: SharingPermission.ALL})
1795- self.service.sharePillarInformation(
1796- product, wrong_person, product.owner,
1797- {InformationType.PRIVATESECURITY: SharingPermission.ALL})
1798+ with admin_logged_in():
1799+ self.service.sharePillarInformation(
1800+ product, right_team, product.owner,
1801+ {InformationType.USERDATA: SharingPermission.ALL})
1802+ self.service.sharePillarInformation(
1803+ product, wrong_person, product.owner,
1804+ {InformationType.PRIVATESECURITY: SharingPermission.ALL})
1805 self.assertEqual(
1806 False,
1807 self.service.checkPillarAccess(
1808@@ -1415,11 +1318,10 @@
1809 # an information type.
1810 product = self.factory.makeProduct()
1811 grantee = self.factory.makePerson()
1812- with FeatureFixture(WRITE_FLAG):
1813- with admin_logged_in():
1814- self.service.sharePillarInformation(
1815- product, grantee, product.owner,
1816- {InformationType.USERDATA: SharingPermission.ALL})
1817+ with admin_logged_in():
1818+ self.service.sharePillarInformation(
1819+ product, grantee, product.owner,
1820+ {InformationType.USERDATA: SharingPermission.ALL})
1821 # The owner is granted access on product creation. So we need to allow
1822 # for that in the check below.
1823 self.assertContentEqual(
1824@@ -1431,10 +1333,9 @@
1825 # checkPillarAccess checks whether the user has full access to
1826 # an information type.
1827 product = self.factory.makeProduct()
1828- with FeatureFixture(WRITE_FLAG):
1829- with admin_logged_in():
1830- self.service.deletePillarGrantee(
1831- product, product.owner, product.owner)
1832+ with admin_logged_in():
1833+ self.service.deletePillarGrantee(
1834+ product, product.owner, product.owner)
1835 self.assertContentEqual(
1836 [(InformationType.PRIVATESECURITY, 0),
1837 (InformationType.USERDATA, 0)],
1838@@ -1499,14 +1400,13 @@
1839
1840 def _sharePillarInformation(self):
1841 pillar_uri = canonical_url(self.pillar, force_local_path=True)
1842- with FeatureFixture(WRITE_FLAG):
1843- return self._named_post(
1844- 'sharePillarInformation', pillar=pillar_uri,
1845- grantee=self.grantee_uri,
1846- user=self.grantor_uri,
1847- permissions={
1848- InformationType.USERDATA.title:
1849- SharingPermission.ALL.title})
1850+ return self._named_post(
1851+ 'sharePillarInformation', pillar=pillar_uri,
1852+ grantee=self.grantee_uri,
1853+ user=self.grantor_uri,
1854+ permissions={
1855+ InformationType.USERDATA.title:
1856+ SharingPermission.ALL.title})
1857
1858
1859 class TestLaunchpadlib(ApiTestMixin, TestCaseWithFactory):
1860@@ -1518,9 +1418,6 @@
1861 super(TestLaunchpadlib, self).setUp()
1862 self.launchpad = self.factory.makeLaunchpadService(person=self.owner)
1863 self.service = self.launchpad.load('+services/sharing')
1864- flag = FeatureFixture(WRITE_FLAG)
1865- flag.setUp()
1866- self.addCleanup(flag.cleanUp)
1867 transaction.commit()
1868 self._sharePillarInformation()
1869
1870
1871=== modified file 'lib/lp/registry/tests/test_teammembership.py'
1872--- lib/lp/registry/tests/test_teammembership.py 2012-08-14 23:27:07 +0000
1873+++ lib/lp/registry/tests/test_teammembership.py 2012-08-28 04:39:25 +0000
1874@@ -504,7 +504,7 @@
1875 The number of db queries should be constant not O(depth).
1876 """
1877 self.assertStatementCount(
1878- 7,
1879+ 9,
1880 self.team5.setMembershipData, self.no_priv,
1881 TeamMembershipStatus.DEACTIVATED, self.team5.teamowner)
1882
1883@@ -998,7 +998,6 @@
1884
1885 def setUp(self):
1886 self.useFixture(FeatureFixture({
1887- 'disclosure.unsubscribe_jobs.enabled': 'true',
1888 'jobs.celery.enabled_classes': 'RemoveArtifactSubscriptionsJob',
1889 }))
1890 super(TestTeamMembershipJobs, self).setUp()
1891
1892=== modified file 'lib/lp/services/features/flags.py'
1893--- lib/lp/services/features/flags.py 2012-08-14 18:51:43 +0000
1894+++ lib/lp/services/features/flags.py 2012-08-28 04:39:25 +0000
1895@@ -197,12 +197,6 @@
1896 '',
1897 '',
1898 ''),
1899- ('disclosure.add-team-person-picker.enabled',
1900- 'boolean',
1901- 'Allows users to add a new team directly from the person picker.',
1902- '',
1903- '',
1904- ''),
1905 ('bugs.autoconfirm.enabled_distribution_names',
1906 'space delimited',
1907 ('Enables auto-confirming bugtasks for distributions (and their '
1908@@ -233,34 +227,6 @@
1909 '',
1910 '',
1911 ''),
1912- ('disclosure.enhanced_sharing.enabled',
1913- 'boolean',
1914- ('If true, will allow the use of the new sharing view and apis used '
1915- 'for the new disclosure data model to view but not write data.'),
1916- '',
1917- 'Sharing overview',
1918- ''),
1919- ('disclosure.enhanced_sharing_details.enabled',
1920- 'boolean',
1921- ('If true, enables the details page for viewing the `Some` things that'
1922- 'shared with a user or team.'),
1923- '',
1924- '',
1925- ''),
1926- ('disclosure.enhanced_sharing.writable',
1927- 'boolean',
1928- ('If true, will allow the use of the new sharing view and apis used '
1929- 'to edit the new disclosure data model.'),
1930- '',
1931- 'Sharing management',
1932- ''),
1933- ('disclosure.unsubscribe_jobs.enabled',
1934- 'boolean',
1935- ('If true, the jobs to unsubscribe users who lose access to bugs'
1936- 'and branches are run.'),
1937- '',
1938- '',
1939- ''),
1940 ('registry.upcoming_work_view.enabled',
1941 'boolean',
1942 ('If true, the new upcoming work view of teams is available.'),