Merge lp:~henninge/launchpad/devel-710591-importer into lp:launchpad
- devel-710591-importer
- Merge into devel
Status: | Superseded |
---|---|
Proposed branch: | lp:~henninge/launchpad/devel-710591-importer |
Merge into: | lp:launchpad |
Prerequisite: | lp:~henninge/launchpad/devel-710591-setcurrenttranslation-extension |
Diff against target: |
860 lines (+489/-117) 10 files modified
lib/lp/registry/model/distribution.py (+9/-6) lib/lp/translations/model/potmsgset.py (+6/-4) lib/lp/translations/scripts/upload_translations.py (+96/-0) lib/lp/translations/tests/test_translationmessage.py (+175/-75) lib/lp/translations/tests/test_translationpolicy.py (+38/-8) lib/lp/translations/utilities/tests/test_file_importer.py (+78/-17) lib/lp/translations/utilities/tests/test_translation_sharing_info.py (+40/-0) lib/lp/translations/utilities/translation_import.py (+26/-5) lib/lp/translations/utilities/translationsharinginfo.py (+2/-2) scripts/rosetta/upload-translations.py (+19/-0) |
To merge this branch: | bzr merge lp:~henninge/launchpad/devel-710591-importer |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jeroen T. Vermeulen (community) | code | Approve | |
Ian Booth (community) | release-critical | Approve | |
Review via email: mp+48682@code.launchpad.net |
This proposal has been superseded by a proposal from 2011-02-11.
Commit message
Description of the change
= Summary =
This is the final branch to fix bug 710591. It brings together
the functions and methods that the previous two introduced.
== Proposed fix ==
Add a boolean property to FileImporter that makes use
has_upstream_
use.
Replace the use of "approve" in the importer with the
"accept" mtethods.
== Pre-implementation notes ==
I still refer to my chat with Danilo about this but also
Jeroen and I talked a bit while he reviewed the last
branch.
== Implementation details ==
Pretty straight forward implementation, I'd say.
== Tests ==
bin/test -vvcm lp.translations
I also ran this to check that anything related to "import" might
be affected:
bin/test -vvcm lp.translations -t import
== Demo and Q/A ==
Import on a source package and see what happens.
= Launchpad lint =
Checking for conflicts and issues in changed files.
Linting changed files:
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
./lib/lp/
365: E302 expected 2 blank lines, found 1
Henning Eggers (henninge) wrote : | # |
Ian Booth (wallyworld) wrote : | # |
Approved so long as the formal code review is ok and it's fully QAed as soon as possible after deployment to qastaging.
Jeroen T. Vermeulen (jtv) wrote : | # |
Beautiful.
In accordance to my personal prove-you'
107 + # - The by_maintainer flag must be set.
You may want to mention where this flag is (on the import-queue entry), since it's not where the reader would be most likely to look for it. You could say something like "the translation must come from an upload with the by_maintainer flag set."
Jeroen
Preview Diff
1 | === modified file 'lib/lp/registry/model/distribution.py' | |||
2 | --- lib/lp/registry/model/distribution.py 2011-02-09 19:25:43 +0000 | |||
3 | +++ lib/lp/registry/model/distribution.py 2011-02-11 14:44:33 +0000 | |||
4 | @@ -205,6 +205,9 @@ | |||
5 | 205 | HasTranslationImportsMixin, | 205 | HasTranslationImportsMixin, |
6 | 206 | ) | 206 | ) |
7 | 207 | from lp.translations.model.translationpolicy import TranslationPolicyMixin | 207 | from lp.translations.model.translationpolicy import TranslationPolicyMixin |
8 | 208 | from lp.translations.utilities.translationsharinginfo import ( | ||
9 | 209 | has_upstream_template, | ||
10 | 210 | ) | ||
11 | 208 | 211 | ||
12 | 209 | 212 | ||
13 | 210 | class Distribution(SQLBase, BugTargetBase, MakesAnnouncements, | 213 | class Distribution(SQLBase, BugTargetBase, MakesAnnouncements, |
14 | @@ -1845,11 +1848,11 @@ | |||
15 | 1845 | assert sourcepackage is not None, ( | 1848 | assert sourcepackage is not None, ( |
16 | 1846 | "Translations sharing policy requires a SourcePackage.") | 1849 | "Translations sharing policy requires a SourcePackage.") |
17 | 1847 | 1850 | ||
23 | 1848 | sharing_productseries = sourcepackage.productseries | 1851 | if not has_upstream_template( |
24 | 1849 | if sharing_productseries is None: | 1852 | sourcepackage.distroseries, sourcepackage.sourcepackagename): |
25 | 1850 | # There is no known upstream series. Take the uploader's | 1853 | # There is no known upstream template or series. Take the |
26 | 1851 | # word for whether these are upstream translations (in which | 1854 | # uploader's word for whether these are upstream translations |
27 | 1852 | # case they're shared) or not. | 1855 | # (in which case they're shared) or not. |
28 | 1853 | # What are the consequences if that value is incorrect? In | 1856 | # What are the consequences if that value is incorrect? In |
29 | 1854 | # the case where translations from upstream are purportedly | 1857 | # the case where translations from upstream are purportedly |
30 | 1855 | # from Ubuntu, we miss a chance at sharing when the package | 1858 | # from Ubuntu, we miss a chance at sharing when the package |
31 | @@ -1861,7 +1864,7 @@ | |||
32 | 1861 | # translations for upstream. | 1864 | # translations for upstream. |
33 | 1862 | return purportedly_upstream | 1865 | return purportedly_upstream |
34 | 1863 | 1866 | ||
36 | 1864 | upstream_product = sharing_productseries.product | 1867 | upstream_product = sourcepackage.productseries.product |
37 | 1865 | return upstream_product.invitesTranslationEdits(person, language) | 1868 | return upstream_product.invitesTranslationEdits(person, language) |
38 | 1866 | 1869 | ||
39 | 1867 | 1870 | ||
40 | 1868 | 1871 | ||
41 | === modified file 'lib/lp/translations/model/potmsgset.py' | |||
42 | --- lib/lp/translations/model/potmsgset.py 2011-02-04 17:14:20 +0000 | |||
43 | +++ lib/lp/translations/model/potmsgset.py 2011-02-11 14:44:33 +0000 | |||
44 | @@ -796,11 +796,12 @@ | |||
45 | 796 | template, pofile.language, template.translation_side) | 796 | template, pofile.language, template.translation_side) |
46 | 797 | other = self.getOtherTranslation( | 797 | other = self.getOtherTranslation( |
47 | 798 | pofile.language, template.translation_side) | 798 | pofile.language, template.translation_side) |
51 | 799 | if other is not None: | 799 | if current is None or other is None or current == other: |
49 | 800 | other.is_current_upstream = False | ||
50 | 801 | if current is None or other is None: | ||
52 | 802 | translator = suggestion.submitter | 800 | translator = suggestion.submitter |
53 | 803 | potranslations = dictify_translations(suggestion.all_msgstrs) | 801 | potranslations = dictify_translations(suggestion.all_msgstrs) |
54 | 802 | if other is not None: | ||
55 | 803 | # Steal flag beforehand. | ||
56 | 804 | other.is_current_upstream = False | ||
57 | 804 | self._setTranslation( | 805 | self._setTranslation( |
58 | 805 | pofile, translator, suggestion.origin, potranslations, | 806 | pofile, translator, suggestion.origin, potranslations, |
59 | 806 | share_with_other_side=True, | 807 | share_with_other_side=True, |
60 | @@ -808,8 +809,9 @@ | |||
61 | 808 | lock_timestamp=lock_timestamp) | 809 | lock_timestamp=lock_timestamp) |
62 | 809 | else: | 810 | else: |
63 | 810 | # Make it only current in upstream. | 811 | # Make it only current in upstream. |
64 | 811 | suggestion.is_current_upstream = True | ||
65 | 812 | if suggestion != other: | 812 | if suggestion != other: |
66 | 813 | other.is_current_upstream = False | ||
67 | 814 | suggestion.is_current_upstream = True | ||
68 | 813 | pofile.markChanged(translator=suggestion.submitter) | 815 | pofile.markChanged(translator=suggestion.submitter) |
69 | 814 | 816 | ||
70 | 815 | def _cloneAndDiverge(self, original_message, pofile): | 817 | def _cloneAndDiverge(self, original_message, pofile): |
71 | 816 | 818 | ||
72 | === added file 'lib/lp/translations/scripts/upload_translations.py' | |||
73 | --- lib/lp/translations/scripts/upload_translations.py 1970-01-01 00:00:00 +0000 | |||
74 | +++ lib/lp/translations/scripts/upload_translations.py 2011-02-11 14:44:33 +0000 | |||
75 | @@ -0,0 +1,96 @@ | |||
76 | 1 | # Copyright 2011 Canonical Ltd. This software is licensed under the | ||
77 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | ||
78 | 3 | |||
79 | 4 | __metaclass__ = type | ||
80 | 5 | |||
81 | 6 | __all__ = [ | ||
82 | 7 | 'UploadPackageTranslations', | ||
83 | 8 | ] | ||
84 | 9 | |||
85 | 10 | import os | ||
86 | 11 | |||
87 | 12 | from zope.component import getUtility | ||
88 | 13 | |||
89 | 14 | from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities | ||
90 | 15 | from lp.registry.interfaces.sourcepackagename import ISourcePackageNameSet | ||
91 | 16 | from lp.services.scripts.base import ( | ||
92 | 17 | LaunchpadScript, | ||
93 | 18 | LaunchpadScriptFailure, | ||
94 | 19 | ) | ||
95 | 20 | from lp.translations.interfaces.translationimportqueue import ( | ||
96 | 21 | ITranslationImportQueue, | ||
97 | 22 | ) | ||
98 | 23 | |||
99 | 24 | |||
100 | 25 | class UploadPackageTranslations(LaunchpadScript): | ||
101 | 26 | """Upload translations for given distribution package.""" | ||
102 | 27 | description = "Upload translation files for a package." | ||
103 | 28 | |||
104 | 29 | def add_my_options(self): | ||
105 | 30 | """See `LaunchpadScript`.""" | ||
106 | 31 | self.parser.add_option('-d', '--distribution', dest='distro', | ||
107 | 32 | help="Distribution to upload for.", default='ubuntu') | ||
108 | 33 | self.parser.add_option('-s', '--series', dest='distroseries', | ||
109 | 34 | help="Distribution release series to upload for.") | ||
110 | 35 | self.parser.add_option('-p', '--package', dest='package', | ||
111 | 36 | help="Name of source package to upload to.") | ||
112 | 37 | self.parser.add_option('-l', '--dry-run', dest='dryrun', | ||
113 | 38 | action='store_true', default=False, | ||
114 | 39 | help="Pretend to upload, but make no actual changes.") | ||
115 | 40 | |||
116 | 41 | def main(self): | ||
117 | 42 | """See `LaunchpadScript`.""" | ||
118 | 43 | self._setDistroDetails() | ||
119 | 44 | self._setPackage() | ||
120 | 45 | |||
121 | 46 | if self.options.dryrun: | ||
122 | 47 | self.logger.info("Dry run. Not really uploading anything.") | ||
123 | 48 | |||
124 | 49 | queue = getUtility(ITranslationImportQueue) | ||
125 | 50 | rosetta_team = getUtility(ILaunchpadCelebrities).rosetta_experts | ||
126 | 51 | |||
127 | 52 | for filename in self.args: | ||
128 | 53 | if not os.access(filename, os.R_OK): | ||
129 | 54 | self.logger.info("Skipping: %s" % filename) | ||
130 | 55 | continue | ||
131 | 56 | self.logger.info("Uploading: %s." % filename) | ||
132 | 57 | content = open(filename).read() | ||
133 | 58 | queue.addOrUpdateEntry( | ||
134 | 59 | filename, content, True, rosetta_team, | ||
135 | 60 | sourcepackagename = self.sourcepackagename, | ||
136 | 61 | distroseries = self.distroseries) | ||
137 | 62 | self._commit() | ||
138 | 63 | |||
139 | 64 | self.logger.info("Done.") | ||
140 | 65 | |||
141 | 66 | def _commit(self): | ||
142 | 67 | """Commit transaction (or abort if dry run).""" | ||
143 | 68 | if self.txn: | ||
144 | 69 | if self.options.dryrun: | ||
145 | 70 | self.txn.abort() | ||
146 | 71 | else: | ||
147 | 72 | self.txn.commit() | ||
148 | 73 | |||
149 | 74 | def _setDistroDetails(self): | ||
150 | 75 | """Figure out the `Distribution`/`DistroSeries` to act upon.""" | ||
151 | 76 | # Avoid circular imports. | ||
152 | 77 | from lp.registry.interfaces.distribution import IDistributionSet | ||
153 | 78 | |||
154 | 79 | distroset = getUtility(IDistributionSet) | ||
155 | 80 | self.distro = distroset.getByName(self.options.distro) | ||
156 | 81 | |||
157 | 82 | if not self.options.distroseries: | ||
158 | 83 | raise LaunchpadScriptFailure( | ||
159 | 84 | "Specify a distribution release series.") | ||
160 | 85 | |||
161 | 86 | self.distroseries = self.distro.getSeries(self.options.distroseries) | ||
162 | 87 | |||
163 | 88 | def _setPackage(self): | ||
164 | 89 | """Find `SourcePackage` of given name.""" | ||
165 | 90 | # Avoid circular imports. | ||
166 | 91 | if not self.options.package: | ||
167 | 92 | raise LaunchpadScriptFailure("No package specified.") | ||
168 | 93 | |||
169 | 94 | nameset = getUtility(ISourcePackageNameSet) | ||
170 | 95 | |||
171 | 96 | self.sourcepackagename = nameset.queryByName(self.options.package) | ||
172 | 0 | 97 | ||
173 | === modified file 'lib/lp/translations/tests/test_translationmessage.py' | |||
174 | --- lib/lp/translations/tests/test_translationmessage.py 2011-02-04 18:04:14 +0000 | |||
175 | +++ lib/lp/translations/tests/test_translationmessage.py 2011-02-11 14:44:33 +0000 | |||
176 | @@ -362,6 +362,7 @@ | |||
177 | 362 | 362 | ||
178 | 363 | self.assertEqual([], karmarecorder.karma_events) | 363 | self.assertEqual([], karmarecorder.karma_events) |
179 | 364 | 364 | ||
180 | 365 | |||
181 | 365 | class TestAcceptFromUpstreamImportOnPackage(TestCaseWithFactory): | 366 | class TestAcceptFromUpstreamImportOnPackage(TestCaseWithFactory): |
182 | 366 | """Tests for `TranslationMessage.acceptFromUpstreamImportOnPackage`. | 367 | """Tests for `TranslationMessage.acceptFromUpstreamImportOnPackage`. |
183 | 367 | 368 | ||
184 | @@ -371,100 +372,199 @@ | |||
185 | 371 | 372 | ||
186 | 372 | layer = ZopelessDatabaseLayer | 373 | layer = ZopelessDatabaseLayer |
187 | 373 | 374 | ||
188 | 375 | def _getStates(self, *messages): | ||
189 | 376 | """Get is_current_* states for messages. | ||
190 | 377 | |||
191 | 378 | :param messages: A list of messages to get state for. | ||
192 | 379 | :returns: List of tuples of two boolean values for the | ||
193 | 380 | values of (is_current_ubuntu, is_current_upstream) for each | ||
194 | 381 | message. | ||
195 | 382 | """ | ||
196 | 383 | return [ | ||
197 | 384 | (message.is_current_ubuntu, message.is_current_upstream) | ||
198 | 385 | for message in messages] | ||
199 | 386 | |||
200 | 387 | def _makeMessages(self, pofile, | ||
201 | 388 | identical_ubuntu=None, identical_upstream=None, | ||
202 | 389 | is_tracking=False): | ||
203 | 390 | """ Create a suggestion and possible pre-existing translations. | ||
204 | 391 | |||
205 | 392 | The two identical_* parameters are tri-state: | ||
206 | 393 | - If None, do not create such a message. | ||
207 | 394 | - If True, the suggestion is identical to this message. | ||
208 | 395 | - If False, the suggestion is different from this message. | ||
209 | 396 | |||
210 | 397 | :param pofile: The pofile to create messages in. | ||
211 | 398 | :param identical_ubuntu: If and how to create the ubuntu message. | ||
212 | 399 | :param identical upstream: If and how to create the upstream | ||
213 | 400 | message. | ||
214 | 401 | :param is_trackging: Used if both messages are created to indicate | ||
215 | 402 | that they should be identical to each other. | ||
216 | 403 | :returns: One, two or three messages, as requested. | ||
217 | 404 | """ | ||
218 | 405 | ubuntu = None | ||
219 | 406 | upstream = None | ||
220 | 407 | |||
221 | 408 | potmsgset = self.factory.makePOTMsgSet(potemplate=pofile.potemplate) | ||
222 | 409 | |||
223 | 410 | if identical_upstream is not None: | ||
224 | 411 | upstream = self.factory.makeCurrentTranslationMessage( | ||
225 | 412 | potmsgset=potmsgset, pofile=pofile, current_other=True) | ||
226 | 413 | upstream.is_current_ubuntu = False | ||
227 | 414 | if identical_ubuntu is not None: | ||
228 | 415 | if is_tracking or (identical_ubuntu and identical_upstream): | ||
229 | 416 | assert upstream is not None, ( | ||
230 | 417 | "Don't use is_tracking without identical_upstream") | ||
231 | 418 | upstream.is_current_ubuntu = True | ||
232 | 419 | ubuntu = upstream | ||
233 | 420 | else: | ||
234 | 421 | ubuntu = self.factory.makeCurrentTranslationMessage( | ||
235 | 422 | potmsgset=potmsgset, pofile=pofile) | ||
236 | 423 | if identical_upstream: | ||
237 | 424 | translations = upstream.translations | ||
238 | 425 | elif identical_ubuntu: | ||
239 | 426 | translations = ubuntu.translations | ||
240 | 427 | else: | ||
241 | 428 | translations = None | ||
242 | 429 | suggestion = self.factory.makeSuggestion( | ||
243 | 430 | pofile=pofile, potmsgset=potmsgset, translations=translations) | ||
244 | 431 | |||
245 | 432 | return [message for message in (suggestion, ubuntu, upstream) | ||
246 | 433 | if message is not None] | ||
247 | 434 | |||
248 | 374 | def test_accept_activates_message_if_untranslated(self): | 435 | def test_accept_activates_message_if_untranslated(self): |
249 | 375 | # An untranslated message accepts an imported translation. | 436 | # An untranslated message accepts an imported translation. |
250 | 376 | pofile = self.factory.makePOFile(side=TranslationSide.UBUNTU) | 437 | pofile = self.factory.makePOFile(side=TranslationSide.UBUNTU) |
255 | 377 | suggestion = self.factory.makeSuggestion(pofile=pofile) | 438 | suggestion = self._makeMessages(pofile)[0] |
252 | 378 | reviewer = self.factory.makePerson() | ||
253 | 379 | self.assertFalse(suggestion.is_current_ubuntu) | ||
254 | 380 | self.assertFalse(suggestion.is_current_upstream) | ||
256 | 381 | 439 | ||
257 | 382 | suggestion.acceptFromUpstreamImportOnPackage(pofile) | 440 | suggestion.acceptFromUpstreamImportOnPackage(pofile) |
258 | 383 | 441 | ||
259 | 384 | # Messages are always accepted on the other side, too. | 442 | # Messages are always accepted on the other side, too. |
262 | 385 | self.assertTrue(suggestion.is_current_ubuntu) | 443 | self.assertEqual([(True, True)], self._getStates(suggestion)) |
261 | 386 | self.assertTrue(suggestion.is_current_upstream) | ||
263 | 387 | 444 | ||
264 | 388 | def test_accept_no_previously_imported(self): | 445 | def test_accept_no_previously_imported(self): |
265 | 389 | # If there was already a current translation, but no previously | 446 | # If there was already a current translation, but no previously |
266 | 390 | # imported one, it is disabled when a suggestion is accepted. | 447 | # imported one, it is disabled when a suggestion is accepted. |
283 | 391 | pofile, potmsgset = self.factory.makePOFileAndPOTMsgSet( | 448 | pofile = self.factory.makePOFile(side=TranslationSide.UBUNTU) |
284 | 392 | side=TranslationSide.UBUNTU) | 449 | (suggestion, incumbent_message) = self._makeMessages( |
285 | 393 | suggestion = self.factory.makeSuggestion( | 450 | pofile, identical_ubuntu=False) |
286 | 394 | pofile=pofile, potmsgset=potmsgset) | 451 | |
287 | 395 | incumbent_message = self.factory.makeCurrentTranslationMessage( | 452 | suggestion.acceptFromUpstreamImportOnPackage(pofile) |
288 | 396 | pofile=pofile, potmsgset=potmsgset) | 453 | |
289 | 397 | 454 | self.assertEqual( | |
290 | 398 | self.assertTrue(incumbent_message.is_current_ubuntu) | 455 | [(True, True), (False, False)], |
291 | 399 | self.assertFalse(suggestion.is_current_ubuntu) | 456 | self._getStates(suggestion, incumbent_message)) |
292 | 400 | 457 | ||
293 | 401 | suggestion.acceptFromUpstreamImportOnPackage(pofile) | 458 | def test_accept_upstream_no_ubuntu(self): |
294 | 402 | 459 | # If there was already an upstream translation, but no ubuntu | |
295 | 403 | self.assertFalse(incumbent_message.is_current_ubuntu) | 460 | # one, the suggestion replaces both. |
296 | 404 | self.assertTrue(suggestion.is_current_ubuntu) | 461 | pofile = self.factory.makePOFile(side=TranslationSide.UBUNTU) |
297 | 405 | # Messages are always accepted on the other side, too. | 462 | (suggestion, upstream_message) = self._makeMessages( |
298 | 406 | self.assertTrue(suggestion.is_current_upstream) | 463 | pofile, identical_upstream=False) |
299 | 464 | |||
300 | 465 | suggestion.acceptFromUpstreamImportOnPackage(pofile) | ||
301 | 466 | |||
302 | 467 | self.assertEqual( | ||
303 | 468 | [(True, True), (False, False)], | ||
304 | 469 | self._getStates(suggestion, upstream_message)) | ||
305 | 407 | 470 | ||
306 | 408 | def test_accept_previously_imported(self): | 471 | def test_accept_previously_imported(self): |
347 | 409 | # If there was already a current translation, and a previously | 472 | # If there was already an ubuntu translation, and an upstream |
348 | 410 | # imported one, the current translation is left untouched. | 473 | # one, the ubuntu translation is left untouched. |
349 | 411 | pofile, potmsgset = self.factory.makePOFileAndPOTMsgSet( | 474 | pofile = self.factory.makePOFile(side=TranslationSide.UBUNTU) |
350 | 412 | side=TranslationSide.UBUNTU) | 475 | (suggestion, ubuntu_message, upstream_message) = self._makeMessages( |
351 | 413 | imported_message = self.factory.makeCurrentTranslationMessage( | 476 | pofile, identical_ubuntu=False, identical_upstream=False) |
352 | 414 | pofile=pofile, potmsgset=potmsgset, current_other=True) | 477 | |
353 | 415 | imported_message.is_current_ubuntu = False | 478 | suggestion.acceptFromUpstreamImportOnPackage(pofile) |
354 | 416 | 479 | ||
355 | 417 | suggestion = self.factory.makeSuggestion( | 480 | # The suggestion is accepted as the upstream translation. |
356 | 418 | pofile=pofile, potmsgset=potmsgset) | 481 | self.assertEqual( |
357 | 419 | incumbent_message = self.factory.makeCurrentTranslationMessage( | 482 | [(False, True), (True, False), (False, False)], |
358 | 420 | pofile=pofile, potmsgset=potmsgset) | 483 | self._getStates(suggestion, ubuntu_message, upstream_message)) |
359 | 421 | 484 | ||
360 | 422 | self.assertTrue(incumbent_message.is_current_ubuntu) | 485 | def test_accept_previously_imported_tracking(self): |
361 | 423 | self.assertFalse(suggestion.is_current_ubuntu) | 486 | # If there was already an ubuntu translation, and an identical |
362 | 424 | self.assertTrue(imported_message.is_current_upstream) | 487 | # upstream one, the new suggestion replaces both. |
363 | 425 | 488 | pofile = self.factory.makePOFile(side=TranslationSide.UBUNTU) | |
364 | 426 | suggestion.acceptFromUpstreamImportOnPackage(pofile) | 489 | (suggestion, ubuntu_message, upstream_message) = self._makeMessages( |
365 | 427 | 490 | pofile, identical_ubuntu=False, identical_upstream=False, | |
366 | 428 | self.assertTrue(incumbent_message.is_current_ubuntu) | 491 | is_tracking=True) |
367 | 429 | self.assertFalse(suggestion.is_current_ubuntu) | 492 | |
368 | 430 | # Messages are always accepted on the other side, too. | 493 | suggestion.acceptFromUpstreamImportOnPackage(pofile) |
369 | 431 | self.assertFalse(imported_message.is_current_upstream) | 494 | |
370 | 432 | self.assertTrue(suggestion.is_current_upstream) | 495 | self.assertEqual( |
371 | 433 | 496 | [(True, True), (False, False), (False, False)], | |
372 | 434 | def test_accept_current_message(self): | 497 | self._getStates(suggestion, ubuntu_message, upstream_message)) |
373 | 435 | # Accepting a message that's already current does nothing on this | 498 | |
374 | 436 | # side but makes sure the other side's flag is set. | 499 | def test_accept_different_upstream(self): |
375 | 437 | pofile = self.factory.makePOFile(side=TranslationSide.UBUNTU) | 500 | # If there was already an identcal ubuntu translation, and a |
376 | 438 | translation = self.factory.makeCurrentTranslationMessage( | 501 | # different upstream one, the new suggestion will become both. |
377 | 439 | pofile=pofile) | 502 | pofile = self.factory.makePOFile(side=TranslationSide.UBUNTU) |
378 | 440 | self.assertTrue(translation.is_current_ubuntu) | 503 | (suggestion, ubuntu_message, upstream_message) = self._makeMessages( |
379 | 441 | self.assertFalse(translation.is_current_upstream) | 504 | pofile, identical_ubuntu=True, identical_upstream=False) |
380 | 442 | 505 | ||
381 | 443 | translation.acceptFromUpstreamImportOnPackage(pofile) | 506 | suggestion.acceptFromUpstreamImportOnPackage(pofile) |
382 | 444 | 507 | ||
383 | 445 | self.assertTrue(translation.is_current_ubuntu) | 508 | self.assertEqual( |
384 | 446 | self.assertTrue(translation.is_current_upstream) | 509 | [(True, True), (True, True), (False, False)], |
385 | 447 | 510 | self._getStates(suggestion, ubuntu_message, upstream_message)) | |
386 | 448 | def test_accept_current_and_imported_message(self): | 511 | |
387 | 512 | def test_accept_different_ubuntu(self): | ||
388 | 513 | # If there was already an identcal upstream translation, and a | ||
389 | 514 | # different ubuntu one, the ubuntu translation is not touched. | ||
390 | 515 | pofile = self.factory.makePOFile(side=TranslationSide.UBUNTU) | ||
391 | 516 | (suggestion, ubuntu_message, upstream_message) = self._makeMessages( | ||
392 | 517 | pofile, identical_ubuntu=False, identical_upstream=True) | ||
393 | 518 | |||
394 | 519 | suggestion.acceptFromUpstreamImportOnPackage(pofile) | ||
395 | 520 | |||
396 | 521 | self.assertEqual( | ||
397 | 522 | [(False, True), (True, False), (False, True)], | ||
398 | 523 | self._getStates(suggestion, ubuntu_message, upstream_message)) | ||
399 | 524 | |||
400 | 525 | def test_accept_ubuntu_message(self): | ||
401 | 526 | # Accepting a message that's identical to the ubuntu message makes | ||
402 | 527 | # sure that the message also becomes current upstream. | ||
403 | 528 | pofile = self.factory.makePOFile(side=TranslationSide.UBUNTU) | ||
404 | 529 | (suggestion, ubuntu_message) = self._makeMessages( | ||
405 | 530 | pofile, identical_ubuntu=True) | ||
406 | 531 | |||
407 | 532 | suggestion.acceptFromUpstreamImportOnPackage(pofile) | ||
408 | 533 | |||
409 | 534 | self.assertEqual( | ||
410 | 535 | [(True, True), (True, True)], | ||
411 | 536 | self._getStates(suggestion, ubuntu_message)) | ||
412 | 537 | |||
413 | 538 | def test_accept_upstream_message(self): | ||
414 | 539 | # Accepting a message that's identical to the upstream message makes | ||
415 | 540 | # sure that the message also becomes current in ubuntu. | ||
416 | 541 | pofile = self.factory.makePOFile(side=TranslationSide.UBUNTU) | ||
417 | 542 | (suggestion, upstream_message) = self._makeMessages( | ||
418 | 543 | pofile, identical_upstream=True) | ||
419 | 544 | |||
420 | 545 | suggestion.acceptFromUpstreamImportOnPackage(pofile) | ||
421 | 546 | |||
422 | 547 | self.assertEqual( | ||
423 | 548 | [(True, True), (True, True)], | ||
424 | 549 | self._getStates(suggestion, upstream_message)) | ||
425 | 550 | |||
426 | 551 | def test_accept_ubuntu_and_upstream_message(self): | ||
427 | 449 | # Accepting a message that's already current and was also imported | 552 | # Accepting a message that's already current and was also imported |
428 | 450 | # does nothing. | 553 | # does nothing. |
429 | 451 | pofile = self.factory.makePOFile(side=TranslationSide.UBUNTU) | 554 | pofile = self.factory.makePOFile(side=TranslationSide.UBUNTU) |
439 | 452 | translation = self.factory.makeCurrentTranslationMessage( | 555 | (suggestion, ubuntu_message, upstream_message) = self._makeMessages( |
440 | 453 | pofile=pofile, current_other=True) | 556 | pofile, identical_ubuntu=True, identical_upstream=True) |
441 | 454 | self.assertTrue(translation.is_current_ubuntu) | 557 | |
442 | 455 | self.assertTrue(translation.is_current_upstream) | 558 | suggestion.acceptFromUpstreamImportOnPackage(pofile) |
443 | 456 | 559 | ||
444 | 457 | translation.acceptFromUpstreamImportOnPackage(pofile) | 560 | self.assertEqual( |
445 | 458 | 561 | [(True, True), (True, True), (True, True)], | |
446 | 459 | self.assertTrue(translation.is_current_ubuntu) | 562 | self._getStates(suggestion, ubuntu_message, upstream_message)) |
438 | 460 | self.assertTrue(translation.is_current_upstream) | ||
447 | 461 | 563 | ||
448 | 462 | def test_accept_detects_conflict(self): | 564 | def test_accept_detects_conflict(self): |
449 | 463 | pofile = self.factory.makePOFile(side=TranslationSide.UBUNTU) | 565 | pofile = self.factory.makePOFile(side=TranslationSide.UBUNTU) |
454 | 464 | current = self.factory.makeCurrentTranslationMessage(pofile=pofile) | 566 | (suggestion, ubuntu_message) = self._makeMessages( |
455 | 465 | potmsgset = current.potmsgset | 567 | pofile, identical_ubuntu=False) |
452 | 466 | suggestion = self.factory.makeSuggestion( | ||
453 | 467 | pofile=pofile, potmsgset=potmsgset) | ||
456 | 468 | old = datetime.now(UTC) - timedelta(days=1) | 568 | old = datetime.now(UTC) - timedelta(days=1) |
457 | 469 | 569 | ||
458 | 470 | self.assertRaises( | 570 | self.assertRaises( |
459 | 471 | 571 | ||
460 | === modified file 'lib/lp/translations/tests/test_translationpolicy.py' | |||
461 | --- lib/lp/translations/tests/test_translationpolicy.py 2010-11-10 05:04:16 +0000 | |||
462 | +++ lib/lp/translations/tests/test_translationpolicy.py 2011-02-11 14:44:33 +0000 | |||
463 | @@ -379,33 +379,63 @@ | |||
464 | 379 | self.user = self.factory.makePerson() | 379 | self.user = self.factory.makePerson() |
465 | 380 | self.language = self.factory.makeLanguage() | 380 | self.language = self.factory.makeLanguage() |
466 | 381 | 381 | ||
468 | 382 | def _doesPackageShare(self, sourcepackage, from_upstream=False): | 382 | def _doesPackageShare(self, sourcepackage, by_maintainer=False): |
469 | 383 | """Does this `SourcePackage` share with upstream?""" | 383 | """Does this `SourcePackage` share with upstream?""" |
470 | 384 | distro = sourcepackage.distroseries.distribution | 384 | distro = sourcepackage.distroseries.distribution |
471 | 385 | return distro.sharesTranslationsWithOtherSide( | 385 | return distro.sharesTranslationsWithOtherSide( |
472 | 386 | self.user, self.language, sourcepackage=sourcepackage, | 386 | self.user, self.language, sourcepackage=sourcepackage, |
474 | 387 | purportedly_upstream=from_upstream) | 387 | purportedly_upstream=by_maintainer) |
475 | 388 | 388 | ||
476 | 389 | def test_product_always_shares(self): | 389 | def test_product_always_shares(self): |
477 | 390 | product = self.factory.makeProduct() | 390 | product = self.factory.makeProduct() |
478 | 391 | self.assertTrue( | 391 | self.assertTrue( |
479 | 392 | product.sharesTranslationsWithOtherSide(self.user, self.language)) | 392 | product.sharesTranslationsWithOtherSide(self.user, self.language)) |
480 | 393 | 393 | ||
482 | 394 | def test_distribution_shares_only_if_invited(self): | 394 | def _makePackageAndProductSeries(self): |
483 | 395 | package = self.factory.makeSourcePackage() | 395 | package = self.factory.makeSourcePackage() |
484 | 396 | self.factory.makePackagingLink( | 396 | self.factory.makePackagingLink( |
485 | 397 | sourcepackagename=package.sourcepackagename, | 397 | sourcepackagename=package.sourcepackagename, |
486 | 398 | distroseries=package.distroseries) | 398 | distroseries=package.distroseries) |
488 | 399 | product = package.productseries.product | 399 | return (package, package.productseries) |
489 | 400 | |||
490 | 401 | def test_distribution_shares_only_if_invited_with_template(self): | ||
491 | 402 | # With an upstream template, translations will be shared if the | ||
492 | 403 | # product invites edits. | ||
493 | 404 | package, productseries = self._makePackageAndProductSeries() | ||
494 | 405 | product = productseries.product | ||
495 | 406 | self.factory.makePOTemplate(productseries=productseries) | ||
496 | 400 | 407 | ||
497 | 401 | product.translationpermission = TranslationPermission.OPEN | 408 | product.translationpermission = TranslationPermission.OPEN |
498 | 402 | self.assertTrue(self._doesPackageShare(package)) | 409 | self.assertTrue(self._doesPackageShare(package)) |
499 | 403 | product.translationpermission = TranslationPermission.CLOSED | 410 | product.translationpermission = TranslationPermission.CLOSED |
500 | 404 | self.assertFalse(self._doesPackageShare(package)) | 411 | self.assertFalse(self._doesPackageShare(package)) |
501 | 405 | 412 | ||
503 | 406 | def test_unlinked_package_shares_only_upstream_translations(self): | 413 | def test_distribution_shares_not_without_template(self): |
504 | 414 | # Without an upstream template, translations will not be shared | ||
505 | 415 | # if they do not originate from uploads done by the maintainer. | ||
506 | 416 | package, productseries = self._makePackageAndProductSeries() | ||
507 | 417 | product = productseries.product | ||
508 | 418 | |||
509 | 419 | product.translationpermission = TranslationPermission.OPEN | ||
510 | 420 | self.assertFalse(self._doesPackageShare(package)) | ||
511 | 421 | product.translationpermission = TranslationPermission.CLOSED | ||
512 | 422 | self.assertFalse(self._doesPackageShare(package)) | ||
513 | 423 | |||
514 | 424 | def test_distribution_shares_only_by_maintainer_without_template(self): | ||
515 | 425 | # Without an upstream template, translations will be shared | ||
516 | 426 | # if they do originate from uploads done by the maintainer. | ||
517 | 427 | package, productseries = self._makePackageAndProductSeries() | ||
518 | 428 | product = productseries.product | ||
519 | 429 | |||
520 | 430 | product.translationpermission = TranslationPermission.OPEN | ||
521 | 431 | self.assertTrue(self._doesPackageShare(package, by_maintainer=True)) | ||
522 | 432 | product.translationpermission = TranslationPermission.CLOSED | ||
523 | 433 | self.assertTrue(self._doesPackageShare(package, by_maintainer=True)) | ||
524 | 434 | |||
525 | 435 | def test_distribution_shares_only_by_maintainer_without_upstream(self): | ||
526 | 436 | # Without an upstream product series, translations will only be | ||
527 | 437 | # shared if they do originate from uploads done by the maintainer. | ||
528 | 407 | package = self.factory.makeSourcePackage() | 438 | package = self.factory.makeSourcePackage() |
531 | 408 | distro = package.distroseries.distribution | 439 | for by_maintainer in [False, True]: |
530 | 409 | for from_upstream in [False, True]: | ||
532 | 410 | self.assertEqual( | 440 | self.assertEqual( |
534 | 411 | from_upstream, self._doesPackageShare(package, from_upstream)) | 441 | by_maintainer, self._doesPackageShare(package, by_maintainer)) |
535 | 412 | 442 | ||
536 | === modified file 'lib/lp/translations/utilities/tests/test_file_importer.py' | |||
537 | --- lib/lp/translations/utilities/tests/test_file_importer.py 2011-01-24 15:51:18 +0000 | |||
538 | +++ lib/lp/translations/utilities/tests/test_file_importer.py 2011-02-11 14:44:33 +0000 | |||
539 | @@ -11,7 +11,6 @@ | |||
540 | 11 | from zope.component import getUtility | 11 | from zope.component import getUtility |
541 | 12 | from zope.security.proxy import removeSecurityProxy | 12 | from zope.security.proxy import removeSecurityProxy |
542 | 13 | 13 | ||
543 | 14 | from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities | ||
544 | 15 | from canonical.librarian.testing.fake import FakeLibrarian | 14 | from canonical.librarian.testing.fake import FakeLibrarian |
545 | 16 | from canonical.testing import ( | 15 | from canonical.testing import ( |
546 | 17 | LaunchpadZopelessLayer, | 16 | LaunchpadZopelessLayer, |
547 | @@ -21,6 +20,7 @@ | |||
548 | 21 | from lp.testing import TestCaseWithFactory | 20 | from lp.testing import TestCaseWithFactory |
549 | 22 | from lp.translations.enums import TranslationPermission | 21 | from lp.translations.enums import TranslationPermission |
550 | 23 | from lp.translations.interfaces.potemplate import IPOTemplateSet | 22 | from lp.translations.interfaces.potemplate import IPOTemplateSet |
551 | 23 | from lp.translations.interfaces.side import TranslationSide | ||
552 | 24 | from lp.translations.interfaces.translationfileformat import ( | 24 | from lp.translations.interfaces.translationfileformat import ( |
553 | 25 | TranslationFileFormat, | 25 | TranslationFileFormat, |
554 | 26 | ) | 26 | ) |
555 | @@ -582,9 +582,6 @@ | |||
556 | 582 | """Class test for the sharing operation of the FileImporter base class.""" | 582 | """Class test for the sharing operation of the FileImporter base class.""" |
557 | 583 | layer = LaunchpadZopelessLayer | 583 | layer = LaunchpadZopelessLayer |
558 | 584 | 584 | ||
559 | 585 | UPSTREAM = 0 | ||
560 | 586 | UBUNTU = 1 | ||
561 | 587 | |||
562 | 588 | POFILE = dedent("""\ | 585 | POFILE = dedent("""\ |
563 | 589 | msgid "" | 586 | msgid "" |
564 | 590 | msgstr "" | 587 | msgstr "" |
565 | @@ -612,18 +609,15 @@ | |||
566 | 612 | 609 | ||
567 | 613 | def _makeImportEntry(self, side, by_maintainer=False, uploader=None, | 610 | def _makeImportEntry(self, side, by_maintainer=False, uploader=None, |
568 | 614 | no_upstream=False): | 611 | no_upstream=False): |
570 | 615 | if side == self.UPSTREAM: | 612 | if side == TranslationSide.UPSTREAM: |
571 | 616 | potemplate = self.upstream_template | 613 | potemplate = self.upstream_template |
572 | 617 | else: | 614 | else: |
573 | 618 | # Create a template in a source package. | 615 | # Create a template in a source package. |
574 | 619 | ubuntu = getUtility(ILaunchpadCelebrities).ubuntu | ||
575 | 620 | distroseries = self.factory.makeDistroSeries(distribution=ubuntu) | ||
576 | 621 | ubuntu.translation_focus = distroseries | ||
577 | 622 | sourcepackagename = self.factory.makeSourcePackageName() | ||
578 | 623 | potemplate = self.factory.makePOTemplate( | 616 | potemplate = self.factory.makePOTemplate( |
582 | 624 | distroseries=distroseries, | 617 | name=self.upstream_template.name, side=side) |
583 | 625 | sourcepackagename=sourcepackagename, | 618 | distroseries = potemplate.distroseries |
584 | 626 | name=self.upstream_template.name) | 619 | sourcepackagename = potemplate.sourcepackagename |
585 | 620 | distroseries.distribution.translation_focus = distroseries | ||
586 | 627 | if not no_upstream: | 621 | if not no_upstream: |
587 | 628 | # Link the source package to the upstream series to | 622 | # Link the source package to the upstream series to |
588 | 629 | # enable sharing. | 623 | # enable sharing. |
589 | @@ -657,7 +651,7 @@ | |||
590 | 657 | 651 | ||
591 | 658 | def test_makeImportEntry_templates_are_sharing(self): | 652 | def test_makeImportEntry_templates_are_sharing(self): |
592 | 659 | # Sharing between upstream and Ubuntu was set up correctly. | 653 | # Sharing between upstream and Ubuntu was set up correctly. |
594 | 660 | entry = self._makeImportEntry(self.UBUNTU) | 654 | entry = self._makeImportEntry(TranslationSide.UBUNTU) |
595 | 661 | subset = getUtility(IPOTemplateSet).getSharingSubset( | 655 | subset = getUtility(IPOTemplateSet).getSharingSubset( |
596 | 662 | distribution=entry.distroseries.distribution, | 656 | distribution=entry.distroseries.distribution, |
597 | 663 | sourcepackagename=entry.sourcepackagename) | 657 | sourcepackagename=entry.sourcepackagename) |
598 | @@ -667,7 +661,7 @@ | |||
599 | 667 | 661 | ||
600 | 668 | def test_share_with_other_side_upstream(self): | 662 | def test_share_with_other_side_upstream(self): |
601 | 669 | # An upstream queue entry will be shared with ubuntu. | 663 | # An upstream queue entry will be shared with ubuntu. |
603 | 670 | entry = self._makeImportEntry(self.UPSTREAM) | 664 | entry = self._makeImportEntry(TranslationSide.UPSTREAM) |
604 | 671 | importer = POFileImporter( | 665 | importer = POFileImporter( |
605 | 672 | entry, importers[TranslationFileFormat.PO], None) | 666 | entry, importers[TranslationFileFormat.PO], None) |
606 | 673 | self.assertTrue( | 667 | self.assertTrue( |
607 | @@ -676,7 +670,7 @@ | |||
608 | 676 | 670 | ||
609 | 677 | def test_share_with_other_side_ubuntu(self): | 671 | def test_share_with_other_side_ubuntu(self): |
610 | 678 | # An ubuntu queue entry will not be shared with upstream. | 672 | # An ubuntu queue entry will not be shared with upstream. |
612 | 679 | entry = self._makeImportEntry(self.UBUNTU) | 673 | entry = self._makeImportEntry(TranslationSide.UBUNTU) |
613 | 680 | importer = POFileImporter( | 674 | importer = POFileImporter( |
614 | 681 | entry, importers[TranslationFileFormat.PO], None) | 675 | entry, importers[TranslationFileFormat.PO], None) |
615 | 682 | self.assertFalse( | 676 | self.assertFalse( |
616 | @@ -685,7 +679,8 @@ | |||
617 | 685 | 679 | ||
618 | 686 | def test_share_with_other_side_ubuntu_no_upstream(self): | 680 | def test_share_with_other_side_ubuntu_no_upstream(self): |
619 | 687 | # An ubuntu queue entry cannot share with a non-existent upstream. | 681 | # An ubuntu queue entry cannot share with a non-existent upstream. |
621 | 688 | entry = self._makeImportEntry(self.UBUNTU, no_upstream=True) | 682 | entry = self._makeImportEntry( |
622 | 683 | TranslationSide.UBUNTU, no_upstream=True) | ||
623 | 689 | importer = POFileImporter( | 684 | importer = POFileImporter( |
624 | 690 | entry, importers[TranslationFileFormat.PO], None) | 685 | entry, importers[TranslationFileFormat.PO], None) |
625 | 691 | self.assertFalse( | 686 | self.assertFalse( |
626 | @@ -696,9 +691,75 @@ | |||
627 | 696 | # If the uploader in ubuntu has rights on upstream as well, the | 691 | # If the uploader in ubuntu has rights on upstream as well, the |
628 | 697 | # translations are shared. | 692 | # translations are shared. |
629 | 698 | entry = self._makeImportEntry( | 693 | entry = self._makeImportEntry( |
631 | 699 | self.UBUNTU, uploader=self.translator.translator) | 694 | TranslationSide.UBUNTU, uploader=self.translator.translator) |
632 | 700 | importer = POFileImporter( | 695 | importer = POFileImporter( |
633 | 701 | entry, importers[TranslationFileFormat.PO], None) | 696 | entry, importers[TranslationFileFormat.PO], None) |
634 | 702 | self.assertTrue( | 697 | self.assertTrue( |
635 | 703 | importer.share_with_other_side, | 698 | importer.share_with_other_side, |
636 | 704 | "Ubuntu import should share with upstream.") | 699 | "Ubuntu import should share with upstream.") |
637 | 700 | |||
638 | 701 | def test_is_upstream_import_on_sourcepackage_none(self): | ||
639 | 702 | # To do an upstream import on a sourcepackage, three conditions must | ||
640 | 703 | # be met. | ||
641 | 704 | # - It has to be on a sourcepackage. | ||
642 | 705 | # - The by_maintainer flag must be set on the queue entry. | ||
643 | 706 | # - There must be no matching template in the upstream project or | ||
644 | 707 | # even no upstream project at all. | ||
645 | 708 | # This case meets none of them. | ||
646 | 709 | entry = self._makeImportEntry( | ||
647 | 710 | TranslationSide.UPSTREAM, uploader=self.translator.translator) | ||
648 | 711 | importer = POFileImporter( | ||
649 | 712 | entry, importers[TranslationFileFormat.PO], None) | ||
650 | 713 | self.assertFalse(importer.is_upstream_import_on_sourcepackage) | ||
651 | 714 | |||
652 | 715 | def test_is_upstream_import_on_sourcepackage_by_maintainer(self): | ||
653 | 716 | # This entry is by_maintainer. | ||
654 | 717 | entry = self._makeImportEntry( | ||
655 | 718 | TranslationSide.UPSTREAM, by_maintainer=True, | ||
656 | 719 | uploader=self.translator.translator) | ||
657 | 720 | importer = POFileImporter( | ||
658 | 721 | entry, importers[TranslationFileFormat.PO], None) | ||
659 | 722 | self.assertFalse(importer.is_upstream_import_on_sourcepackage) | ||
660 | 723 | |||
661 | 724 | def test_is_upstream_import_on_sourcepackage_upstream_template(self): | ||
662 | 725 | # This entry is for a sourcepackage with an upstream potemplate. | ||
663 | 726 | entry = self._makeImportEntry( | ||
664 | 727 | TranslationSide.UBUNTU, uploader=self.translator.translator) | ||
665 | 728 | importer = POFileImporter( | ||
666 | 729 | entry, importers[TranslationFileFormat.PO], None) | ||
667 | 730 | self.assertFalse(importer.is_upstream_import_on_sourcepackage) | ||
668 | 731 | |||
669 | 732 | def test_is_upstream_import_on_sourcepackage_upstream_any_template(self): | ||
670 | 733 | # Actually any upstream potemplate will disallow upstream imports. | ||
671 | 734 | |||
672 | 735 | # Use _makeImportEntry to create upstream template and packaging | ||
673 | 736 | # link. | ||
674 | 737 | unused_entry = self._makeImportEntry( | ||
675 | 738 | TranslationSide.UBUNTU, uploader=self.translator.translator) | ||
676 | 739 | |||
677 | 740 | sourcepackagename = unused_entry.sourcepackagename | ||
678 | 741 | distroseries = unused_entry.distroseries | ||
679 | 742 | other_potemplate = self.factory.makePOTemplate( | ||
680 | 743 | distroseries=distroseries, sourcepackagename=sourcepackagename) | ||
681 | 744 | |||
682 | 745 | entry = self.factory.makeTranslationImportQueueEntry( | ||
683 | 746 | potemplate=other_potemplate, by_maintainer=True, | ||
684 | 747 | uploader=self.translator.translator, content=self.POFILE) | ||
685 | 748 | entry.potemplate = other_potemplate | ||
686 | 749 | entry.pofile = self.factory.makePOFile(potemplate=other_potemplate) | ||
687 | 750 | transaction.commit() | ||
688 | 751 | |||
689 | 752 | importer = POFileImporter( | ||
690 | 753 | entry, importers[TranslationFileFormat.PO], None) | ||
691 | 754 | |||
692 | 755 | self.assertFalse(importer.is_upstream_import_on_sourcepackage) | ||
693 | 756 | |||
694 | 757 | def test_is_upstream_import_on_sourcepackage_ok(self): | ||
695 | 758 | # This entry qualifies. | ||
696 | 759 | entry = self._makeImportEntry( | ||
697 | 760 | TranslationSide.UBUNTU, by_maintainer=True, no_upstream=True, | ||
698 | 761 | uploader=self.translator.translator) | ||
699 | 762 | importer = POFileImporter( | ||
700 | 763 | entry, importers[TranslationFileFormat.PO], None) | ||
701 | 764 | self.assertTrue(importer.is_upstream_import_on_sourcepackage) | ||
702 | 765 | |||
703 | 705 | 766 | ||
704 | === modified file 'lib/lp/translations/utilities/tests/test_translation_sharing_info.py' | |||
705 | --- lib/lp/translations/utilities/tests/test_translation_sharing_info.py 2011-02-03 18:40:36 +0000 | |||
706 | +++ lib/lp/translations/utilities/tests/test_translation_sharing_info.py 2011-02-11 14:44:33 +0000 | |||
707 | @@ -264,6 +264,27 @@ | |||
708 | 264 | has_upstream_template( | 264 | has_upstream_template( |
709 | 265 | distroseries, sourcepackagename, different_templatename)) | 265 | distroseries, sourcepackagename, different_templatename)) |
710 | 266 | 266 | ||
711 | 267 | def test_has_upstream_template_any_template(self): | ||
712 | 268 | # There is one template on the upstream project, not specifying | ||
713 | 269 | # a template name still indicates that there is a template. | ||
714 | 270 | distroseries, sourcepackagename = self._makeSourcePackage() | ||
715 | 271 | productseries = self._makeUpstreamProductSeries( | ||
716 | 272 | distroseries, sourcepackagename) | ||
717 | 273 | self.factory.makePOTemplate( | ||
718 | 274 | productseries=productseries) | ||
719 | 275 | |||
720 | 276 | self.assertTrue( | ||
721 | 277 | has_upstream_template(distroseries, sourcepackagename)) | ||
722 | 278 | |||
723 | 279 | def test_has_upstream_template_any_template_none(self): | ||
724 | 280 | # There is no template on the upstream project. | ||
725 | 281 | distroseries, sourcepackagename = self._makeSourcePackage() | ||
726 | 282 | productseries = self._makeUpstreamProductSeries( | ||
727 | 283 | distroseries, sourcepackagename) | ||
728 | 284 | |||
729 | 285 | self.assertFalse( | ||
730 | 286 | has_upstream_template(distroseries, sourcepackagename)) | ||
731 | 287 | |||
732 | 267 | def test_has_ubuntu_template_no_sourcepackage(self): | 288 | def test_has_ubuntu_template_no_sourcepackage(self): |
733 | 268 | # There is no Ubuntu source package, so no Ubuntu template can be | 289 | # There is no Ubuntu source package, so no Ubuntu template can be |
734 | 269 | # found. | 290 | # found. |
735 | @@ -308,3 +329,22 @@ | |||
736 | 308 | 329 | ||
737 | 309 | self.assertFalse( | 330 | self.assertFalse( |
738 | 310 | has_ubuntu_template(productseries, different_templatename)) | 331 | has_ubuntu_template(productseries, different_templatename)) |
739 | 332 | |||
740 | 333 | def test_has_ubuntu_template_any_template(self): | ||
741 | 334 | # There is one template on the Ubuntu source package, not specifying | ||
742 | 335 | # a template name still indicates that there is a template. | ||
743 | 336 | distroseries, sourcepackagename = self._makeSourcePackage() | ||
744 | 337 | productseries = self._makeUpstreamProductSeries( | ||
745 | 338 | distroseries, sourcepackagename) | ||
746 | 339 | self.factory.makePOTemplate( | ||
747 | 340 | distroseries=distroseries, sourcepackagename=sourcepackagename) | ||
748 | 341 | |||
749 | 342 | self.assertTrue(has_ubuntu_template(productseries)) | ||
750 | 343 | |||
751 | 344 | def test_has_ubuntu_template_any_template_none(self): | ||
752 | 345 | # There is no template on the Ubuntu source package. | ||
753 | 346 | distroseries, sourcepackagename = self._makeSourcePackage() | ||
754 | 347 | productseries = self._makeUpstreamProductSeries( | ||
755 | 348 | distroseries, sourcepackagename) | ||
756 | 349 | |||
757 | 350 | self.assertFalse(has_ubuntu_template(productseries)) | ||
758 | 311 | 351 | ||
759 | === modified file 'lib/lp/translations/utilities/translation_import.py' | |||
760 | --- lib/lp/translations/utilities/translation_import.py 2011-01-04 17:23:42 +0000 | |||
761 | +++ lib/lp/translations/utilities/translation_import.py 2011-02-11 14:44:33 +0000 | |||
762 | @@ -432,6 +432,23 @@ | |||
763 | 432 | purportedly_upstream=from_upstream) | 432 | purportedly_upstream=from_upstream) |
764 | 433 | 433 | ||
765 | 434 | @cachedproperty | 434 | @cachedproperty |
766 | 435 | def is_upstream_import_on_sourcepackage(self): | ||
767 | 436 | """Use TranslationMessage.acceptFromUpstreamImportOnPackage`.""" | ||
768 | 437 | if self.pofile is None: | ||
769 | 438 | return False | ||
770 | 439 | if not self.translation_import_queue_entry.by_maintainer: | ||
771 | 440 | return False | ||
772 | 441 | if self.translation_import_queue_entry.sourcepackagename is None: | ||
773 | 442 | return False | ||
774 | 443 | distroseries = self.translation_import_queue_entry.distroseries | ||
775 | 444 | sourcepackagename = ( | ||
776 | 445 | self.translation_import_queue_entry.sourcepackagename) | ||
777 | 446 | from lp.translations.utilities.translationsharinginfo import ( | ||
778 | 447 | has_upstream_template) | ||
779 | 448 | return not has_upstream_template( | ||
780 | 449 | distroseries=distroseries, sourcepackagename=sourcepackagename) | ||
781 | 450 | |||
782 | 451 | @cachedproperty | ||
783 | 435 | def translations_are_msgids(self): | 452 | def translations_are_msgids(self): |
784 | 436 | """Are these English strings instead of translations? | 453 | """Are these English strings instead of translations? |
785 | 437 | 454 | ||
786 | @@ -466,12 +483,16 @@ | |||
787 | 466 | message.validation_status = TranslationValidationStatus.OK | 483 | message.validation_status = TranslationValidationStatus.OK |
788 | 467 | return True | 484 | return True |
789 | 468 | 485 | ||
791 | 469 | def _approveMessage(self, potmsgset, message, message_data): | 486 | def _acceptMessage(self, potmsgset, message, message_data): |
792 | 470 | """Try to approve the message, return None on TranslationConflict.""" | 487 | """Try to approve the message, return None on TranslationConflict.""" |
793 | 471 | try: | 488 | try: |
797 | 472 | message.approve( | 489 | if self.is_upstream_import_on_sourcepackage: |
798 | 473 | self.pofile, self.last_translator, | 490 | message.acceptFromUpstreamImportOnPackage( |
799 | 474 | self.share_with_other_side, self.lock_timestamp) | 491 | self.pofile, self.lock_timestamp) |
800 | 492 | else: | ||
801 | 493 | message.acceptFromImport( | ||
802 | 494 | self.pofile, self.share_with_other_side, | ||
803 | 495 | self.lock_timestamp) | ||
804 | 475 | except TranslationConflict: | 496 | except TranslationConflict: |
805 | 476 | self._addConflictError(message_data, potmsgset) | 497 | self._addConflictError(message_data, potmsgset) |
806 | 477 | if self.logger is not None: | 498 | if self.logger is not None: |
807 | @@ -529,7 +550,7 @@ | |||
808 | 529 | validation_ok = self._validateMessage( | 550 | validation_ok = self._validateMessage( |
809 | 530 | potmsgset, new_message, sanitized_translations, message_data) | 551 | potmsgset, new_message, sanitized_translations, message_data) |
810 | 531 | if validation_ok and self.is_editor: | 552 | if validation_ok and self.is_editor: |
812 | 532 | return self._approveMessage(potmsgset, new_message, message_data) | 553 | return self._acceptMessage(potmsgset, new_message, message_data) |
813 | 533 | 554 | ||
814 | 534 | return new_message | 555 | return new_message |
815 | 535 | 556 | ||
816 | 536 | 557 | ||
817 | === modified file 'lib/lp/translations/utilities/translationsharinginfo.py' | |||
818 | --- lib/lp/translations/utilities/translationsharinginfo.py 2011-02-03 18:40:36 +0000 | |||
819 | +++ lib/lp/translations/utilities/translationsharinginfo.py 2011-02-11 14:44:33 +0000 | |||
820 | @@ -161,14 +161,14 @@ | |||
821 | 161 | distroseries, sourcepackagename, templatename)) | 161 | distroseries, sourcepackagename, templatename)) |
822 | 162 | 162 | ||
823 | 163 | 163 | ||
825 | 164 | def has_ubuntu_template(productseries, templatename): | 164 | def has_ubuntu_template(productseries, templatename=None): |
826 | 165 | """Check for existence of ubuntu template.""" | 165 | """Check for existence of ubuntu template.""" |
827 | 166 | result = find_ubuntu_sharing_info( | 166 | result = find_ubuntu_sharing_info( |
828 | 167 | productseries, templatename, template_only=True) | 167 | productseries, templatename, template_only=True) |
829 | 168 | return not result.is_empty() | 168 | return not result.is_empty() |
830 | 169 | 169 | ||
831 | 170 | 170 | ||
833 | 171 | def has_upstream_template(distroseries, sourcepackagename, templatename): | 171 | def has_upstream_template(distroseries, sourcepackagename, templatename=None): |
834 | 172 | """Check for existence of upstream template.""" | 172 | """Check for existence of upstream template.""" |
835 | 173 | result = find_upstream_sharing_info( | 173 | result = find_upstream_sharing_info( |
836 | 174 | distroseries, sourcepackagename, templatename, | 174 | distroseries, sourcepackagename, templatename, |
837 | 175 | 175 | ||
838 | === added file 'scripts/rosetta/upload-translations.py' | |||
839 | --- scripts/rosetta/upload-translations.py 1970-01-01 00:00:00 +0000 | |||
840 | +++ scripts/rosetta/upload-translations.py 2011-02-11 14:44:33 +0000 | |||
841 | @@ -0,0 +1,19 @@ | |||
842 | 1 | #!/usr/bin/python -S | ||
843 | 2 | # | ||
844 | 3 | # Copyright 2009 Canonical Ltd. This software is licensed under the | ||
845 | 4 | # GNU Affero General Public License version 3 (see the file LICENSE). | ||
846 | 5 | # pylint: disable-msg=W0403 | ||
847 | 6 | |||
848 | 7 | """Upload translations to given package.""" | ||
849 | 8 | |||
850 | 9 | __metaclass__ = type | ||
851 | 10 | |||
852 | 11 | import _pythonpath | ||
853 | 12 | |||
854 | 13 | from lp.translations.scripts.upload_translations import ( | ||
855 | 14 | UploadPackageTranslations) | ||
856 | 15 | |||
857 | 16 | |||
858 | 17 | if __name__ == '__main__': | ||
859 | 18 | script = UploadPackageTranslations('upload-translations') | ||
860 | 19 | script.run() |
Hi Ian,
thanks for the approval of the previous branch. I am requesting r-c for this final branch for the same bug, even though it did not have a code review yet just to make you aware of it.
Cheers,
Henning