Merge lp:~wgrant/launchpad/edit-stacked-information-type into lp:launchpad

Proposed by William Grant
Status: Merged
Approved by: Ian Booth
Approved revision: no longer in the source branch.
Merged at revision: 15621
Proposed branch: lp:~wgrant/launchpad/edit-stacked-information-type
Merge into: lp:launchpad
Diff against target: 156 lines (+46/-59)
2 files modified
lib/lp/code/browser/branch.py (+28/-55)
lib/lp/code/browser/tests/test_branch.py (+18/-4)
To merge this branch: bzr merge lp:~wgrant/launchpad/edit-stacked-information-type
Reviewer Review Type Date Requested Status
Ian Booth (community) Approve
Review via email: mp+114767@code.launchpad.net

Commit message

Stop special-casing private stacked-on branches so much on Branch:+edit.

Description of the change

This branch simplifies BranchEditView's handling of the information type of branches stacked on private branches. Previously it replaced the usual radio buttons with a disabled checkbox, and some text describing why it's locked. I've integrated this into the normal information type widget, so if the stacked-on branch is private it'll display only (branch.stacked_on.information_type, branch.information_type), allowing the user to make it consistent by switching to the matching type.

There's no replacement for the warning text describing why the choices are restricted, but the case is uncommon enough that we probably don't care. It's already restricted by branch visibility policies without a corresponding warning.

To post a comment you must log in.
Revision history for this message
Ian Booth (wallyworld) wrote :

