Merge lp:~wgrant/launchpad/bug-sharing-policy into lp:launchpad
- bug-sharing-policy
- Merge into devel
Proposed by
William Grant
Status: | Merged |
---|---|
Approved by: | Curtis Hovey |
Approved revision: | no longer in the source branch. |
Merged at revision: | 15833 |
Proposed branch: | lp:~wgrant/launchpad/bug-sharing-policy |
Merge into: | lp:launchpad |
Diff against target: |
564 lines (+235/-28) 10 files modified
lib/lp/bugs/browser/tests/test_bugs.py (+28/-1) lib/lp/bugs/browser/tests/test_bugtarget_filebug.py (+47/-3) lib/lp/bugs/interfaces/bugtarget.py (+23/-0) lib/lp/bugs/mail/tests/test_handler.py (+24/-1) lib/lp/bugs/tests/test_bugs_webservice.py (+25/-2) lib/lp/code/model/branchnamespace.py (+2/-5) lib/lp/code/model/tests/test_branchnamespace.py (+2/-2) lib/lp/registry/enums.py (+8/-1) lib/lp/registry/model/product.py (+10/-1) lib/lp/registry/tests/test_product.py (+66/-12) |
To merge this branch: | bzr merge lp:~wgrant/launchpad/bug-sharing-policy |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Curtis Hovey (community) | code | Approve | |
Review via email: mp+120385@code.launchpad.net |
Commit message
Product.
Description of the change
This branch adjusts Product.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/lp/bugs/browser/tests/test_bugs.py' | |||
2 | --- lib/lp/bugs/browser/tests/test_bugs.py 2012-08-08 11:48:29 +0000 | |||
3 | +++ lib/lp/bugs/browser/tests/test_bugs.py 2012-08-20 13:34:33 +0000 | |||
4 | @@ -12,7 +12,11 @@ | |||
5 | 12 | from lp.bugs.interfaces.bugtask import BugTaskStatus | 12 | from lp.bugs.interfaces.bugtask import BugTaskStatus |
6 | 13 | from lp.bugs.interfaces.malone import IMaloneApplication | 13 | from lp.bugs.interfaces.malone import IMaloneApplication |
7 | 14 | from lp.bugs.publisher import BugsLayer | 14 | from lp.bugs.publisher import BugsLayer |
9 | 15 | from lp.registry.enums import InformationType | 15 | from lp.registry.enums import ( |
10 | 16 | BugSharingPolicy, | ||
11 | 17 | InformationType, | ||
12 | 18 | ) | ||
13 | 19 | from lp.registry.interfaces.person import IPersonSet | ||
14 | 16 | from lp.registry.interfaces.product import License | 20 | from lp.registry.interfaces.product import License |
15 | 17 | from lp.services.webapp.publisher import canonical_url | 21 | from lp.services.webapp.publisher import canonical_url |
16 | 18 | from lp.testing import ( | 22 | from lp.testing import ( |
17 | @@ -24,6 +28,7 @@ | |||
18 | 24 | ) | 28 | ) |
19 | 25 | from lp.testing.layers import DatabaseFunctionalLayer | 29 | from lp.testing.layers import DatabaseFunctionalLayer |
20 | 26 | from lp.testing.pages import find_tag_by_id | 30 | from lp.testing.pages import find_tag_by_id |
21 | 31 | from lp.testing.sampledata import COMMERCIAL_ADMIN_EMAIL | ||
22 | 27 | from lp.testing.views import create_initialized_view | 32 | from lp.testing.views import create_initialized_view |
23 | 28 | 33 | ||
24 | 29 | 34 | ||
25 | @@ -175,6 +180,28 @@ | |||
26 | 175 | project.owner, 'title', 'description', project, private=False) | 180 | project.owner, 'title', 'description', project, private=False) |
27 | 176 | self.assertEqual(InformationType.PUBLIC, bug.information_type) | 181 | self.assertEqual(InformationType.PUBLIC, bug.information_type) |
28 | 177 | 182 | ||
29 | 183 | def test_createBug_default_sharing_policy_proprietary(self): | ||
30 | 184 | # createBug() does not adapt the default kwargs when they are none. | ||
31 | 185 | project = self.factory.makeProduct( | ||
32 | 186 | licenses=[License.OTHER_PROPRIETARY]) | ||
33 | 187 | comadmin = getUtility(IPersonSet).getByEmail(COMMERCIAL_ADMIN_EMAIL) | ||
34 | 188 | project.setBugSharingPolicy( | ||
35 | 189 | BugSharingPolicy.PROPRIETARY_OR_PUBLIC, comadmin) | ||
36 | 190 | bug = self.application.createBug( | ||
37 | 191 | project.owner, 'title', 'description', project) | ||
38 | 192 | self.assertEqual(InformationType.PROPRIETARY, bug.information_type) | ||
39 | 193 | |||
40 | 194 | def test_createBug_public_bug_sharing_policy_proprietary(self): | ||
41 | 195 | # createBug() adapts a kwarg to InformationType if one is is not None. | ||
42 | 196 | project = self.factory.makeProduct( | ||
43 | 197 | licenses=[License.OTHER_PROPRIETARY]) | ||
44 | 198 | comadmin = getUtility(IPersonSet).getByEmail(COMMERCIAL_ADMIN_EMAIL) | ||
45 | 199 | project.setBugSharingPolicy( | ||
46 | 200 | BugSharingPolicy.PROPRIETARY_OR_PUBLIC, comadmin) | ||
47 | 201 | bug = self.application.createBug( | ||
48 | 202 | project.owner, 'title', 'description', project, private=False) | ||
49 | 203 | self.assertEqual(InformationType.PUBLIC, bug.information_type) | ||
50 | 204 | |||
51 | 178 | def test_createBug_default_private_bugs_false(self): | 205 | def test_createBug_default_private_bugs_false(self): |
52 | 179 | # createBug() does not adapt the default kwargs when they are none. | 206 | # createBug() does not adapt the default kwargs when they are none. |
53 | 180 | project = self.factory.makeProduct( | 207 | project = self.factory.makeProduct( |
54 | 181 | 208 | ||
55 | === modified file 'lib/lp/bugs/browser/tests/test_bugtarget_filebug.py' | |||
56 | --- lib/lp/bugs/browser/tests/test_bugtarget_filebug.py 2012-08-14 01:57:17 +0000 | |||
57 | +++ lib/lp/bugs/browser/tests/test_bugtarget_filebug.py 2012-08-20 13:34:33 +0000 | |||
58 | @@ -25,9 +25,11 @@ | |||
59 | 25 | ) | 25 | ) |
60 | 26 | from lp.bugs.publisher import BugsLayer | 26 | from lp.bugs.publisher import BugsLayer |
61 | 27 | from lp.registry.enums import ( | 27 | from lp.registry.enums import ( |
62 | 28 | BugSharingPolicy, | ||
63 | 28 | InformationType, | 29 | InformationType, |
64 | 29 | PRIVATE_INFORMATION_TYPES, | 30 | PRIVATE_INFORMATION_TYPES, |
65 | 30 | ) | 31 | ) |
66 | 32 | from lp.registry.interfaces.person import IPersonSet | ||
67 | 31 | from lp.registry.interfaces.projectgroup import IProjectGroup | 33 | from lp.registry.interfaces.projectgroup import IProjectGroup |
68 | 32 | from lp.services.webapp.servers import LaunchpadTestRequest | 34 | from lp.services.webapp.servers import LaunchpadTestRequest |
69 | 33 | from lp.testing import ( | 35 | from lp.testing import ( |
70 | @@ -41,6 +43,7 @@ | |||
71 | 41 | find_main_content, | 43 | find_main_content, |
72 | 42 | find_tag_by_id, | 44 | find_tag_by_id, |
73 | 43 | ) | 45 | ) |
74 | 46 | from lp.testing.sampledata import COMMERCIAL_ADMIN_EMAIL | ||
75 | 44 | from lp.testing.views import ( | 47 | from lp.testing.views import ( |
76 | 45 | create_initialized_view, | 48 | create_initialized_view, |
77 | 46 | create_view, | 49 | create_view, |
78 | @@ -353,7 +356,7 @@ | |||
79 | 353 | self.assertEqual(expected_guidelines, view.bug_reporting_guidelines) | 356 | self.assertEqual(expected_guidelines, view.bug_reporting_guidelines) |
80 | 354 | 357 | ||
81 | 355 | def filebug_via_view(self, private_bugs=False, information_type=None, | 358 | def filebug_via_view(self, private_bugs=False, information_type=None, |
83 | 356 | extra_data_token=None): | 359 | bug_sharing_policy=None, extra_data_token=None): |
84 | 357 | form = { | 360 | form = { |
85 | 358 | 'field.title': 'A bug', | 361 | 'field.title': 'A bug', |
86 | 359 | 'field.comment': 'A comment', | 362 | 'field.comment': 'A comment', |
87 | @@ -364,6 +367,11 @@ | |||
88 | 364 | product = self.factory.makeProduct(official_malone=True) | 367 | product = self.factory.makeProduct(official_malone=True) |
89 | 365 | if private_bugs: | 368 | if private_bugs: |
90 | 366 | removeSecurityProxy(product).private_bugs = True | 369 | removeSecurityProxy(product).private_bugs = True |
91 | 370 | if bug_sharing_policy: | ||
92 | 371 | self.factory.makeCommercialSubscription(product=product) | ||
93 | 372 | comadmin = getUtility(IPersonSet).getByEmail( | ||
94 | 373 | COMMERCIAL_ADMIN_EMAIL) | ||
95 | 374 | product.setBugSharingPolicy(bug_sharing_policy, comadmin) | ||
96 | 367 | with person_logged_in(product.owner): | 375 | with person_logged_in(product.owner): |
97 | 368 | view = create_view( | 376 | view = create_view( |
98 | 369 | product, '+filebug', method='POST', form=form, | 377 | product, '+filebug', method='POST', form=form, |
99 | @@ -397,6 +405,15 @@ | |||
100 | 397 | InformationType.USERDATA, view.default_information_type) | 405 | InformationType.USERDATA, view.default_information_type) |
101 | 398 | self.assertEqual(InformationType.USERDATA, bug.information_type) | 406 | self.assertEqual(InformationType.USERDATA, bug.information_type) |
102 | 399 | 407 | ||
103 | 408 | def test_filebug_information_type_with_bug_sharing_policy(self): | ||
104 | 409 | # If we don't specify the bug's information_type, it follows the | ||
105 | 410 | # target's getDefaultBugInformationType(). | ||
106 | 411 | bug, view = self.filebug_via_view( | ||
107 | 412 | bug_sharing_policy=BugSharingPolicy.PROPRIETARY) | ||
108 | 413 | self.assertEqual( | ||
109 | 414 | InformationType.PROPRIETARY, view.default_information_type) | ||
110 | 415 | self.assertEqual(InformationType.PROPRIETARY, bug.information_type) | ||
111 | 416 | |||
112 | 400 | def test_filebug_information_type_with_public_blob(self): | 417 | def test_filebug_information_type_with_public_blob(self): |
113 | 401 | # Bugs filed with an apport blob that doesn't request privacy | 418 | # Bugs filed with an apport blob that doesn't request privacy |
114 | 402 | # are public by default. | 419 | # are public by default. |
115 | @@ -414,7 +431,7 @@ | |||
116 | 414 | InformationType.USERDATA, view.default_information_type) | 431 | InformationType.USERDATA, view.default_information_type) |
117 | 415 | self.assertEqual(InformationType.USERDATA, bug.information_type) | 432 | self.assertEqual(InformationType.USERDATA, bug.information_type) |
118 | 416 | 433 | ||
120 | 417 | def test_filebug_information_type_normal_projects(self): | 434 | def test_filebug_information_type_public_policy(self): |
121 | 418 | # The vocabulary for information_type when filing a bug is created | 435 | # The vocabulary for information_type when filing a bug is created |
122 | 419 | # correctly for non commercial projects. | 436 | # correctly for non commercial projects. |
123 | 420 | product = self.factory.makeProduct(official_malone=True) | 437 | product = self.factory.makeProduct(official_malone=True) |
124 | @@ -425,6 +442,20 @@ | |||
125 | 425 | soup = BeautifulSoup(html) | 442 | soup = BeautifulSoup(html) |
126 | 426 | self.assertIsNone(soup.find('label', text="Proprietary")) | 443 | self.assertIsNone(soup.find('label', text="Proprietary")) |
127 | 427 | 444 | ||
128 | 445 | def test_filebug_information_type_proprietary_policy(self): | ||
129 | 446 | # The vocabulary for information_type when filing a bug is created | ||
130 | 447 | # correctly for a project with a proprietary sharing policy. | ||
131 | 448 | product = self.factory.makeProduct(official_malone=True) | ||
132 | 449 | self.factory.makeCommercialSubscription(product=product) | ||
133 | 450 | comadmin = getUtility(IPersonSet).getByEmail(COMMERCIAL_ADMIN_EMAIL) | ||
134 | 451 | product.setBugSharingPolicy(BugSharingPolicy.PROPRIETARY, comadmin) | ||
135 | 452 | with person_logged_in(product.owner): | ||
136 | 453 | view = create_initialized_view( | ||
137 | 454 | product, '+filebug', principal=product.owner) | ||
138 | 455 | html = view.render() | ||
139 | 456 | soup = BeautifulSoup(html) | ||
140 | 457 | self.assertIsNotNone(soup.find('label', text="Proprietary")) | ||
141 | 458 | |||
142 | 428 | def test_filebug_information_type_vocabulary(self): | 459 | def test_filebug_information_type_vocabulary(self): |
143 | 429 | # The vocabulary for information_type when filing a bug is created | 460 | # The vocabulary for information_type when filing a bug is created |
144 | 430 | # correctly. | 461 | # correctly. |
145 | @@ -455,7 +486,8 @@ | |||
146 | 455 | 486 | ||
147 | 456 | layer = DatabaseFunctionalLayer | 487 | layer = DatabaseFunctionalLayer |
148 | 457 | 488 | ||
150 | 458 | def filebug_via_view(self, private_bugs=False, security_related=False): | 489 | def filebug_via_view(self, private_bugs=False, bug_sharing_policy=None, |
151 | 490 | security_related=False): | ||
152 | 459 | form = { | 491 | form = { |
153 | 460 | 'field.title': 'A bug', | 492 | 'field.title': 'A bug', |
154 | 461 | 'field.comment': 'A comment', | 493 | 'field.comment': 'A comment', |
155 | @@ -465,6 +497,11 @@ | |||
156 | 465 | product = self.factory.makeProduct(official_malone=True) | 497 | product = self.factory.makeProduct(official_malone=True) |
157 | 466 | if private_bugs: | 498 | if private_bugs: |
158 | 467 | removeSecurityProxy(product).private_bugs = True | 499 | removeSecurityProxy(product).private_bugs = True |
159 | 500 | if bug_sharing_policy: | ||
160 | 501 | self.factory.makeCommercialSubscription(product=product) | ||
161 | 502 | comadmin = getUtility(IPersonSet).getByEmail( | ||
162 | 503 | COMMERCIAL_ADMIN_EMAIL) | ||
163 | 504 | product.setBugSharingPolicy(bug_sharing_policy, comadmin) | ||
164 | 468 | anyone = self.factory.makePerson() | 505 | anyone = self.factory.makePerson() |
165 | 469 | with person_logged_in(anyone): | 506 | with person_logged_in(anyone): |
166 | 470 | view = create_initialized_view( | 507 | view = create_initialized_view( |
167 | @@ -499,6 +536,13 @@ | |||
168 | 499 | bug = self.filebug_via_view(private_bugs=True) | 536 | bug = self.filebug_via_view(private_bugs=True) |
169 | 500 | self.assertEqual(InformationType.USERDATA, bug.information_type) | 537 | self.assertEqual(InformationType.USERDATA, bug.information_type) |
170 | 501 | 538 | ||
171 | 539 | def test_filebug_with_proprietary_sharing(self): | ||
172 | 540 | # Non security related bugs are PROPRIETARY for products with a | ||
173 | 541 | # proprietary sharing policy. | ||
174 | 542 | bug = self.filebug_via_view( | ||
175 | 543 | bug_sharing_policy=BugSharingPolicy.PROPRIETARY) | ||
176 | 544 | self.assertEqual(InformationType.PROPRIETARY, bug.information_type) | ||
177 | 545 | |||
178 | 502 | def test_filebug_view_renders_security_related(self): | 546 | def test_filebug_view_renders_security_related(self): |
179 | 503 | # The security_related checkbox is rendered for non bug supervisors. | 547 | # The security_related checkbox is rendered for non bug supervisors. |
180 | 504 | product = self.factory.makeProduct(official_malone=True) | 548 | product = self.factory.makeProduct(official_malone=True) |
181 | 505 | 549 | ||
182 | === modified file 'lib/lp/bugs/interfaces/bugtarget.py' | |||
183 | --- lib/lp/bugs/interfaces/bugtarget.py 2012-08-08 03:45:16 +0000 | |||
184 | +++ lib/lp/bugs/interfaces/bugtarget.py 2012-08-20 13:34:33 +0000 | |||
185 | @@ -18,6 +18,8 @@ | |||
186 | 18 | 'IOfficialBugTagTargetPublic', | 18 | 'IOfficialBugTagTargetPublic', |
187 | 19 | 'IOfficialBugTagTargetRestricted', | 19 | 'IOfficialBugTagTargetRestricted', |
188 | 20 | 'ISeriesBugTarget', | 20 | 'ISeriesBugTarget', |
189 | 21 | 'POLICY_ALLOWED_TYPES', | ||
190 | 22 | 'POLICY_DEFAULT_TYPES', | ||
191 | 21 | ] | 23 | ] |
192 | 22 | 24 | ||
193 | 23 | 25 | ||
194 | @@ -59,6 +61,12 @@ | |||
195 | 59 | BugTagsSearchCombinator, | 61 | BugTagsSearchCombinator, |
196 | 60 | IBugTaskSearch, | 62 | IBugTaskSearch, |
197 | 61 | ) | 63 | ) |
198 | 64 | from lp.registry.enums import ( | ||
199 | 65 | BugSharingPolicy, | ||
200 | 66 | FREE_INFORMATION_TYPES, | ||
201 | 67 | InformationType, | ||
202 | 68 | NON_EMBARGOED_INFORMATION_TYPES, | ||
203 | 69 | ) | ||
204 | 62 | from lp.services.fields import Tag | 70 | from lp.services.fields import Tag |
205 | 63 | 71 | ||
206 | 64 | 72 | ||
207 | @@ -197,6 +205,21 @@ | |||
208 | 197 | vocabulary=BugBlueprintSearch, required=False)) | 205 | vocabulary=BugBlueprintSearch, required=False)) |
209 | 198 | 206 | ||
210 | 199 | 207 | ||
211 | 208 | POLICY_ALLOWED_TYPES = { | ||
212 | 209 | BugSharingPolicy.PUBLIC: FREE_INFORMATION_TYPES, | ||
213 | 210 | BugSharingPolicy.PUBLIC_OR_PROPRIETARY: NON_EMBARGOED_INFORMATION_TYPES, | ||
214 | 211 | BugSharingPolicy.PROPRIETARY_OR_PUBLIC: NON_EMBARGOED_INFORMATION_TYPES, | ||
215 | 212 | BugSharingPolicy.PROPRIETARY: (InformationType.PROPRIETARY,), | ||
216 | 213 | } | ||
217 | 214 | |||
218 | 215 | POLICY_DEFAULT_TYPES = { | ||
219 | 216 | BugSharingPolicy.PUBLIC: InformationType.PUBLIC, | ||
220 | 217 | BugSharingPolicy.PUBLIC_OR_PROPRIETARY: InformationType.PUBLIC, | ||
221 | 218 | BugSharingPolicy.PROPRIETARY_OR_PUBLIC: InformationType.PROPRIETARY, | ||
222 | 219 | BugSharingPolicy.PROPRIETARY: InformationType.PROPRIETARY, | ||
223 | 220 | } | ||
224 | 221 | |||
225 | 222 | |||
226 | 200 | class IHasBugs(Interface): | 223 | class IHasBugs(Interface): |
227 | 201 | """An entity which has a collection of bug tasks.""" | 224 | """An entity which has a collection of bug tasks.""" |
228 | 202 | 225 | ||
229 | 203 | 226 | ||
230 | === modified file 'lib/lp/bugs/mail/tests/test_handler.py' | |||
231 | --- lib/lp/bugs/mail/tests/test_handler.py 2012-05-04 00:03:07 +0000 | |||
232 | +++ lib/lp/bugs/mail/tests/test_handler.py 2012-08-20 13:34:33 +0000 | |||
233 | @@ -28,7 +28,11 @@ | |||
234 | 28 | MaloneHandler, | 28 | MaloneHandler, |
235 | 29 | ) | 29 | ) |
236 | 30 | from lp.bugs.model.bugnotification import BugNotification | 30 | from lp.bugs.model.bugnotification import BugNotification |
238 | 31 | from lp.registry.enums import InformationType | 31 | from lp.registry.enums import ( |
239 | 32 | BugSharingPolicy, | ||
240 | 33 | InformationType, | ||
241 | 34 | ) | ||
242 | 35 | from lp.registry.interfaces.person import IPersonSet | ||
243 | 32 | from lp.services.config import config | 36 | from lp.services.config import config |
244 | 33 | from lp.services.identity.interfaces.emailaddress import EmailAddressStatus | 37 | from lp.services.identity.interfaces.emailaddress import EmailAddressStatus |
245 | 34 | from lp.services.mail import stub | 38 | from lp.services.mail import stub |
246 | @@ -48,6 +52,7 @@ | |||
247 | 48 | LaunchpadZopelessLayer, | 52 | LaunchpadZopelessLayer, |
248 | 49 | ) | 53 | ) |
249 | 50 | from lp.testing.mail_helpers import pop_notifications | 54 | from lp.testing.mail_helpers import pop_notifications |
250 | 55 | from lp.testing.sampledata import COMMERCIAL_ADMIN_EMAIL | ||
251 | 51 | 56 | ||
252 | 52 | 57 | ||
253 | 53 | class TestMaloneHandler(TestCaseWithFactory): | 58 | class TestMaloneHandler(TestCaseWithFactory): |
254 | @@ -253,6 +258,24 @@ | |||
255 | 253 | self.assertEqual(1, len(bug.bugtasks)) | 258 | self.assertEqual(1, len(bug.bugtasks)) |
256 | 254 | self.assertEqual(project, bug.bugtasks[0].target) | 259 | self.assertEqual(project, bug.bugtasks[0].target) |
257 | 255 | 260 | ||
258 | 261 | def test_new_bug_with_sharing_policy_proprietary(self): | ||
259 | 262 | project = self.factory.makeProduct(name='fnord') | ||
260 | 263 | self.factory.makeCommercialSubscription(product=project) | ||
261 | 264 | comadmin = getUtility(IPersonSet).getByEmail(COMMERCIAL_ADMIN_EMAIL) | ||
262 | 265 | project.setBugSharingPolicy(BugSharingPolicy.PROPRIETARY, comadmin) | ||
263 | 266 | transaction.commit() | ||
264 | 267 | handler = MaloneHandler() | ||
265 | 268 | with person_logged_in(project.owner): | ||
266 | 269 | msg = self.factory.makeSignedMessage( | ||
267 | 270 | body='borked\n affects fnord', | ||
268 | 271 | subject='subject borked', | ||
269 | 272 | to_address='new@bugs.launchpad.dev') | ||
270 | 273 | handler.process(msg, msg['To']) | ||
271 | 274 | notification = self.getLatestBugNotification() | ||
272 | 275 | bug = notification.bug | ||
273 | 276 | self.assertEqual([project.owner], list(bug.getDirectSubscribers())) | ||
274 | 277 | self.assertEqual(InformationType.PROPRIETARY, bug.information_type) | ||
275 | 278 | |||
276 | 256 | def test_new_bug_with_one_misplaced_affects_line(self): | 279 | def test_new_bug_with_one_misplaced_affects_line(self): |
277 | 257 | # Affects commands in the wrong position are processed as the user | 280 | # Affects commands in the wrong position are processed as the user |
278 | 258 | # intended when the bug is new and there is only one affects. | 281 | # intended when the bug is new and there is only one affects. |
279 | 259 | 282 | ||
280 | === modified file 'lib/lp/bugs/tests/test_bugs_webservice.py' | |||
281 | --- lib/lp/bugs/tests/test_bugs_webservice.py 2012-08-08 07:22:51 +0000 | |||
282 | +++ lib/lp/bugs/tests/test_bugs_webservice.py 2012-08-20 13:34:33 +0000 | |||
283 | @@ -19,11 +19,18 @@ | |||
284 | 19 | Equals, | 19 | Equals, |
285 | 20 | LessThan, | 20 | LessThan, |
286 | 21 | ) | 21 | ) |
288 | 22 | from zope.component import getMultiAdapter | 22 | from zope.component import ( |
289 | 23 | getMultiAdapter, | ||
290 | 24 | getUtility, | ||
291 | 25 | ) | ||
292 | 23 | 26 | ||
293 | 24 | from lp.bugs.browser.bugtask import get_comments_for_bugtask | 27 | from lp.bugs.browser.bugtask import get_comments_for_bugtask |
294 | 25 | from lp.bugs.interfaces.bug import IBug | 28 | from lp.bugs.interfaces.bug import IBug |
296 | 26 | from lp.registry.enums import InformationType | 29 | from lp.registry.enums import ( |
297 | 30 | BugSharingPolicy, | ||
298 | 31 | InformationType, | ||
299 | 32 | ) | ||
300 | 33 | from lp.registry.interfaces.person import IPersonSet | ||
301 | 27 | from lp.registry.interfaces.product import License | 34 | from lp.registry.interfaces.product import License |
302 | 28 | from lp.services.webapp import snapshot | 35 | from lp.services.webapp import snapshot |
303 | 29 | from lp.services.webapp.servers import LaunchpadTestRequest | 36 | from lp.services.webapp.servers import LaunchpadTestRequest |
304 | @@ -45,6 +52,7 @@ | |||
305 | 45 | from lp.testing.pages import LaunchpadWebServiceCaller | 52 | from lp.testing.pages import LaunchpadWebServiceCaller |
306 | 46 | from lp.testing.sampledata import ( | 53 | from lp.testing.sampledata import ( |
307 | 47 | ADMIN_EMAIL, | 54 | ADMIN_EMAIL, |
308 | 55 | COMMERCIAL_ADMIN_EMAIL, | ||
309 | 48 | USER_EMAIL, | 56 | USER_EMAIL, |
310 | 49 | ) | 57 | ) |
311 | 50 | 58 | ||
312 | @@ -399,3 +407,18 @@ | |||
313 | 399 | target=api_url(project), title='title', description='desc', | 407 | target=api_url(project), title='title', description='desc', |
314 | 400 | private=True) | 408 | private=True) |
315 | 401 | self.assertEqual('Private', bug.information_type) | 409 | self.assertEqual('Private', bug.information_type) |
316 | 410 | |||
317 | 411 | def test_default_sharing_policy_proprietary(self): | ||
318 | 412 | # Verify the path through user submission, to MaloneApplication to | ||
319 | 413 | # BugSet, and back to the user creates a private bug according | ||
320 | 414 | # to the project's bug sharing policy. | ||
321 | 415 | project = self.factory.makeProduct( | ||
322 | 416 | licenses=[License.OTHER_PROPRIETARY]) | ||
323 | 417 | comadmin = getUtility(IPersonSet).getByEmail(COMMERCIAL_ADMIN_EMAIL) | ||
324 | 418 | project.setBugSharingPolicy( | ||
325 | 419 | BugSharingPolicy.PROPRIETARY_OR_PUBLIC, comadmin) | ||
326 | 420 | webservice = launchpadlib_for('test', 'salgado') | ||
327 | 421 | bugs_collection = webservice.load('/bugs') | ||
328 | 422 | bug = bugs_collection.createBug( | ||
329 | 423 | target=api_url(project), title='title', description='desc') | ||
330 | 424 | self.assertEqual('Proprietary', bug.information_type) | ||
331 | 402 | 425 | ||
332 | === modified file 'lib/lp/code/model/branchnamespace.py' | |||
333 | --- lib/lp/code/model/branchnamespace.py 2012-08-16 21:57:43 +0000 | |||
334 | +++ lib/lp/code/model/branchnamespace.py 2012-08-20 13:34:33 +0000 | |||
335 | @@ -47,6 +47,8 @@ | |||
336 | 47 | from lp.code.model.branch import Branch | 47 | from lp.code.model.branch import Branch |
337 | 48 | from lp.registry.enums import ( | 48 | from lp.registry.enums import ( |
338 | 49 | BranchSharingPolicy, | 49 | BranchSharingPolicy, |
339 | 50 | FREE_INFORMATION_TYPES, | ||
340 | 51 | FREE_PRIVATE_INFORMATION_TYPES, | ||
341 | 50 | InformationType, | 52 | InformationType, |
342 | 51 | PersonVisibility, | 53 | PersonVisibility, |
343 | 52 | NON_EMBARGOED_INFORMATION_TYPES, | 54 | NON_EMBARGOED_INFORMATION_TYPES, |
344 | @@ -82,11 +84,6 @@ | |||
345 | 82 | ) | 84 | ) |
346 | 83 | 85 | ||
347 | 84 | 86 | ||
348 | 85 | FREE_PRIVATE_INFORMATION_TYPES = ( | ||
349 | 86 | InformationType.PRIVATESECURITY, InformationType.USERDATA) | ||
350 | 87 | FREE_INFORMATION_TYPES = ( | ||
351 | 88 | PUBLIC_INFORMATION_TYPES + FREE_PRIVATE_INFORMATION_TYPES) | ||
352 | 89 | |||
353 | 90 | POLICY_ALLOWED_TYPES = { | 87 | POLICY_ALLOWED_TYPES = { |
354 | 91 | BranchSharingPolicy.PUBLIC: FREE_INFORMATION_TYPES, | 88 | BranchSharingPolicy.PUBLIC: FREE_INFORMATION_TYPES, |
355 | 92 | BranchSharingPolicy.PUBLIC_OR_PROPRIETARY: NON_EMBARGOED_INFORMATION_TYPES, | 89 | BranchSharingPolicy.PUBLIC_OR_PROPRIETARY: NON_EMBARGOED_INFORMATION_TYPES, |
356 | 93 | 90 | ||
357 | === modified file 'lib/lp/code/model/tests/test_branchnamespace.py' | |||
358 | --- lib/lp/code/model/tests/test_branchnamespace.py 2012-08-17 04:48:04 +0000 | |||
359 | +++ lib/lp/code/model/tests/test_branchnamespace.py 2012-08-20 13:34:33 +0000 | |||
360 | @@ -32,14 +32,14 @@ | |||
361 | 32 | ) | 32 | ) |
362 | 33 | from lp.code.interfaces.branchtarget import IBranchTarget | 33 | from lp.code.interfaces.branchtarget import IBranchTarget |
363 | 34 | from lp.code.model.branchnamespace import ( | 34 | from lp.code.model.branchnamespace import ( |
364 | 35 | FREE_INFORMATION_TYPES, | ||
365 | 36 | FREE_PRIVATE_INFORMATION_TYPES, | ||
366 | 37 | PackageNamespace, | 35 | PackageNamespace, |
367 | 38 | PersonalNamespace, | 36 | PersonalNamespace, |
368 | 39 | ProductNamespace, | 37 | ProductNamespace, |
369 | 40 | ) | 38 | ) |
370 | 41 | from lp.registry.enums import ( | 39 | from lp.registry.enums import ( |
371 | 42 | BranchSharingPolicy, | 40 | BranchSharingPolicy, |
372 | 41 | FREE_INFORMATION_TYPES, | ||
373 | 42 | FREE_PRIVATE_INFORMATION_TYPES, | ||
374 | 43 | InformationType, | 43 | InformationType, |
375 | 44 | NON_EMBARGOED_INFORMATION_TYPES, | 44 | NON_EMBARGOED_INFORMATION_TYPES, |
376 | 45 | PersonVisibility, | 45 | PersonVisibility, |
377 | 46 | 46 | ||
378 | === modified file 'lib/lp/registry/enums.py' | |||
379 | --- lib/lp/registry/enums.py 2012-08-16 21:57:43 +0000 | |||
380 | +++ lib/lp/registry/enums.py 2012-08-20 13:34:33 +0000 | |||
381 | @@ -10,6 +10,8 @@ | |||
382 | 10 | 'DistroSeriesDifferenceStatus', | 10 | 'DistroSeriesDifferenceStatus', |
383 | 11 | 'DistroSeriesDifferenceType', | 11 | 'DistroSeriesDifferenceType', |
384 | 12 | 'EXCLUSIVE_TEAM_POLICY', | 12 | 'EXCLUSIVE_TEAM_POLICY', |
385 | 13 | 'FREE_INFORMATION_TYPES', | ||
386 | 14 | 'FREE_PRIVATE_INFORMATION_TYPES', | ||
387 | 13 | 'INCLUSIVE_TEAM_POLICY', | 15 | 'INCLUSIVE_TEAM_POLICY', |
388 | 14 | 'InformationType', | 16 | 'InformationType', |
389 | 15 | 'NON_EMBARGOED_INFORMATION_TYPES', | 17 | 'NON_EMBARGOED_INFORMATION_TYPES', |
390 | @@ -77,7 +79,6 @@ | |||
391 | 77 | PUBLIC_INFORMATION_TYPES = ( | 79 | PUBLIC_INFORMATION_TYPES = ( |
392 | 78 | InformationType.PUBLIC, InformationType.PUBLICSECURITY) | 80 | InformationType.PUBLIC, InformationType.PUBLICSECURITY) |
393 | 79 | 81 | ||
394 | 80 | |||
395 | 81 | PRIVATE_INFORMATION_TYPES = ( | 82 | PRIVATE_INFORMATION_TYPES = ( |
396 | 82 | InformationType.PRIVATESECURITY, InformationType.USERDATA, | 83 | InformationType.PRIVATESECURITY, InformationType.USERDATA, |
397 | 83 | InformationType.PROPRIETARY, InformationType.EMBARGOED) | 84 | InformationType.PROPRIETARY, InformationType.EMBARGOED) |
398 | @@ -90,6 +91,12 @@ | |||
399 | 90 | SECURITY_INFORMATION_TYPES = ( | 91 | SECURITY_INFORMATION_TYPES = ( |
400 | 91 | InformationType.PUBLICSECURITY, InformationType.PRIVATESECURITY) | 92 | InformationType.PUBLICSECURITY, InformationType.PRIVATESECURITY) |
401 | 92 | 93 | ||
402 | 94 | FREE_PRIVATE_INFORMATION_TYPES = ( | ||
403 | 95 | InformationType.PRIVATESECURITY, InformationType.USERDATA) | ||
404 | 96 | |||
405 | 97 | FREE_INFORMATION_TYPES = ( | ||
406 | 98 | PUBLIC_INFORMATION_TYPES + FREE_PRIVATE_INFORMATION_TYPES) | ||
407 | 99 | |||
408 | 93 | 100 | ||
409 | 94 | class SharingPermission(DBEnumeratedType): | 101 | class SharingPermission(DBEnumeratedType): |
410 | 95 | """Sharing permission. | 102 | """Sharing permission. |
411 | 96 | 103 | ||
412 | === modified file 'lib/lp/registry/model/product.py' | |||
413 | --- lib/lp/registry/model/product.py 2012-08-17 05:05:37 +0000 | |||
414 | +++ lib/lp/registry/model/product.py 2012-08-20 13:34:33 +0000 | |||
415 | @@ -91,6 +91,10 @@ | |||
416 | 91 | from lp.blueprints.model.sprint import HasSprintsMixin | 91 | from lp.blueprints.model.sprint import HasSprintsMixin |
417 | 92 | from lp.bugs.interfaces.bugsummary import IBugSummaryDimension | 92 | from lp.bugs.interfaces.bugsummary import IBugSummaryDimension |
418 | 93 | from lp.bugs.interfaces.bugsupervisor import IHasBugSupervisor | 93 | from lp.bugs.interfaces.bugsupervisor import IHasBugSupervisor |
419 | 94 | from lp.bugs.interfaces.bugtarget import ( | ||
420 | 95 | POLICY_ALLOWED_TYPES, | ||
421 | 96 | POLICY_DEFAULT_TYPES, | ||
422 | 97 | ) | ||
423 | 94 | from lp.bugs.interfaces.bugtaskfilter import OrderedBugTask | 98 | from lp.bugs.interfaces.bugtaskfilter import OrderedBugTask |
424 | 95 | from lp.bugs.model.bugtarget import ( | 99 | from lp.bugs.model.bugtarget import ( |
425 | 96 | BugTargetBase, | 100 | BugTargetBase, |
426 | @@ -595,6 +599,9 @@ | |||
427 | 595 | 599 | ||
428 | 596 | def getAllowedBugInformationTypes(self): | 600 | def getAllowedBugInformationTypes(self): |
429 | 597 | """See `IProduct.`""" | 601 | """See `IProduct.`""" |
430 | 602 | if self.bug_sharing_policy is not None: | ||
431 | 603 | return POLICY_ALLOWED_TYPES[self.bug_sharing_policy] | ||
432 | 604 | |||
433 | 598 | types = set(InformationType.items) | 605 | types = set(InformationType.items) |
434 | 599 | types.discard(InformationType.PROPRIETARY) | 606 | types.discard(InformationType.PROPRIETARY) |
435 | 600 | types.discard(InformationType.EMBARGOED) | 607 | types.discard(InformationType.EMBARGOED) |
436 | @@ -602,7 +609,9 @@ | |||
437 | 602 | 609 | ||
438 | 603 | def getDefaultBugInformationType(self): | 610 | def getDefaultBugInformationType(self): |
439 | 604 | """See `IDistribution.`""" | 611 | """See `IDistribution.`""" |
441 | 605 | if self.private_bugs: | 612 | if self.bug_sharing_policy is not None: |
442 | 613 | return POLICY_DEFAULT_TYPES[self.bug_sharing_policy] | ||
443 | 614 | elif self.private_bugs: | ||
444 | 606 | return InformationType.USERDATA | 615 | return InformationType.USERDATA |
445 | 607 | else: | 616 | else: |
446 | 608 | return InformationType.PUBLIC | 617 | return InformationType.PUBLIC |
447 | 609 | 618 | ||
448 | === modified file 'lib/lp/registry/tests/test_product.py' | |||
449 | --- lib/lp/registry/tests/test_product.py 2012-08-17 05:05:37 +0000 | |||
450 | +++ lib/lp/registry/tests/test_product.py 2012-08-20 13:34:33 +0000 | |||
451 | @@ -32,6 +32,7 @@ | |||
452 | 32 | BranchSharingPolicy, | 32 | BranchSharingPolicy, |
453 | 33 | BugSharingPolicy, | 33 | BugSharingPolicy, |
454 | 34 | EXCLUSIVE_TEAM_POLICY, | 34 | EXCLUSIVE_TEAM_POLICY, |
455 | 35 | FREE_INFORMATION_TYPES, | ||
456 | 35 | INCLUSIVE_TEAM_POLICY, | 36 | INCLUSIVE_TEAM_POLICY, |
457 | 36 | InformationType, | 37 | InformationType, |
458 | 37 | ) | 38 | ) |
459 | @@ -44,6 +45,7 @@ | |||
460 | 44 | IAccessPolicySource, | 45 | IAccessPolicySource, |
461 | 45 | ) | 46 | ) |
462 | 46 | from lp.registry.interfaces.oopsreferences import IHasOOPSReferences | 47 | from lp.registry.interfaces.oopsreferences import IHasOOPSReferences |
463 | 48 | from lp.registry.interfaces.person import IPersonSet | ||
464 | 47 | from lp.registry.interfaces.product import ( | 49 | from lp.registry.interfaces.product import ( |
465 | 48 | IProduct, | 50 | IProduct, |
466 | 49 | IProductSet, | 51 | IProductSet, |
467 | @@ -79,6 +81,7 @@ | |||
468 | 79 | get_feedback_messages, | 81 | get_feedback_messages, |
469 | 80 | setupBrowser, | 82 | setupBrowser, |
470 | 81 | ) | 83 | ) |
471 | 84 | from lp.testing.sampledata import COMMERCIAL_ADMIN_EMAIL | ||
472 | 82 | from lp.translations.enums import TranslationPermission | 85 | from lp.translations.enums import TranslationPermission |
473 | 83 | from lp.translations.interfaces.customlanguagecode import ( | 86 | from lp.translations.interfaces.customlanguagecode import ( |
474 | 84 | IHasCustomLanguageCodes, | 87 | IHasCustomLanguageCodes, |
475 | @@ -377,26 +380,77 @@ | |||
476 | 377 | grantees = set([grant.grantee for grant in grants]) | 380 | grantees = set([grant.grantee for grant in grants]) |
477 | 378 | self.assertEqual(expected_grantess, grantees) | 381 | self.assertEqual(expected_grantess, grantees) |
478 | 379 | 382 | ||
482 | 380 | def test_getAllowedBugInformationTypes(self): | 383 | |
483 | 381 | # All projects currently support just the non-proprietary | 384 | class TestProductBugInformationTypes(TestCaseWithFactory): |
484 | 382 | # information types. | 385 | |
485 | 386 | layer = DatabaseFunctionalLayer | ||
486 | 387 | |||
487 | 388 | def makeProductWithPolicy(self, bug_sharing_policy, private_bugs=False): | ||
488 | 389 | product = self.factory.makeProduct(private_bugs=private_bugs) | ||
489 | 390 | self.factory.makeCommercialSubscription(product=product) | ||
490 | 391 | comadmin = getUtility(IPersonSet).getByEmail(COMMERCIAL_ADMIN_EMAIL) | ||
491 | 392 | product.setBugSharingPolicy(bug_sharing_policy, comadmin) | ||
492 | 393 | return product | ||
493 | 394 | |||
494 | 395 | def test_no_policy(self): | ||
495 | 396 | # New projects can only use the non-proprietary information | ||
496 | 397 | # types. | ||
497 | 398 | product = self.factory.makeProduct() | ||
498 | 383 | self.assertContentEqual( | 399 | self.assertContentEqual( |
506 | 384 | [InformationType.PUBLIC, InformationType.PUBLICSECURITY, | 400 | FREE_INFORMATION_TYPES, product.getAllowedBugInformationTypes()) |
500 | 385 | InformationType.PRIVATESECURITY, InformationType.USERDATA], | ||
501 | 386 | self.factory.makeProduct().getAllowedBugInformationTypes()) | ||
502 | 387 | |||
503 | 388 | def test_getDefaultBugInformationType_public(self): | ||
504 | 389 | # The default information type for normal projects is PUBLIC. | ||
505 | 390 | product = self.factory.makeProduct() | ||
507 | 391 | self.assertEqual( | 401 | self.assertEqual( |
508 | 392 | InformationType.PUBLIC, product.getDefaultBugInformationType()) | 402 | InformationType.PUBLIC, product.getDefaultBugInformationType()) |
509 | 393 | 403 | ||
512 | 394 | def test_getDefaultBugInformationType_private(self): | 404 | def test_legacy_private_bugs(self): |
513 | 395 | # private_bugs overrides the default information type to USERDATA. | 405 | # The deprecated private_bugs attribute overrides the default |
514 | 406 | # information type to USERDATA. | ||
515 | 396 | product = self.factory.makeProduct(private_bugs=True) | 407 | product = self.factory.makeProduct(private_bugs=True) |
516 | 408 | self.assertContentEqual( | ||
517 | 409 | FREE_INFORMATION_TYPES, product.getAllowedBugInformationTypes()) | ||
518 | 397 | self.assertEqual( | 410 | self.assertEqual( |
519 | 398 | InformationType.USERDATA, product.getDefaultBugInformationType()) | 411 | InformationType.USERDATA, product.getDefaultBugInformationType()) |
520 | 399 | 412 | ||
521 | 413 | def test_sharing_policy_overrides_private_bugs(self): | ||
522 | 414 | # bug_sharing_policy overrides private_bugs. | ||
523 | 415 | product = self.makeProductWithPolicy( | ||
524 | 416 | BugSharingPolicy.PUBLIC, private_bugs=True) | ||
525 | 417 | self.assertContentEqual( | ||
526 | 418 | FREE_INFORMATION_TYPES, product.getAllowedBugInformationTypes()) | ||
527 | 419 | self.assertEqual( | ||
528 | 420 | InformationType.PUBLIC, product.getDefaultBugInformationType()) | ||
529 | 421 | |||
530 | 422 | def test_sharing_policy_public_or_proprietary(self): | ||
531 | 423 | # bug_sharing_policy can enable Proprietary. | ||
532 | 424 | product = self.makeProductWithPolicy( | ||
533 | 425 | BugSharingPolicy.PUBLIC_OR_PROPRIETARY) | ||
534 | 426 | self.assertContentEqual( | ||
535 | 427 | FREE_INFORMATION_TYPES + (InformationType.PROPRIETARY,), | ||
536 | 428 | product.getAllowedBugInformationTypes()) | ||
537 | 429 | self.assertEqual( | ||
538 | 430 | InformationType.PUBLIC, | ||
539 | 431 | product.getDefaultBugInformationType()) | ||
540 | 432 | |||
541 | 433 | def test_sharing_policy_proprietary_or_public(self): | ||
542 | 434 | # bug_sharing_policy can enable and default to Proprietary. | ||
543 | 435 | product = self.makeProductWithPolicy( | ||
544 | 436 | BugSharingPolicy.PROPRIETARY_OR_PUBLIC) | ||
545 | 437 | self.assertContentEqual( | ||
546 | 438 | FREE_INFORMATION_TYPES + (InformationType.PROPRIETARY,), | ||
547 | 439 | product.getAllowedBugInformationTypes()) | ||
548 | 440 | self.assertEqual( | ||
549 | 441 | InformationType.PROPRIETARY, | ||
550 | 442 | product.getDefaultBugInformationType()) | ||
551 | 443 | |||
552 | 444 | def test_sharing_policy_proprietary(self): | ||
553 | 445 | # bug_sharing_policy can enable only Proprietary. | ||
554 | 446 | product = self.makeProductWithPolicy(BugSharingPolicy.PROPRIETARY) | ||
555 | 447 | self.assertContentEqual( | ||
556 | 448 | [InformationType.PROPRIETARY], | ||
557 | 449 | product.getAllowedBugInformationTypes()) | ||
558 | 450 | self.assertEqual( | ||
559 | 451 | InformationType.PROPRIETARY, | ||
560 | 452 | product.getDefaultBugInformationType()) | ||
561 | 453 | |||
562 | 400 | 454 | ||
563 | 401 | class TestProductFiles(TestCase): | 455 | class TestProductFiles(TestCase): |
564 | 402 | """Tests for downloadable product files.""" | 456 | """Tests for downloadable product files.""" |
Thank you.
I Suppose my branch to remove the commercial admin restriction needs to land after yours so that I can remove the test hacks.