Merge lp:~jtv/launchpad/bug-487447 into lp:launchpad
- bug-487447
- Merge into devel
Proposed by
Jeroen T. Vermeulen
Status: | Merged |
---|---|
Approved by: | Jeroen T. Vermeulen |
Approved revision: | not available |
Merged at revision: | not available |
Proposed branch: | lp:~jtv/launchpad/bug-487447 |
Merge into: | lp:launchpad |
Prerequisite: | lp:~jtv/launchpad/bug-488218 |
Diff against target: |
357 lines (+120/-67) 10 files modified
database/schema/security.cfg (+25/-23) lib/lp/testing/factory.py (+0/-1) lib/lp/translations/browser/potemplate.py (+6/-5) lib/lp/translations/interfaces/pofile.py (+3/-0) lib/lp/translations/interfaces/potemplate.py (+1/-2) lib/lp/translations/model/pofile.py (+13/-16) lib/lp/translations/model/potemplate.py (+5/-11) lib/lp/translations/model/translationimportqueue.py (+3/-2) lib/lp/translations/scripts/tests/test_message_sharing_migration.py (+3/-1) lib/lp/translations/tests/test_autoapproval.py (+61/-6) |
To merge this branch: | bzr merge lp:~jtv/launchpad/bug-487447 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Abel Deuring (community) | code | Approve | |
Review via email: mp+15315@code.launchpad.net |
Commit message
Reorganize database permissions for Translations approval. Factor canEditTranslations out of newPOFile.
Description of the change
To post a comment you must log in.
Revision history for this message
Jeroen T. Vermeulen (jtv) wrote : | # |
Revision history for this message
Abel Deuring (adeuring) wrote : | # |
Hi Jeroen,
your changes look good (as usual ;) Just one deatil: I think you don't need a permission to access public.project. Or do I miss anything?
review:
Approve
(code)
Revision history for this message
Jeroen T. Vermeulen (jtv) wrote : | # |
Thanks! The Project permission is because Projects can have TranslationGroups (as can Products).
Jeroen
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'database/schema/security.cfg' | |||
2 | --- database/schema/security.cfg 2009-11-06 01:16:21 +0000 | |||
3 | +++ database/schema/security.cfg 2009-11-27 14:15:31 +0000 | |||
4 | @@ -453,29 +453,12 @@ | |||
5 | 453 | [translations_import_queue_gardener] | 453 | [translations_import_queue_gardener] |
6 | 454 | # Translations import queue management | 454 | # Translations import queue management |
7 | 455 | type=user | 455 | type=user |
12 | 456 | groups=script | 456 | groups=script,translations_approval |
9 | 457 | public.customlanguagecode = SELECT | ||
10 | 458 | public.distribution = SELECT | ||
11 | 459 | public.distroseries = SELECT | ||
13 | 460 | public.karma = SELECT, INSERT, UPDATE | 457 | public.karma = SELECT, INSERT, UPDATE |
14 | 461 | public.karmaaction = SELECT | 458 | public.karmaaction = SELECT |
15 | 462 | public.language = SELECT | ||
16 | 463 | public.person = SELECT | ||
17 | 464 | public.pofile = SELECT, INSERT, UPDATE | ||
18 | 465 | public.pomsgid = SELECT | ||
19 | 466 | public.potemplate = SELECT, INSERT, UPDATE | ||
20 | 467 | public.potmsgset = SELECT | ||
21 | 468 | public.potranslation = SELECT, INSERT | 459 | public.potranslation = SELECT, INSERT |
22 | 469 | public.product = SELECT | ||
23 | 470 | public.productseries = SELECT | ||
24 | 471 | public.sourcepackagename = SELECT | ||
25 | 472 | public.teamparticipation = SELECT | ||
26 | 473 | public.translationgroup = SELECT | ||
27 | 474 | public.translationimportqueueentry = SELECT, DELETE, UPDATE | 460 | public.translationimportqueueentry = SELECT, DELETE, UPDATE |
28 | 475 | public.translationrelicensingagreement = SELECT | ||
29 | 476 | public.translationtemplateitem = SELECT | ||
30 | 477 | public.translationmessage = SELECT, INSERT, UPDATE | 461 | public.translationmessage = SELECT, INSERT, UPDATE |
31 | 478 | public.translator = SELECT | ||
32 | 479 | public.validpersoncache = SELECT | 462 | public.validpersoncache = SELECT |
33 | 480 | 463 | ||
34 | 481 | [poexport] | 464 | [poexport] |
35 | @@ -1369,13 +1352,32 @@ | |||
36 | 1369 | public.validpersoncache = SELECT | 1352 | public.validpersoncache = SELECT |
37 | 1370 | public.translator = SELECT | 1353 | public.translator = SELECT |
38 | 1371 | 1354 | ||
39 | 1355 | # Any script that approves translation uploads. | ||
40 | 1356 | [translations_approval] | ||
41 | 1357 | type=group | ||
42 | 1358 | public.customlanguagecode = SELECT | ||
43 | 1359 | public.distribution = SELECT | ||
44 | 1360 | public.distroseries = SELECT | ||
45 | 1361 | public.language = SELECT | ||
46 | 1362 | public.person = SELECT | ||
47 | 1363 | public.pofile = SELECT, INSERT, UPDATE | ||
48 | 1364 | public.pomsgid = SELECT | ||
49 | 1365 | public.potemplate = SELECT, INSERT, UPDATE | ||
50 | 1366 | public.potmsgset = SELECT | ||
51 | 1367 | public.product = SELECT | ||
52 | 1368 | public.productseries = SELECT | ||
53 | 1369 | public.project = SELECT | ||
54 | 1370 | public.sourcepackagename = SELECT | ||
55 | 1371 | public.teamparticipation = SELECT | ||
56 | 1372 | public.translationgroup = SELECT | ||
57 | 1373 | public.translationimportqueueentry = SELECT, UPDATE | ||
58 | 1374 | public.translationrelicensingagreement = SELECT | ||
59 | 1375 | public.translationtemplateitem = SELECT | ||
60 | 1376 | public.translator = SELECT | ||
61 | 1377 | |||
62 | 1372 | [translationsbranchscanner] | 1378 | [translationsbranchscanner] |
63 | 1373 | type=user | 1379 | type=user |
69 | 1374 | groups=branchscanner | 1380 | groups=branchscanner,translations_approval |
65 | 1375 | public.language = SELECT | ||
66 | 1376 | public.translationrelicensingagreement = SELECT | ||
67 | 1377 | public.translationgroup = SELECT | ||
68 | 1378 | public.translator = SELECT | ||
70 | 1379 | 1381 | ||
71 | 1380 | [translationstobranch] | 1382 | [translationstobranch] |
72 | 1381 | type=user | 1383 | type=user |
73 | 1382 | 1384 | ||
74 | === modified file 'lib/lp/testing/factory.py' | |||
75 | --- lib/lp/testing/factory.py 2009-11-23 19:56:19 +0000 | |||
76 | +++ lib/lp/testing/factory.py 2009-11-27 14:15:31 +0000 | |||
77 | @@ -1587,7 +1587,6 @@ | |||
78 | 1587 | if potemplate is None: | 1587 | if potemplate is None: |
79 | 1588 | potemplate = self.makePOTemplate(owner=owner) | 1588 | potemplate = self.makePOTemplate(owner=owner) |
80 | 1589 | return potemplate.newPOFile(language_code, variant, | 1589 | return potemplate.newPOFile(language_code, variant, |
81 | 1590 | requester=potemplate.owner, | ||
82 | 1591 | create_sharing=create_sharing) | 1590 | create_sharing=create_sharing) |
83 | 1592 | 1591 | ||
84 | 1593 | def makePOTMsgSet(self, potemplate, singular=None, plural=None, | 1592 | def makePOTMsgSet(self, potemplate, singular=None, plural=None, |
85 | 1594 | 1593 | ||
86 | === modified file 'lib/lp/translations/browser/potemplate.py' | |||
87 | --- lib/lp/translations/browser/potemplate.py 2009-09-19 21:22:13 +0000 | |||
88 | +++ lib/lp/translations/browser/potemplate.py 2009-11-27 14:15:31 +0000 | |||
89 | @@ -89,11 +89,12 @@ | |||
90 | 89 | return self.context.getDummyPOFile(name, requester=user) | 89 | return self.context.getDummyPOFile(name, requester=user) |
91 | 90 | else: | 90 | else: |
92 | 91 | # It's a POST. | 91 | # It's a POST. |
98 | 92 | # XXX CarlosPerelloMarin 2006-04-20: We should check the kind of | 92 | # XXX CarlosPerelloMarin 2006-04-20 bug=40275: We should |
99 | 93 | # POST we got, a Log out action will be also a POST and we should | 93 | # check the kind of POST we got. A logout will also be a |
100 | 94 | # not create an IPOFile in that case. See bug #40275 for more | 94 | # POST and we should not create a POFile in that case. |
101 | 95 | # information. | 95 | pofile = self.context.newPOFile(name) |
102 | 96 | return self.context.newPOFile(name, requester=user) | 96 | pofile.setOwnerIfPrivileged(user) |
103 | 97 | return pofile | ||
104 | 97 | 98 | ||
105 | 98 | 99 | ||
106 | 99 | class POTemplateFacets(StandardLaunchpadFacets): | 100 | class POTemplateFacets(StandardLaunchpadFacets): |
107 | 100 | 101 | ||
108 | === modified file 'lib/lp/translations/interfaces/pofile.py' | |||
109 | --- lib/lp/translations/interfaces/pofile.py 2009-10-27 12:42:22 +0000 | |||
110 | +++ lib/lp/translations/interfaces/pofile.py 2009-11-27 14:15:31 +0000 | |||
111 | @@ -214,6 +214,9 @@ | |||
112 | 214 | def canEditTranslations(person): | 214 | def canEditTranslations(person): |
113 | 215 | """Whether the given person is able to add/edit translations.""" | 215 | """Whether the given person is able to add/edit translations.""" |
114 | 216 | 216 | ||
115 | 217 | def setOwnerIfPrivileged(person): | ||
116 | 218 | """Set `owner` to `person`, provided `person` has edit rights.""" | ||
117 | 219 | |||
118 | 217 | def canAddSuggestions(person): | 220 | def canAddSuggestions(person): |
119 | 218 | """Whether the given person is able to add new suggestions.""" | 221 | """Whether the given person is able to add new suggestions.""" |
120 | 219 | 222 | ||
121 | 220 | 223 | ||
122 | === modified file 'lib/lp/translations/interfaces/potemplate.py' | |||
123 | --- lib/lp/translations/interfaces/potemplate.py 2009-10-30 10:09:17 +0000 | |||
124 | +++ lib/lp/translations/interfaces/potemplate.py 2009-11-27 14:15:31 +0000 | |||
125 | @@ -432,8 +432,7 @@ | |||
126 | 432 | def expireAllMessages(): | 432 | def expireAllMessages(): |
127 | 433 | """Mark all of our message sets as not current (sequence=0)""" | 433 | """Mark all of our message sets as not current (sequence=0)""" |
128 | 434 | 434 | ||
131 | 435 | def newPOFile(language_code, variant=None, | 435 | def newPOFile(language_code, variant=None, create_sharing=True): |
130 | 436 | requester=None, create_sharing=True): | ||
132 | 437 | """Return a new `IPOFile` for the given language. | 436 | """Return a new `IPOFile` for the given language. |
133 | 438 | 437 | ||
134 | 439 | Raise LanguageNotFound if the language does not exist in the | 438 | Raise LanguageNotFound if the language does not exist in the |
135 | 440 | 439 | ||
136 | === modified file 'lib/lp/translations/model/pofile.py' | |||
137 | --- lib/lp/translations/model/pofile.py 2009-11-17 09:50:33 +0000 | |||
138 | +++ lib/lp/translations/model/pofile.py 2009-11-27 14:15:31 +0000 | |||
139 | @@ -244,6 +244,19 @@ | |||
140 | 244 | forms = 2 | 244 | forms = 2 |
141 | 245 | return forms | 245 | return forms |
142 | 246 | 246 | ||
143 | 247 | def canEditTranslations(self, person): | ||
144 | 248 | """See `IPOFile`.""" | ||
145 | 249 | return _can_edit_translations(self, person) | ||
146 | 250 | |||
147 | 251 | def canAddSuggestions(self, person): | ||
148 | 252 | """See `IPOFile`.""" | ||
149 | 253 | return _can_add_suggestions(self, person) | ||
150 | 254 | |||
151 | 255 | def setOwnerIfPrivileged(self, person): | ||
152 | 256 | """See `IPOFile`.""" | ||
153 | 257 | if self.canEditTranslations(person): | ||
154 | 258 | self.owner = person | ||
155 | 259 | |||
156 | 247 | def getHeader(self): | 260 | def getHeader(self): |
157 | 248 | """See `IPOFile`.""" | 261 | """See `IPOFile`.""" |
158 | 249 | translation_importer = getUtility(ITranslationImporter) | 262 | translation_importer = getUtility(ITranslationImporter) |
159 | @@ -586,14 +599,6 @@ | |||
160 | 586 | "Calling prepareTranslationCredits on a message with " | 599 | "Calling prepareTranslationCredits on a message with " |
161 | 587 | "unknown credits type '%s'." % credits_type.title) | 600 | "unknown credits type '%s'." % credits_type.title) |
162 | 588 | 601 | ||
163 | 589 | def canEditTranslations(self, person): | ||
164 | 590 | """See `IPOFile`.""" | ||
165 | 591 | return _can_edit_translations(self, person) | ||
166 | 592 | |||
167 | 593 | def canAddSuggestions(self, person): | ||
168 | 594 | """See `IPOFile`.""" | ||
169 | 595 | return _can_add_suggestions(self, person) | ||
170 | 596 | |||
171 | 597 | def translated(self): | 602 | def translated(self): |
172 | 598 | """See `IPOFile`.""" | 603 | """See `IPOFile`.""" |
173 | 599 | raise NotImplementedError | 604 | raise NotImplementedError |
174 | @@ -1365,14 +1370,6 @@ | |||
175 | 1365 | """See `IPOFile`.""" | 1370 | """See `IPOFile`.""" |
176 | 1366 | return self.potemplate.translationpermission | 1371 | return self.potemplate.translationpermission |
177 | 1367 | 1372 | ||
178 | 1368 | def canEditTranslations(self, person): | ||
179 | 1369 | """See `IPOFile`.""" | ||
180 | 1370 | return _can_edit_translations(self, person) | ||
181 | 1371 | |||
182 | 1372 | def canAddSuggestions(self, person): | ||
183 | 1373 | """See `IPOFile`.""" | ||
184 | 1374 | return _can_add_suggestions(self, person) | ||
185 | 1375 | |||
186 | 1376 | def emptySelectResults(self): | 1373 | def emptySelectResults(self): |
187 | 1377 | return POFile.select("1=2") | 1374 | return POFile.select("1=2") |
188 | 1378 | 1375 | ||
189 | 1379 | 1376 | ||
190 | === modified file 'lib/lp/translations/model/potemplate.py' | |||
191 | --- lib/lp/translations/model/potemplate.py 2009-11-17 09:50:33 +0000 | |||
192 | +++ lib/lp/translations/model/potemplate.py 2009-11-27 14:15:31 +0000 | |||
193 | @@ -734,8 +734,7 @@ | |||
194 | 734 | template._cached_pofiles_by_language[language_code, | 734 | template._cached_pofiles_by_language[language_code, |
195 | 735 | variant] = pofile | 735 | variant] = pofile |
196 | 736 | 736 | ||
199 | 737 | def newPOFile(self, language_code, variant=None, requester=None, | 737 | def newPOFile(self, language_code, variant=None, create_sharing=True): |
198 | 738 | create_sharing=True): | ||
200 | 739 | """See `IPOTemplate`.""" | 738 | """See `IPOTemplate`.""" |
201 | 740 | # Make sure we don't already have a PO file for this language. | 739 | # Make sure we don't already have a PO file for this language. |
202 | 741 | existingpo = self.getPOFileByLang(language_code, variant) | 740 | existingpo = self.getPOFileByLang(language_code, variant) |
203 | @@ -763,13 +762,8 @@ | |||
204 | 763 | else: | 762 | else: |
205 | 764 | data['origin'] = self.sourcepackagename.name | 763 | data['origin'] = self.sourcepackagename.name |
206 | 765 | 764 | ||
214 | 766 | # The default POFile owner is the Rosetta Experts team unless the | 765 | # The default POFile owner is the Rosetta Experts team. |
215 | 767 | # requester has rights to write into that file. | 766 | owner = getUtility(ILaunchpadCelebrities).rosetta_experts |
209 | 768 | dummy_pofile = self.getDummyPOFile(language.code, variant) | ||
210 | 769 | if dummy_pofile.canEditTranslations(requester): | ||
211 | 770 | owner = requester | ||
212 | 771 | else: | ||
213 | 772 | owner = getUtility(ILaunchpadCelebrities).rosetta_experts | ||
216 | 773 | 767 | ||
217 | 774 | path = self._composePOFilePath(language, variant) | 768 | path = self._composePOFilePath(language, variant) |
218 | 775 | 769 | ||
219 | @@ -1117,8 +1111,8 @@ | |||
220 | 1117 | if shared_template is template: | 1111 | if shared_template is template: |
221 | 1118 | continue | 1112 | continue |
222 | 1119 | for pofile in shared_template.pofiles: | 1113 | for pofile in shared_template.pofiles: |
225 | 1120 | template.newPOFile(pofile.language.code, | 1114 | template.newPOFile( |
226 | 1121 | pofile.variant, pofile.owner, False) | 1115 | pofile.language.code, pofile.variant, False) |
227 | 1122 | # Do not continue, else it would trigger an existingpo assertion. | 1116 | # Do not continue, else it would trigger an existingpo assertion. |
228 | 1123 | return | 1117 | return |
229 | 1124 | 1118 | ||
230 | 1125 | 1119 | ||
231 | === modified file 'lib/lp/translations/model/translationimportqueue.py' | |||
232 | --- lib/lp/translations/model/translationimportqueue.py 2009-11-19 07:45:09 +0000 | |||
233 | +++ lib/lp/translations/model/translationimportqueue.py 2009-11-27 14:15:31 +0000 | |||
234 | @@ -444,8 +444,9 @@ | |||
235 | 444 | # Get or create an IPOFile based on the info we guess. | 444 | # Get or create an IPOFile based on the info we guess. |
236 | 445 | pofile = potemplate.getPOFileByLang(language.code, variant=variant) | 445 | pofile = potemplate.getPOFileByLang(language.code, variant=variant) |
237 | 446 | if pofile is None: | 446 | if pofile is None: |
240 | 447 | pofile = potemplate.newPOFile( | 447 | pofile = potemplate.newPOFile(language.code, variant=variant) |
241 | 448 | language.code, variant=variant, requester=self.importer) | 448 | if pofile.canEditTranslations(self.importer): |
242 | 449 | pofile.owner = self.importer | ||
243 | 449 | 450 | ||
244 | 450 | if self.is_published: | 451 | if self.is_published: |
245 | 451 | # This entry comes from upstream, which means that the path we got | 452 | # This entry comes from upstream, which means that the path we got |
246 | 452 | 453 | ||
247 | === modified file 'lib/lp/translations/scripts/tests/test_message_sharing_migration.py' | |||
248 | --- lib/lp/translations/scripts/tests/test_message_sharing_migration.py 2009-10-28 13:08:05 +0000 | |||
249 | +++ lib/lp/translations/scripts/tests/test_message_sharing_migration.py 2009-11-27 14:15:31 +0000 | |||
250 | @@ -514,12 +514,14 @@ | |||
251 | 514 | poftset = getUtility(IPOFileTranslatorSet) | 514 | poftset = getUtility(IPOFileTranslatorSet) |
252 | 515 | 515 | ||
253 | 516 | translator = self.trunk_template.owner | 516 | translator = self.trunk_template.owner |
254 | 517 | self.trunk_pofile.owner = translator | ||
255 | 518 | self.stable_pofile.owner = translator | ||
256 | 517 | 519 | ||
257 | 518 | contented_potmsgset = self.factory.makePOTMsgSet( | 520 | contented_potmsgset = self.factory.makePOTMsgSet( |
258 | 519 | self.trunk_template, singular='snut', sequence=2) | 521 | self.trunk_template, singular='snut', sequence=2) |
259 | 520 | contented_message = self._makeTranslationMessage( | 522 | contented_message = self._makeTranslationMessage( |
260 | 521 | self.trunk_pofile, contented_potmsgset, 'druf', False) | 523 | self.trunk_pofile, contented_potmsgset, 'druf', False) |
262 | 522 | self.assertEqual(contented_message.submitter, translator) | 524 | self.assertEqual(translator, contented_message.submitter) |
263 | 523 | poft = poftset.getForPersonPOFile(translator, self.trunk_pofile) | 525 | poft = poftset.getForPersonPOFile(translator, self.trunk_pofile) |
264 | 524 | self.assertEqual(poft.latest_message, contented_message) | 526 | self.assertEqual(poft.latest_message, contented_message) |
265 | 525 | 527 | ||
266 | 526 | 528 | ||
267 | === modified file 'lib/lp/translations/tests/test_autoapproval.py' | |||
268 | --- lib/lp/translations/tests/test_autoapproval.py 2009-11-19 07:45:09 +0000 | |||
269 | +++ lib/lp/translations/tests/test_autoapproval.py 2009-11-27 14:15:31 +0000 | |||
270 | @@ -23,11 +23,10 @@ | |||
271 | 23 | from lp.registry.model.sourcepackagename import ( | 23 | from lp.registry.model.sourcepackagename import ( |
272 | 24 | SourcePackageName, | 24 | SourcePackageName, |
273 | 25 | SourcePackageNameSet) | 25 | SourcePackageNameSet) |
275 | 26 | from lp.services.worlddata.model.language import Language | 26 | from lp.services.worlddata.model.language import Language, LanguageSet |
276 | 27 | from lp.translations.model.customlanguagecode import CustomLanguageCode | 27 | from lp.translations.model.customlanguagecode import CustomLanguageCode |
280 | 28 | from lp.translations.model.potemplate import ( | 28 | from lp.translations.model.pofile import POFile |
281 | 29 | POTemplateSet, | 29 | from lp.translations.model.potemplate import POTemplateSet, POTemplateSubset |
279 | 30 | POTemplateSubset) | ||
282 | 31 | from lp.translations.model.translationimportqueue import ( | 30 | from lp.translations.model.translationimportqueue import ( |
283 | 32 | TranslationImportQueue, TranslationImportQueueEntry) | 31 | TranslationImportQueue, TranslationImportQueueEntry) |
284 | 33 | from lp.translations.interfaces.customlanguagecode import ICustomLanguageCode | 32 | from lp.translations.interfaces.customlanguagecode import ICustomLanguageCode |
285 | @@ -152,8 +151,7 @@ | |||
286 | 152 | 151 | ||
287 | 153 | def _makePOFile(self, language_code): | 152 | def _makePOFile(self, language_code): |
288 | 154 | """Create a translation file.""" | 153 | """Create a translation file.""" |
291 | 155 | file = self.template.newPOFile( | 154 | file = self.template.newPOFile(language_code) |
290 | 156 | language_code, requester=self.product.owner) | ||
292 | 157 | file.syncUpdate() | 155 | file.syncUpdate() |
293 | 158 | return file | 156 | return file |
294 | 159 | 157 | ||
295 | @@ -829,5 +827,62 @@ | |||
296 | 829 | self.assertFalse(self._exists(entry_id)) | 827 | self.assertFalse(self._exists(entry_id)) |
297 | 830 | 828 | ||
298 | 831 | 829 | ||
299 | 830 | class TestAutoApprovalNewPOFile(TestCaseWithFactory): | ||
300 | 831 | """Test creation of new `POFile`s in approval.""" | ||
301 | 832 | |||
302 | 833 | layer = LaunchpadZopelessLayer | ||
303 | 834 | |||
304 | 835 | def setUp(self): | ||
305 | 836 | super(TestAutoApprovalNewPOFile, self).setUp() | ||
306 | 837 | self.product = self.factory.makeProduct() | ||
307 | 838 | self.queue = TranslationImportQueue() | ||
308 | 839 | self.language = LanguageSet().getLanguageByCode('nl') | ||
309 | 840 | |||
310 | 841 | def _makeTemplate(self, series): | ||
311 | 842 | """Create a template.""" | ||
312 | 843 | return POTemplateSubset(productseries=series).new( | ||
313 | 844 | 'test', 'test', 'test.pot', self.product.owner) | ||
314 | 845 | |||
315 | 846 | def _makeQueueEntry(self, series): | ||
316 | 847 | """Create translation import queue entry.""" | ||
317 | 848 | return self.queue.addOrUpdateEntry( | ||
318 | 849 | "%s.po" % self.language.code, 'contents', True, | ||
319 | 850 | self.product.owner, productseries=series) | ||
320 | 851 | |||
321 | 852 | def test_getGuessedPOFile_creates_POFile(self): | ||
322 | 853 | # Auto-approval may involve creating POFiles. The queue | ||
323 | 854 | # gardener has permissions to do this. The POFile's owner is | ||
324 | 855 | # the rosetta_experts team. | ||
325 | 856 | trunk = self.product.getSeries('trunk') | ||
326 | 857 | template = self._makeTemplate(trunk) | ||
327 | 858 | entry = self._makeQueueEntry(trunk) | ||
328 | 859 | rosetta_experts = getUtility(ILaunchpadCelebrities).rosetta_experts | ||
329 | 860 | |||
330 | 861 | become_the_gardener(self.layer) | ||
331 | 862 | |||
332 | 863 | pofile = entry.getGuessedPOFile() | ||
333 | 864 | |||
334 | 865 | self.assertIsInstance(pofile, POFile) | ||
335 | 866 | self.assertNotEqual(rosetta_experts, pofile.owner) | ||
336 | 867 | |||
337 | 868 | def test_getGuessedPOFile_creates_POFile_with_credits(self): | ||
338 | 869 | # When the approver creates a POFile for a template that | ||
339 | 870 | # has a translation credits message, it also includes a | ||
340 | 871 | # "translation" for the credits message. | ||
341 | 872 | trunk = self.product.getSeries('trunk') | ||
342 | 873 | template = self._makeTemplate(trunk) | ||
343 | 874 | credits = self.factory.makePOTMsgSet( | ||
344 | 875 | template, singular='translation-credits', sequence=1) | ||
345 | 876 | |||
346 | 877 | entry = self._makeQueueEntry(trunk) | ||
347 | 878 | |||
348 | 879 | become_the_gardener(self.layer) | ||
349 | 880 | |||
350 | 881 | pofile = entry.getGuessedPOFile() | ||
351 | 882 | |||
352 | 883 | credits.getCurrentTranslationMessage(template, self.language) | ||
353 | 884 | self.assertNotEqual(None, credits) | ||
354 | 885 | |||
355 | 886 | |||
356 | 832 | def test_suite(): | 887 | def test_suite(): |
357 | 833 | return unittest.TestLoader().loadTestsFromName(__name__) | 888 | return unittest.TestLoader().loadTestsFromName(__name__) |
= Bugs 443129, 487447 =
We were getting some database permission errors as the two scripts that approve translations uploads created new POFiles. This has been happening a lot lately, particularly because of a fairly pointless permissions check in initializing the owner of a new POFile. POFile.owner pretty much unused anyway.
This branch does the following:
* Reorganizes database permissions by creating a single group for "anything that approves translations uploads."
* Lifts the setting of POFile.owner out of newPOFile and into the caller—along with the check to see whether that person is qualified to be the owner.
* Gets rid of the parameter that told newPOFile what owner to set (if qualified).
* Hoists some related IPOFile methods from POFile and DummyPOFile into their common base class.
* Always makes rosetta_experts the owner of POFiles created by the approver (instead of the uploader).
* Tests for the database privileges necessary for approving a POFile.
No lint. Main test is test_autoapproval. Q/A procedure on staging:
- Set up a project for translation, including an import branch. credits"
- Push a template and a translation to the branch. The template should have a message "translation-
- See that the template and the translation get approved & imported.
- Manually upload another translation for the same template.
- See this get approved & imported as well.
Jeroen