Looks great.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/code/browser/branch.py'
2--- lib/lp/code/browser/branch.py 2012-07-12 21:56:46 +0000
3+++ lib/lp/code/browser/branch.py 2012-07-13 01:31:19 +0000
4@@ -48,9 +48,7 @@
5 from lazr.uri import URI
6 import pytz
7 import simplejson
8-from zope.app.form import CustomWidgetFactory
9 from zope.app.form.browser import TextAreaWidget
10-from zope.app.form.browser.boolwidgets import CheckBoxWidget
11 from zope.component import (
12 getUtility,
13 queryAdapter,
14@@ -124,11 +122,7 @@
15 from lp.code.interfaces.branchcollection import IAllBranches
16 from lp.code.interfaces.branchmergeproposal import IBranchMergeProposal
17 from lp.code.interfaces.codereviewvote import ICodeReviewVoteReference
18-from lp.registry.enums import (
19- InformationType,
20- PRIVATE_INFORMATION_TYPES,
21- PUBLIC_INFORMATION_TYPES,
22- )
23+from lp.registry.enums import InformationType
24 from lp.registry.interfaces.person import IPersonSet
25 from lp.registry.interfaces.productseries import IProductSeries
26 from lp.registry.vocabularies import (
27@@ -1033,34 +1027,7 @@
28
29 def setUpFields(self):
30 super(BranchEditView, self).setUpFields()
31- # This is to prevent users from converting push/import
32- # branches to pull branches.
33 branch = self.context
34- if branch.private:
35- # If this branch is stacked on a private branch, render some text
36- # to inform the user the information type cannot be changed.
37- if (branch.stacked_on and branch.stacked_on.information_type in
38- PRIVATE_INFORMATION_TYPES):
39- stacked_info_type = branch.stacked_on.information_type.title
40- private_info = Bool(
41- __name__="private",
42- title=_("Branch is %s" % stacked_info_type),
43- description=_(
44- "This branch is %(info_type)s because it is "
45- "stacked on a %(info_type)s branch." % {
46- 'info_type': stacked_info_type}))
47- private_info_field = form.Fields(
48- private_info, render_context=self.render_context)
49- self.form_fields = (private_info_field
50- + self.form_fields.omit('information_type'))
51- new_field_names = self.field_names
52- index = new_field_names.index('information_type')
53- new_field_names[index] = 'private'
54- self.form_fields = self.form_fields.select(*new_field_names)
55- self.form_fields['private'].custom_widget = (
56- CustomWidgetFactory(
57- CheckBoxWidget, extra='disabled="disabled"'))
58-
59 # If the user can administer branches, then they should be able to
60 # assign the ownership of the branch to any valid person or team.
61 if check_permission('launchpad.Admin', branch):
62@@ -1109,27 +1076,33 @@
63 bug with an obscure type.
64 """
65 allowed_types = self.context.getAllowedInformationTypes(self.user)
66- shown_types = (
67- InformationType.PUBLIC,
68- InformationType.USERDATA,
69- InformationType.PROPRIETARY,
70- )
71-
72- # We only show Embargoed Security and Unembargoed Security
73- # if the branch is linked to a bug with one of those types,
74- # as they're confusing and not generally useful otherwise.
75- # Once Proprietary is fully deployed, User Data should be
76- # added here.
77- hidden_types = (
78- InformationType.UNEMBARGOEDSECURITY,
79- InformationType.EMBARGOEDSECURITY,
80- )
81- if set(allowed_types).intersection(hidden_types):
82- params = BugTaskSearchParams(
83- user=self.user, linked_branches=self.context.id,
84- information_type=hidden_types)
85- if getUtility(IBugTaskSet).searchBugIds(params).count() > 0:
86- shown_types += hidden_types
87+
88+ # If we're stacked on a private branch, only show that
89+ # information type.
90+ if self.context.stacked_on and self.context.stacked_on.private:
91+ shown_types = set([self.context.stacked_on.information_type])
92+ else:
93+ shown_types = (
94+ InformationType.PUBLIC,
95+ InformationType.USERDATA,
96+ InformationType.PROPRIETARY,
97+ )
98+
99+ # We only show Embargoed Security and Unembargoed Security
100+ # if the branch is linked to a bug with one of those types,
101+ # as they're confusing and not generally useful otherwise.
102+ # Once Proprietary is fully deployed, User Data should be
103+ # added here.
104+ hidden_types = (
105+ InformationType.UNEMBARGOEDSECURITY,
106+ InformationType.EMBARGOEDSECURITY,
107+ )
108+ if set(allowed_types).intersection(hidden_types):
109+ params = BugTaskSearchParams(
110+ user=self.user, linked_branches=self.context.id,
111+ information_type=hidden_types)
112+ if getUtility(IBugTaskSet).searchBugIds(params).count() > 0:
113+ shown_types += hidden_types
114
115 # Now take the intersection of the allowed and shown types.
116 combined_types = set(allowed_types).intersection(shown_types)
117
118=== modified file 'lib/lp/code/browser/tests/test_branch.py'
119--- lib/lp/code/browser/tests/test_branch.py 2012-07-12 09:13:16 +0000
120+++ lib/lp/code/browser/tests/test_branch.py 2012-07-13 01:31:19 +0000
121@@ -36,10 +36,7 @@
122 BranchVisibilityRule,
123 )
124 from lp.registry.enums import InformationType
125-from lp.registry.interfaces.person import (
126- PersonVisibility,
127- TeamSubscriptionPolicy,
128- )
129+from lp.registry.interfaces.person import PersonVisibility
130 from lp.services.config import config
131 from lp.services.database.constants import UTC_NOW
132 from lp.services.features.testing import FeatureFixture
133@@ -985,6 +982,23 @@
134 self.assertShownTypes(
135 [InformationType.PUBLIC, InformationType.PROPRIETARY], branch)
136
137+ def test_stacked_on_private(self):
138+ # A branch stacked on a private branch has its choices limited
139+ # to the current type and the stacked-on type.
140+ product = self.factory.makeProduct()
141+ stacked_on_branch = self.factory.makeBranch(
142+ product=product, information_type=InformationType.USERDATA)
143+ branch = self.factory.makeBranch(
144+ product=product, stacked_on=stacked_on_branch,
145+ owner=product.owner,
146+ information_type=InformationType.EMBARGOEDSECURITY)
147+ with admin_logged_in():
148+ branch.product.setBranchVisibilityTeamPolicy(
149+ branch.owner, BranchVisibilityRule.PRIVATE)
150+ self.assertShownTypes(
151+ [InformationType.EMBARGOEDSECURITY, InformationType.USERDATA],
152+ branch)
153+
154 def test_private_branch(self):
155 # Branches on projects with a private policy can be set to
156 # User Data (aka. Private)