Merge lp:~stevenk/launchpad/destroy-private-projects-feature-flags into lp:launchpad

Proposed by Steve Kowalik
Status: Merged
Merged at revision: 16483
Proposed branch: lp:~stevenk/launchpad/destroy-private-projects-feature-flags
Merge into: lp:launchpad
Diff against target: 940 lines (+91/-278)
13 files modified
lib/lp/blueprints/browser/specification.py (+11/-35)
lib/lp/blueprints/browser/tests/test_specification.py (+0/-49)
lib/lp/blueprints/templates/specification-index.pt (+1/-1)
lib/lp/registry/browser/pillar.py (+3/-6)
lib/lp/registry/browser/product.py (+26/-46)
lib/lp/registry/browser/tests/project-add-views.txt (+3/-0)
lib/lp/registry/browser/tests/test_pillar_sharing.py (+3/-17)
lib/lp/registry/browser/tests/test_product.py (+41/-67)
lib/lp/registry/browser/tests/test_projectgroup.py (+1/-8)
lib/lp/registry/browser/tests/test_sourcepackage_views.py (+1/-4)
lib/lp/registry/model/product.py (+0/-3)
lib/lp/registry/tests/test_product.py (+0/-23)
lib/lp/services/features/flags.py (+1/-19)
To merge this branch: bzr merge lp:~stevenk/launchpad/destroy-private-projects-feature-flags
Reviewer Review Type Date Requested Status
William Grant code Approve
Review via email: mp+147022@code.launchpad.net

Description of the change

Destroy the three private project feature flags.

To post a comment you must log in.
Revision history for this message
William Grant (wgrant) :
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/blueprints/browser/specification.py'
2--- lib/lp/blueprints/browser/specification.py 2013-01-30 05:31:20 +0000
3+++ lib/lp/blueprints/browser/specification.py 2013-02-07 06:17:24 +0000
4@@ -125,7 +125,6 @@
5 from lp.registry.interfaces.product import IProduct
6 from lp.registry.interfaces.productseries import IProductSeries
7 from lp.services.config import config
8-from lp.services.features import getFeatureFlag
9 from lp.services.fields import WorkItemsText
10 from lp.services.propertycache import cachedproperty
11 from lp.services.webapp import (
12@@ -144,21 +143,12 @@
13 )
14
15
16-INFORMATION_TYPE_FLAG = 'blueprints.information_type.enabled'
17-
18-
19 class INewSpecification(Interface):
20 """A schema for a new specification."""
21
22 use_template(ISpecification, include=[
23- 'name',
24- 'title',
25- 'specurl',
26- 'summary',
27- 'assignee',
28- 'drafter',
29- 'approver',
30- ])
31+ 'name', 'title', 'specurl', 'summary', 'assignee', 'drafter',
32+ 'approver'])
33
34 definition_status = Choice(
35 title=_('Definition Status'),
36@@ -225,8 +215,6 @@
37 Does nothing if the user cannot select different information types or
38 the feature flag is not enabled.
39 """
40- if not getFeatureFlag(INFORMATION_TYPE_FLAG):
41- return fields
42 if len(self.info_types) < 2:
43 return fields
44 info_type_field = copy_field(ISpecification['information_type'],
45@@ -318,10 +306,6 @@
46 def validate(self, data):
47 """See `LaunchpadFormView`.`"""
48 super(NewSpecificationView, self).validate(data)
49- self.validate_information_type(data)
50-
51- def validate_information_type(self, data):
52- """Validate the information type is allowed for this context."""
53 information_type = data.get('information_type', None)
54 if information_type is None:
55 # We rely on the model to set the correct default value.
56@@ -519,14 +503,11 @@
57 class SpecificationContextMenu(ContextMenu, SpecificationEditLinksMixin):
58
59 usedfor = ISpecification
60- links = ['edit', 'people', 'status', 'priority',
61- 'whiteboard', 'proposegoal', 'workitems',
62- 'milestone', 'subscription',
63- 'addsubscriber',
64- 'linkbug', 'unlinkbug', 'linkbranch',
65- 'adddependency', 'removedependency',
66- 'dependencytree', 'linksprint', 'supersede',
67- 'retarget', 'information_type']
68+ links = ['edit', 'people', 'status', 'priority', 'whiteboard',
69+ 'proposegoal', 'workitems', 'milestone', 'subscription',
70+ 'addsubscriber', 'linkbug', 'unlinkbug', 'linkbranch',
71+ 'adddependency', 'removedependency', 'dependencytree',
72+ 'linksprint', 'supersede', 'retarget', 'information_type']
73
74 @enabled_with_permission('launchpad.Edit')
75 def milestone(self):
76@@ -1537,16 +1518,13 @@
77
78 @action(_('Continue'), name='continue')
79 def continue_action(self, action, data):
80- self.context.linkBranch(branch=data['branch'],
81- registrant=self.user)
82+ self.context.linkBranch(branch=data['branch'], registrant=self.user)
83
84 @property
85 def next_url(self):
86 return canonical_url(self.context)
87
88- @property
89- def cancel_url(self):
90- return canonical_url(self.context)
91+ cancel_url = next_url
92
93
94 class SpecificationSetView(AppFrontPageSearchView, HasSpecificationsView):
95@@ -1600,8 +1578,7 @@
96 if starter is None:
97 return ''
98 date_formatter = DateTimeFormatterAPI(context.date_started)
99- return "%s %s" % (
100- format_link(starter), date_formatter.displaydate())
101+ return "%s %s" % (format_link(starter), date_formatter.displaydate())
102 return render
103
104
105@@ -1615,6 +1592,5 @@
106 if completer is None:
107 return ''
108 date_formatter = DateTimeFormatterAPI(context.date_completed)
109- return "%s %s" % (
110- format_link(completer), date_formatter.displaydate())
111+ return "%s %s" % (format_link(completer), date_formatter.displaydate())
112 return render
113
114=== modified file 'lib/lp/blueprints/browser/tests/test_specification.py'
115--- lib/lp/blueprints/browser/tests/test_specification.py 2013-01-31 05:34:42 +0000
116+++ lib/lp/blueprints/browser/tests/test_specification.py 2013-02-07 06:17:24 +0000
117@@ -27,7 +27,6 @@
118 from lp.app.enums import InformationType
119 from lp.app.interfaces.services import IService
120 from lp.blueprints.browser import specification
121-from lp.blueprints.browser.specification import INFORMATION_TYPE_FLAG
122 from lp.blueprints.enums import SpecificationImplementationStatus
123 from lp.blueprints.interfaces.specification import (
124 ISpecification,
125@@ -36,7 +35,6 @@
126 from lp.registry.enums import SpecificationSharingPolicy
127 from lp.registry.interfaces.person import PersonVisibility
128 from lp.registry.interfaces.product import IProductSeries
129-from lp.services.features.testing import FeatureFixture
130 from lp.services.webapp.escaping import html_escape
131 from lp.services.webapp.interaction import ANONYMOUS
132 from lp.services.webapp.interfaces import BrowserNotificationLevel
133@@ -219,12 +217,6 @@
134 self.assertIn(spec_name, view.contents)
135
136
137-def set_blueprint_information_type(test_case, enabled):
138- value = 'true' if enabled else ''
139- fixture = FeatureFixture({INFORMATION_TYPE_FLAG: value})
140- test_case.useFixture(fixture)
141-
142-
143 class TestSpecificationSet(BrowserTestCase):
144
145 layer = DatabaseFunctionalLayer
146@@ -268,10 +260,6 @@
147 portlet_tag = soupmatchers.Tag(
148 'info-type-portlet', True, attrs=dict(id='information-type-summary'))
149
150- def setUp(self):
151- super(TestSpecificationInformationType, self).setUp()
152- set_blueprint_information_type(self, True)
153-
154 def assertBrowserMatches(self, matcher):
155 browser = self.getViewBrowser(self.factory.makeSpecification())
156 self.assertThat(browser.contents, matcher)
157@@ -279,11 +267,6 @@
158 def test_has_privacy_portlet(self):
159 self.assertBrowserMatches(soupmatchers.HTMLContains(self.portlet_tag))
160
161- def test_privacy_portlet_requires_flag(self):
162- set_blueprint_information_type(self, False)
163- self.assertBrowserMatches(
164- Not(soupmatchers.HTMLContains(self.portlet_tag)))
165-
166 def test_has_privacy_banner(self):
167 owner = self.factory.makePerson()
168 policy = SpecificationSharingPolicy.PUBLIC_OR_PROPRIETARY
169@@ -433,7 +416,6 @@
170
171 def test_allowed_info_type_validated(self):
172 """information_type must be validated against context"""
173- set_blueprint_information_type(self, True)
174 context = getUtility(ISpecificationSet)
175 product = self.factory.makeProduct()
176 form = self._create_form_data(product.name)
177@@ -454,7 +436,6 @@
178
179 def test_allowed_info_type_validated(self):
180 """information_type must be validated against context"""
181- set_blueprint_information_type(self, True)
182 sprint = self.factory.makeSprint()
183 product = self.factory.makeProduct(owner=sprint.owner)
184 form = self._create_form_data(product.name)
185@@ -474,7 +455,6 @@
186
187 def test_allowed_info_type_validated(self):
188 """information_type must be validated against context"""
189- set_blueprint_information_type(self, True)
190 project = self.factory.makeProject()
191 product = self.factory.makeProduct(project=project)
192 form = self._create_form_data(product.name)
193@@ -522,7 +502,6 @@
194
195 def setUp(self):
196 super(TestNewSpecificationInformationType, self).setUp()
197- set_blueprint_information_type(self, True)
198 it_field = soupmatchers.Tag(
199 'it-field', True, attrs=dict(name='field.information_type'))
200 self.match_it = soupmatchers.HTMLContains(it_field)
201@@ -532,25 +511,12 @@
202 browser = self.getUserBrowser(NEW_SPEC_FROM_ROOT_URL)
203 self.assertThat(browser.contents, self.match_it)
204
205- def test_from_root_no_flag(self):
206- """Information_type is excluded with no flag."""
207- set_blueprint_information_type(self, False)
208- browser = self.getUserBrowser(NEW_SPEC_FROM_ROOT_URL)
209- self.assertThat(browser.contents, Not(self.match_it))
210-
211 def test_from_sprint(self):
212 """Information_type is included creating from a sprint."""
213 sprint = self.factory.makeSprint()
214 browser = self.getViewBrowser(sprint, view_name='+addspec')
215 self.assertThat(browser.contents, self.match_it)
216
217- def test_from_sprint_no_flag(self):
218- """Information_type is excluded with no flag."""
219- set_blueprint_information_type(self, False)
220- sprint = self.factory.makeSprint()
221- browser = self.getViewBrowser(sprint, view_name='+addspec')
222- self.assertThat(browser.contents, Not(self.match_it))
223-
224 def submitSpec(self, browser):
225 """Submit a Specification via a browser."""
226 name = self.factory.getUniqueString()
227@@ -592,13 +558,6 @@
228 SpecificationSharingPolicy.EMBARGOED_OR_PROPRIETARY)
229 self.assertEqual(InformationType.EMBARGOED, spec.information_type)
230
231- def test_from_product_no_flag(self):
232- """information_type is excluded with no flag."""
233- set_blueprint_information_type(self, False)
234- product = self.factory.makeProduct()
235- browser = self.getViewBrowser(product, view_name='+addspec')
236- self.assertThat(browser.contents, Not(self.match_it))
237-
238 def test_from_productseries(self):
239 """Information_type is included creating from productseries."""
240 policy = SpecificationSharingPolicy.PUBLIC_OR_PROPRIETARY
241@@ -608,13 +567,6 @@
242 browser = self.getViewBrowser(series, view_name='+addspec')
243 self.assertThat(browser.contents, self.match_it)
244
245- def test_from_productseries_no_flag(self):
246- """information_type is excluded with no flag."""
247- set_blueprint_information_type(self, False)
248- series = self.factory.makeProductSeries()
249- browser = self.getViewBrowser(series, view_name='+addspec')
250- self.assertThat(browser.contents, Not(self.match_it))
251-
252 def test_from_distribution(self):
253 """information_type is excluded creating from distro."""
254 distro = self.factory.makeDistribution()
255@@ -633,7 +585,6 @@
256 layer = DatabaseFunctionalLayer
257
258 def _setUp(self):
259- set_blueprint_information_type(self, True)
260 it_field = soupmatchers.Tag(
261 'it-field', True, attrs=dict(name='field.information_type'))
262 self.match_it = soupmatchers.HTMLContains(it_field)
263
264=== modified file 'lib/lp/blueprints/templates/specification-index.pt'
265--- lib/lp/blueprints/templates/specification-index.pt 2012-10-15 16:01:38 +0000
266+++ lib/lp/blueprints/templates/specification-index.pt 2013-02-07 06:17:24 +0000
267@@ -386,7 +386,7 @@
268
269 <tal:side metal:fill-slot="side">
270 <tal:menu replace="structure context/@@+global-actions" />
271- <tal:privacy replace="structure context/@@+portlet-privacy" condition="features/blueprints.information_type.enabled" />
272+ <tal:privacy replace="structure context/@@+portlet-privacy" />
273 <div tal:replace="structure context/@@+portlet-subscribers" />
274 </tal:side>
275 </body>
276
277=== modified file 'lib/lp/registry/browser/pillar.py'
278--- lib/lp/registry/browser/pillar.py 2012-12-18 16:41:18 +0000
279+++ lib/lp/registry/browser/pillar.py 2013-02-07 06:17:24 +0000
280@@ -1,4 +1,4 @@
281-# Copyright 2009-2012 Canonical Ltd. This software is licensed under the
282+# Copyright 2009-2013 Canonical Ltd. This software is licensed under the
283 # GNU Affero General Public License version 3 (see the file LICENSE).
284
285 """Common views for objects that implement `IPillar`."""
286@@ -56,7 +56,6 @@
287 from lp.registry.interfaces.projectgroup import IProjectGroup
288 from lp.registry.model.pillar import PillarPerson
289 from lp.services.config import config
290-from lp.services.features import getFeatureFlag
291 from lp.services.propertycache import cachedproperty
292 from lp.services.webapp.authorization import check_permission
293 from lp.services.webapp.batching import (
294@@ -294,10 +293,8 @@
295
296 @property
297 def specification_sharing_policies(self):
298- if getFeatureFlag('blueprints.information_type.enabled'):
299- return self._getSharingService().getSpecificationSharingPolicies(
300- self.context)
301- return None
302+ return self._getSharingService().getSpecificationSharingPolicies(
303+ self.context)
304
305 @property
306 def sharing_permissions(self):
307
308=== modified file 'lib/lp/registry/browser/product.py'
309--- lib/lp/registry/browser/product.py 2012-11-28 21:26:06 +0000
310+++ lib/lp/registry/browser/product.py 2013-02-07 06:17:24 +0000
311@@ -1,4 +1,4 @@
312-# Copyright 2009-2012 Canonical Ltd. This software is licensed under the
313+# Copyright 2009-2013 Canonical Ltd. This software is licensed under the
314 # GNU Affero General Public License version 3 (see the file LICENSE).
315
316 """Browser views for products."""
317@@ -174,7 +174,6 @@
318 from lp.registry.interfaces.sourcepackagename import ISourcePackageNameSet
319 from lp.services.config import config
320 from lp.services.database.decoratedresultset import DecoratedResultSet
321-from lp.services.features import getFeatureFlag
322 from lp.services.feeds.browser import FeedsMixin
323 from lp.services.fields import (
324 PillarAliases,
325@@ -209,7 +208,6 @@
326
327 OR = ' OR '
328 SPACE = ' '
329-PRIVATE_PROJECTS_FLAG = 'disclosure.private_projects.enabled'
330
331
332 class ProductNavigation(
333@@ -1397,8 +1395,7 @@
334 custom_widget('licenses', LicenseWidget)
335 custom_widget('license_info', GhostWidget)
336 custom_widget(
337- 'information_type',
338- LaunchpadRadioWidgetWithDescription,
339+ 'information_type', LaunchpadRadioWidgetWithDescription,
340 vocabulary=InformationTypeVocabulary(
341 types=PUBLIC_PROPRIETARY_INFORMATION_TYPES))
342
343@@ -1424,19 +1421,10 @@
344 # the form is rendered during LaunchpadFormView's initialize()
345 # when an action is invoked.
346 cache = IJSONRequestCache(self.request)
347- json_dump_information_types(cache,
348- PUBLIC_PROPRIETARY_INFORMATION_TYPES)
349+ json_dump_information_types(
350+ cache, PUBLIC_PROPRIETARY_INFORMATION_TYPES)
351 super(ProductEditView, self).initialize()
352
353- def setUpFields(self):
354- """See `LaunchpadFormView`."""
355- super(ProductEditView, self).setUpFields()
356-
357- private_projects_flag = 'disclosure.private_projects.enabled'
358- private_projects = bool(getFeatureFlag(private_projects_flag))
359- if not private_projects:
360- self.form_fields = self.form_fields.omit('information_type')
361-
362 def validate(self, data):
363 """Validate 'licenses' and 'license_info'.
364
365@@ -1447,10 +1435,11 @@
366 or "Other/Open Source" is checked.
367 """
368 super(ProductEditView, self).validate(data)
369- info_type = data.get('information_type')
370- if info_type is not None:
371- errors = [str(e) for e in
372- self.context.checkInformationType(info_type)]
373+ information_type = data.get('information_type')
374+ if information_type:
375+ errors = [
376+ str(e) for e in self.context.checkInformationType(
377+ information_type)]
378 if len(errors) > 0:
379 self.setFieldError('information_type', ' '.join(errors))
380
381@@ -1881,9 +1870,7 @@
382 def setUpFields(self):
383 """See `LaunchpadFormView`."""
384 super(ProjectAddStepOne, self).setUpFields()
385- self.form_fields = (
386- self.form_fields +
387- create_source_package_fields())
388+ self.form_fields = (self.form_fields + create_source_package_fields())
389
390 def setUpWidgets(self):
391 """See `LaunchpadFormView`."""
392@@ -1925,8 +1912,7 @@
393
394 _field_names = ['displayname', 'name', 'title', 'summary', 'description',
395 'homepageurl', 'information_type', 'licenses',
396- 'license_info', 'driver', 'bug_supervisor', 'owner',
397- ]
398+ 'license_info', 'driver', 'bug_supervisor', 'owner']
399 schema = IProduct
400 step_name = 'projectaddstep2'
401 template = ViewPageTemplateFile('../templates/product-new.pt')
402@@ -1962,8 +1948,8 @@
403 # the form is rendered during LaunchpadFormView's initialize()
404 # when an action is invoked.
405 cache = IJSONRequestCache(self.request)
406- json_dump_information_types(cache,
407- PUBLIC_PROPRIETARY_INFORMATION_TYPES)
408+ json_dump_information_types(
409+ cache, PUBLIC_PROPRIETARY_INFORMATION_TYPES)
410 super(ProjectAddStepTwo, self).initialize()
411
412 @property
413@@ -1972,8 +1958,7 @@
414 return u'Complete Registration'
415 else:
416 return u'Complete registration and link to %s package' % (
417- self.source_package_name.name,
418- )
419+ self.source_package_name.name)
420
421 @property
422 def _return_url(self):
423@@ -2003,8 +1988,7 @@
424
425 @property
426 def enable_information_type(self):
427- private_projects = bool(getFeatureFlag(PRIVATE_PROJECTS_FLAG))
428- return private_projects and not self.source_package_name
429+ return not self.source_package_name
430
431 def setUpFields(self):
432 """See `LaunchpadFormView`."""
433@@ -2013,14 +1997,13 @@
434 hidden_fields = self.form_fields.select(*hidden_names)
435
436 if not self.enable_information_type:
437- hidden_names.extend([
438- 'information_type', 'bug_supervisor', 'driver'])
439+ hidden_names.extend(
440+ ['information_type', 'bug_supervisor', 'driver'])
441
442 visible_fields = self.form_fields.omit(*hidden_names)
443- self.form_fields = (visible_fields +
444- self._createDisclaimMaintainerField() +
445- create_source_package_fields() +
446- hidden_fields)
447+ self.form_fields = (
448+ visible_fields + self._createDisclaimMaintainerField() +
449+ create_source_package_fields() + hidden_fields)
450
451 def _createDisclaimMaintainerField(self):
452 """Return a Bool field for disclaiming maintainer.
453@@ -2048,8 +2031,8 @@
454 self.widgets['name'].read_only = True
455 # The "hint" is really more of an explanation at this point, but the
456 # phrasing is different.
457- self.widgets['name'].hint = ('When published, '
458- "this will be the project's URL.")
459+ self.widgets['name'].hint = (
460+ "When published, this will be the project's URL.")
461 self.widgets['displayname'].visible = False
462 self.widgets['source_package_name'].visible = False
463 self.widgets['distroseries'].visible = False
464@@ -2100,14 +2083,13 @@
465 """
466 # XXX BarryWarsaw 16-Apr-2009 do we need batching and should we return
467 # more than 7 hits?
468- pillar_set = getUtility(IPillarNameSet)
469- return pillar_set.search(self._search_string, 7)
470+ return getUtility(IPillarNameSet).search(self._search_string, 7)
471
472 @cachedproperty
473 def search_results_count(self):
474 """Return the count of matching `IPillar`s."""
475- pillar_set = getUtility(IPillarNameSet)
476- return pillar_set.count_search_matches(self._search_string)
477+ return getUtility(IPillarNameSet).count_search_matches(
478+ self._search_string)
479
480 # StepView requires that its validate() method not be overridden, so make
481 # sure this calls the right method. validateStep() will call the licence
482@@ -2130,8 +2112,7 @@
483 for required_field in ('bug_supervisor', 'driver'):
484 if data.get(required_field) is None:
485 self.setFieldError(
486- required_field,
487- 'Select a user or team.')
488+ required_field, 'Select a user or team.')
489
490 @property
491 def label(self):
492@@ -2194,7 +2175,6 @@
493 """The controlling view for product/+new."""
494
495 page_title = ProjectAddStepOne.page_title
496- related_features = (PRIVATE_PROJECTS_FLAG,)
497 total_steps = 2
498
499 @property
500
501=== modified file 'lib/lp/registry/browser/tests/project-add-views.txt'
502--- lib/lp/registry/browser/tests/project-add-views.txt 2012-07-30 20:02:26 +0000
503+++ lib/lp/registry/browser/tests/project-add-views.txt 2013-02-07 06:17:24 +0000
504@@ -130,6 +130,7 @@
505 ... print error
506 You must select at least one licence. If you select Other/Proprietary
507 or Other/OpenSource you must include a description of the licence.
508+ ...
509
510 When an open source licence is selected, the project is created.
511
512@@ -144,6 +145,8 @@
513 ... 'field.licenses': ['PYTHON'],
514 ... 'field.license_info': '',
515 ... 'field.owner': registrant.name,
516+ ... 'field.driver': registrant.name,
517+ ... 'field.bug_supervisor': registrant.name,
518 ... 'field.__visited_steps__': '%s|%s' % (
519 ... ProjectAddStepOne.step_name, ProjectAddStepTwo.step_name),
520 ... 'field.actions.continue': 'Continue',
521
522=== modified file 'lib/lp/registry/browser/tests/test_pillar_sharing.py'
523--- lib/lp/registry/browser/tests/test_pillar_sharing.py 2012-12-20 14:53:10 +0000
524+++ lib/lp/registry/browser/tests/test_pillar_sharing.py 2013-02-07 06:17:24 +0000
525@@ -1,4 +1,4 @@
526-# Copyright 2012 Canonical Ltd. This software is licensed under the
527+# Copyright 2012-2013 Canonical Ltd. This software is licensed under the
528 # GNU Affero General Public License version 3 (see the file LICENSE).
529
530 """Test views that manage sharing."""
531@@ -29,7 +29,6 @@
532 from lp.registry.model.pillar import PillarPerson
533 from lp.services.config import config
534 from lp.services.database.lpstorm import IStore
535-from lp.services.features.testing import FeatureFixture
536 from lp.services.webapp.interfaces import StormRangeFactoryError
537 from lp.services.webapp.publisher import canonical_url
538 from lp.testing import (
539@@ -270,9 +269,8 @@
540 self.assertIsNotNone(cache.objects.get('branch_sharing_policies'))
541 self.assertIsNotNone(cache.objects.get('bug_sharing_policies'))
542 self.assertIsNotNone(cache.objects.get('sharing_permissions'))
543- # Ensure we don't set specification_sharing_policies without the
544- # feature flag enabled.
545- self.assertIsNone(cache.objects.get('specification_sharing_policies'))
546+ self.assertIsNotNone(
547+ cache.objects.get('specification_sharing_policies'))
548 batch_size = config.launchpad.default_batch_size
549 apgfs = getUtility(IAccessPolicyGrantFlatSource)
550 grantees = apgfs.findGranteePermissionsByPolicy(
551@@ -282,18 +280,6 @@
552 self.assertContentEqual(
553 grantee_data, cache.objects.get('grantee_data'))
554
555- def test_view_date_model_adds_specification(self):
556- # This test can move up to the above test when not feature flagged,
557- # but for now, ensure specification_sharing_policies is added to
558- # the cache if the flag is set.
559- feature_flag = {
560- 'blueprints.information_type.enabled': 'on'}
561- with FeatureFixture(feature_flag):
562- view = create_initialized_view(self.pillar, name='+sharing')
563- cache = IJSONRequestCache(view.request)
564- self.assertIsNotNone(
565- cache.objects.get('specification_sharing_policies'))
566-
567 def test_view_batch_data(self):
568 # Test the expected batching data is in the json request cache.
569 view = create_initialized_view(self.pillar, name='+sharing')
570
571=== modified file 'lib/lp/registry/browser/tests/test_product.py'
572--- lib/lp/registry/browser/tests/test_product.py 2012-11-26 21:01:54 +0000
573+++ lib/lp/registry/browser/tests/test_product.py 2013-02-07 06:17:24 +0000
574@@ -1,4 +1,4 @@
575-# Copyright 2010-2012 Canonical Ltd. This software is licensed under the
576+# Copyright 2010-2013 Canonical Ltd. This software is licensed under the
577 # GNU Affero General Public License version 3 (see the file LICENSE).
578
579 """Tests for product views."""
580@@ -28,7 +28,6 @@
581 ServiceUsage,
582 )
583 from lp.registry.browser.product import (
584- PRIVATE_PROJECTS_FLAG,
585 ProjectAddStepOne,
586 ProjectAddStepTwo,
587 )
588@@ -43,7 +42,6 @@
589 from lp.registry.model.product import Product
590 from lp.services.config import config
591 from lp.services.database.lpstorm import IStore
592-from lp.services.features.testing import FeatureFixture
593 from lp.services.webapp.publisher import canonical_url
594 from lp.testing import (
595 BrowserTestCase,
596@@ -151,7 +149,7 @@
597 form['field.licenses'] = License.OTHER_PROPRIETARY.title
598 form['field.license_info'] = 'Commercial Subscription'
599 else:
600- form['field.information_type'] = 0
601+ form['field.information_type'] = 'PUBLIC'
602 form['field.owner'] = ''
603 form['field.licenses'] = ['MIT']
604 form['field.license_info'] = ''
605@@ -178,7 +176,6 @@
606 self.assertContentEqual(
607 team_membership_policy_data,
608 cache.objects['team_membership_policy_data'])
609- self.assertIn(PRIVATE_PROJECTS_FLAG, cache.objects['related_features'])
610
611 def test_staging_message_is_not_demo(self):
612 view = create_initialized_view(self.product_set, '+new')
613@@ -214,7 +211,8 @@
614 view.view.field_names)
615 self.assertEqual(
616 ['displayname', 'name', 'title', 'summary', 'description',
617- 'homepageurl', 'licenses', 'owner', 'disclaim_maintainer',
618+ 'homepageurl', 'information_type', 'licenses', 'driver',
619+ 'bug_supervisor', 'owner', 'disclaim_maintainer',
620 'source_package_name', 'distroseries', '__visited_steps__',
621 'license_info'],
622 [f.__name__ for f in view.view.form_fields])
623@@ -266,36 +264,25 @@
624 form = make_product_form(action=2)
625 form['field.owner'] = ''
626 form['field.disclaim_maintainer'] = 'on'
627+ form['field.information_type'] = 'PUBLIC'
628 view = create_initialized_view(self.product_set, '+new', form=form)
629 self.assertEqual(0, len(view.view.errors))
630 product = self.product_set.getByName('fnord')
631 self.assertEqual('registry', product.owner.name)
632
633- def test_information_type_saved_new_product_default(self):
634- # information_type should be PUBLIC by default for new projects.
635- # if the private projects feature flag is not enabled.
636- registrant = self.factory.makePerson()
637- login_person(registrant)
638- form = make_product_form(registrant, action=2, proprietary=True)
639- view = create_initialized_view(self.product_set, '+new', form=form)
640- self.assertEqual(0, len(view.view.errors))
641- product = self.product_set.getByName('fnord')
642- self.assertEqual(InformationType.PUBLIC, product.information_type)
643-
644 def test_information_type_saved_new_product_updated(self):
645 # information_type will be updated if passed in via form data,
646 # if the private projects feature flag is enabled.
647- with FeatureFixture({u'disclosure.private_projects.enabled': u'on'}):
648- registrant = self.factory.makePerson()
649- login_person(registrant)
650- form = make_product_form(registrant, action=2, proprietary=True)
651- form['field.maintainer'] = registrant.name
652- view = create_initialized_view(
653- self.product_set, '+new', form=form)
654- self.assertEqual(0, len(view.view.errors))
655- product = self.product_set.getByName('fnord')
656- self.assertEqual(
657- InformationType.PROPRIETARY, product.information_type)
658+ registrant = self.factory.makePerson()
659+ login_person(registrant)
660+ form = make_product_form(registrant, action=2, proprietary=True)
661+ form['field.maintainer'] = registrant.name
662+ view = create_initialized_view(
663+ self.product_set, '+new', form=form)
664+ self.assertEqual(0, len(view.view.errors))
665+ product = self.product_set.getByName('fnord')
666+ self.assertEqual(
667+ InformationType.PROPRIETARY, product.information_type)
668
669
670 class TestProductView(BrowserTestCase):
671@@ -488,37 +475,30 @@
672 def test_limited_information_types_allowed(self):
673 """Products can only be PUBLIC_PROPRIETARY_INFORMATION_TYPES"""
674 product = self.factory.makeProduct()
675- with FeatureFixture({u'disclosure.private_projects.enabled': u'on'}):
676- login_person(product.owner)
677- view = create_initialized_view(
678- product,
679- '+edit',
680- principal=product.owner)
681- vocabulary = view.widgets['information_type'].vocabulary
682- info_types = [t.name for t in vocabulary]
683- expected = ['PUBLIC', 'PROPRIETARY', 'EMBARGOED']
684- self.assertEqual(expected, info_types)
685+ login_person(product.owner)
686+ view = create_initialized_view(
687+ product, '+edit', principal=product.owner)
688+ vocabulary = view.widgets['information_type'].vocabulary
689+ info_types = [t.name for t in vocabulary]
690+ expected = ['PUBLIC', 'PROPRIETARY', 'EMBARGOED']
691+ self.assertEqual(expected, info_types)
692
693 def test_change_information_type_proprietary(self):
694 product = self.factory.makeProduct(name='fnord')
695- with FeatureFixture({u'disclosure.private_projects.enabled': u'on'}):
696- login_person(product.owner)
697- form = self._make_product_edit_form(product, proprietary=True)
698- view = create_initialized_view(product, '+edit', form=form)
699- self.assertEqual(0, len(view.errors))
700+ login_person(product.owner)
701+ form = self._make_product_edit_form(product, proprietary=True)
702+ view = create_initialized_view(product, '+edit', form=form)
703+ self.assertEqual(0, len(view.errors))
704
705- product_set = getUtility(IProductSet)
706- updated_product = product_set.getByName('fnord')
707- self.assertEqual(
708- InformationType.PROPRIETARY, updated_product.information_type)
709- # A complimentary commercial subscription is auto generated for
710- # the product when the information type is changed.
711- self.assertIsNotNone(updated_product.commercial_subscription)
712+ updated_product = getUtility(IProductSet).getByName('fnord')
713+ self.assertEqual(
714+ InformationType.PROPRIETARY, updated_product.information_type)
715+ # A complimentary commercial subscription is auto generated for
716+ # the product when the information type is changed.
717+ self.assertIsNotNone(updated_product.commercial_subscription)
718
719 def test_change_information_type_proprietary_packaged(self):
720 # It should be an error to make a Product private if it is packaged.
721- self.useFixture(FeatureFixture(
722- {u'disclosure.private_projects.enabled': u'on'}))
723 product = self.factory.makeProduct()
724 sourcepackage = self.factory.makeSourcePackage()
725 sourcepackage.setPackaging(product.development_focus, product.owner)
726@@ -537,8 +517,6 @@
727 product = self.factory.makeProduct()
728 self.factory.makeBranch(product=product)
729 self.factory.makeSpecification(product=product)
730- self.useFixture(FeatureFixture(
731- {u'disclosure.private_projects.enabled': u'on'}))
732 browser = self.getViewBrowser(product, '+edit', user=product.owner)
733 info_type = browser.getControl(name='field.information_type')
734 info_type.value = ['PROPRIETARY']
735@@ -552,20 +530,16 @@
736 def test_change_information_type_public(self):
737 owner = self.factory.makePerson(name='pting')
738 product = self.factory.makeProduct(
739- name='fnord',
740- information_type=InformationType.PROPRIETARY,
741- owner=owner,
742- )
743- with FeatureFixture({u'disclosure.private_projects.enabled': u'on'}):
744- login_person(owner)
745- form = self._make_product_edit_form(product)
746- view = create_initialized_view(product, '+edit', form=form)
747- self.assertEqual(0, len(view.errors))
748+ name='fnord', information_type=InformationType.PROPRIETARY,
749+ owner=owner)
750+ login_person(owner)
751+ form = self._make_product_edit_form(product)
752+ view = create_initialized_view(product, '+edit', form=form)
753+ self.assertEqual(0, len(view.errors))
754
755- product_set = getUtility(IProductSet)
756- updated_product = product_set.getByName('fnord')
757- self.assertEqual(
758- InformationType.PUBLIC, updated_product.information_type)
759+ updated_product = getUtility(IProductSet).getByName('fnord')
760+ self.assertEqual(
761+ InformationType.PUBLIC, updated_product.information_type)
762
763
764 class ProductSetReviewLicensesViewTestCase(TestCaseWithFactory):
765
766=== modified file 'lib/lp/registry/browser/tests/test_projectgroup.py'
767--- lib/lp/registry/browser/tests/test_projectgroup.py 2012-11-20 20:53:20 +0000
768+++ lib/lp/registry/browser/tests/test_projectgroup.py 2013-02-07 06:17:24 +0000
769@@ -1,4 +1,4 @@
770-# Copyright 2010-2012 Canonical Ltd. This software is licensed under the
771+# Copyright 2010-2013 Canonical Ltd. This software is licensed under the
772 # GNU Affero General Public License version 3 (see the file LICENSE).
773
774 """Tests for project group views."""
775@@ -21,7 +21,6 @@
776 )
777 from lp.registry.interfaces.person import IPersonSet
778 from lp.registry.interfaces.product import IProductSet
779-from lp.services.features.testing import FeatureFixture
780 from lp.services.webapp import canonical_url
781 from lp.services.webapp.interfaces import ILaunchBag
782 from lp.testing import (
783@@ -102,8 +101,6 @@
784 def test_mixed_product_projectgroup_milestone(self):
785 # If a milestone is mixed between public and proprietary products,
786 # only the public is shown to people without access.
787- self.useFixture(
788- FeatureFixture({u'disclosure.private_projects.enabled': u'on'}))
789 owner = self.factory.makePerson()
790 teammember = self.factory.makePerson()
791 owning_team = self.factory.makeTeam(owner=owner,
792@@ -205,8 +202,6 @@
793 def test_information_type(self):
794 # Information type controls are provided when creating a project via a
795 # project group.
796- self.useFixture(
797- FeatureFixture({u'disclosure.private_projects.enabled': u'on'}))
798 form = make_product_form(action=1)
799 project = self.factory.makeProject()
800 with person_logged_in(project.owner):
801@@ -217,8 +212,6 @@
802
803 def test_information_type_saved(self):
804 # Setting information_type to PROPRIETARY via form actually works.
805- self.useFixture(
806- FeatureFixture({u'disclosure.private_projects.enabled': u'on'}))
807 project = self.factory.makeProject()
808 form = make_product_form(project.owner, action=2, proprietary=True)
809 with person_logged_in(project.owner):
810
811=== modified file 'lib/lp/registry/browser/tests/test_sourcepackage_views.py'
812--- lib/lp/registry/browser/tests/test_sourcepackage_views.py 2012-11-12 22:27:55 +0000
813+++ lib/lp/registry/browser/tests/test_sourcepackage_views.py 2013-02-07 06:17:24 +0000
814@@ -1,4 +1,4 @@
815-# Copyright 2010-2012 Canonical Ltd. This software is licensed under the
816+# Copyright 2010-2013 Canonical Ltd. This software is licensed under the
817 # GNU Affero General Public License version 3 (see the file LICENSE).
818
819 """Tests for SourcePackage view code."""
820@@ -30,7 +30,6 @@
821 IDistroSeriesSet,
822 )
823 from lp.registry.interfaces.sourcepackage import ISourcePackage
824-from lp.services.features.testing import FeatureFixture
825 from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
826 from lp.testing import (
827 BrowserTestCase,
828@@ -165,8 +164,6 @@
829
830 def test_register_upstream_forbids_proprietary(self):
831 # Cannot specify information_type if registering for sourcepackage.
832- self.useFixture(FeatureFixture({'disclosure.private_projects.enabled':
833- 'on'}))
834 sourcepackage = self.factory.makeSourcePackage()
835 browser = self.getViewBrowser(sourcepackage)
836 browser.getControl("Register the upstream project").click()
837
838=== modified file 'lib/lp/registry/model/product.py'
839--- lib/lp/registry/model/product.py 2013-01-22 05:07:31 +0000
840+++ lib/lp/registry/model/product.py 2013-02-07 06:17:24 +0000
841@@ -200,7 +200,6 @@
842 SQLBase,
843 sqlvalues,
844 )
845-from lp.services.features import getFeatureFlag
846 from lp.services.propertycache import (
847 cachedproperty,
848 get_property_cache,
849@@ -1562,8 +1561,6 @@
850
851 def userCanView(self, user):
852 """See `IProductPublic`."""
853- if getFeatureFlag('disclosure.private_project.traversal_override'):
854- return True
855 if self.information_type in PUBLIC_INFORMATION_TYPES:
856 return True
857 if user is None:
858
859=== modified file 'lib/lp/registry/tests/test_product.py'
860--- lib/lp/registry/tests/test_product.py 2013-01-09 04:53:17 +0000
861+++ lib/lp/registry/tests/test_product.py 2013-02-07 06:17:24 +0000
862@@ -92,7 +92,6 @@
863 )
864 from lp.registry.model.productlicense import ProductLicense
865 from lp.services.database.lpstorm import IStore
866-from lp.services.features.testing import FeatureFixture
867 from lp.services.webapp.authorization import check_permission
868 from lp.services.webapp.escaping import html_escape
869 from lp.testing import (
870@@ -1196,28 +1195,6 @@
871 product.userCanView(user)
872 product.userCanView(IPersonRoles(user))
873
874- def test_userCanView_override(self):
875- # userCanView is overridden by the traversal override.
876- product = self.factory.makeProduct(
877- information_type=InformationType.PROPRIETARY)
878- unprivileged = self.factory.makePerson()
879- with person_logged_in(unprivileged):
880- with FeatureFixture(
881- {'disclosure.private_project.traversal_override': 'on'}):
882- self.assertTrue(product.userCanView(unprivileged))
883- self.assertFalse(product.userCanView(unprivileged))
884-
885- def test_anonymous_traversal_override(self):
886- # The traversal override affects the permissions granted to anonymous
887- # users.
888- product = self.factory.makeProduct(
889- information_type=InformationType.PROPRIETARY)
890- with person_logged_in(None):
891- with FeatureFixture(
892- {'disclosure.private_project.traversal_override': 'on'}):
893- self.assertTrue(check_permission('launchpad.View', product))
894- self.assertFalse(check_permission('launchpad.View', product))
895-
896 def test_information_type_prevents_pruning(self):
897 # Access policies for Product.information_type are not pruned.
898 owner = self.factory.makePerson()
899
900=== modified file 'lib/lp/services/features/flags.py'
901--- lib/lp/services/features/flags.py 2012-11-19 05:54:50 +0000
902+++ lib/lp/services/features/flags.py 2013-02-07 06:17:24 +0000
903@@ -1,4 +1,4 @@
904-# Copyright 2010-2012 Canonical Ltd. This software is licensed under the
905+# Copyright 2010-2013 Canonical Ltd. This software is licensed under the
906 # GNU Affero General Public License version 3 (see the file LICENSE).
907
908 __all__ = [
909@@ -57,12 +57,6 @@
910 '',
911 '',
912 ''),
913- ('blueprints.information_type.enabled',
914- 'boolean',
915- 'Enable UI for information_type on Blueprints.',
916- 'Disable UI',
917- 'Blueprint information_type UI',
918- 'https://dev.launchpad.net/LEP/PrivateProjects'),
919 ('bugs.affected_count_includes_dupes.disabled',
920 'boolean',
921 ("Disable adding up affected users across all duplicate bugs."),
922@@ -226,18 +220,6 @@
923 '',
924 '',
925 ''),
926- ('disclosure.private_projects.enabled',
927- 'boolean',
928- 'If true, enabled access to private project registration features.',
929- 'disabled',
930- 'Allow registering a non-public project.',
931- 'http://blog.launchpad.net/general/private-projects-beta'),
932- ('disclosure.private_project.traversal_override',
933- 'boolean',
934- 'If set, allow all users to traverse to private projects.',
935- 'Traversal to private projects requires special access.',
936- 'Override traveral checks.',
937- 'https://dev.launchpad.net/LEP/PrivateProjects'),
938 ])
939
940 # The set of all flag names that are documented.