Merge lp:~henninge/launchpad/bug-128324 into lp:launchpad

Proposed by Henning Eggers
Status: Merged
Approved by: Henning Eggers
Approved revision: no longer in the source branch.
Merged at revision: not available
Proposed branch: lp:~henninge/launchpad/bug-128324
Merge into: lp:launchpad
Diff against target: 588 lines
8 files modified
lib/lp/testing/factory.py (+2/-4)
lib/lp/translations/doc/potmsgset.txt (+7/-69)
lib/lp/translations/interfaces/potemplate.py (+15/-7)
lib/lp/translations/model/potemplate.py (+14/-6)
lib/lp/translations/tests/test_pofile.py (+48/-12)
lib/lp/translations/tests/test_potmsgset.py (+95/-1)
lib/lp/translations/tests/test_shared_potemplate.py (+11/-38)
lib/lp/translations/tests/test_vpoexport.py (+0/-62)
To merge this branch: bzr merge lp:~henninge/launchpad/bug-128324
Reviewer Review Type Date Requested Status
Jeroen T. Vermeulen (community) Approve
Review via email: mp+13946@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Henning Eggers (henninge) wrote :
Download full text (3.2 KiB)

= Details =
See bug 128324.
This branch only contains half the fix as proposed in the bug. It adds the creation of dummy translations to the creation of POTMsgSets. The question of where the creation of POTMsgSets actually happens lead to some more related changes so that it is best to land this part separately now.

A POTMsgSet is created by POTemplate.createPOTMsgSetFromMsgIDs() whose only call site is in POTemplate.createMessageSetFromText(). This used to create an "unbound" POTMsgSet that is not linked to a POTemplate by a TranslationTemplateItem instance. This had to be done by a subsequent call to setSequence.

Having identified createPOTMsgSetFromMsgIDs as the place where POTMsgSets are born, I thought that might be a good place to put the "create dummy translations for all pofiles that belong to this potemplate". But wait, the POTMsgSet had not yet officially been linked to the POTemplate, so setting translations in its POFile seems premature.

The first obvious solution was to do it in setSequence but that seemed to be too much because that methods gets called a lot when re-importing templates where the order has changed.

So really the question is: Should unbound POTMsgSets exist at all? My answer is a clear: No, there is no point in having them. The logical solution is to set the sequence to 0 in createPOTMsgSetFromMsgIDs which the only production call site for createMessageSetFromText had done anyway.

So it was only the makePOTMsgSet factory method that needed to be adjusted too and any test that depended on this missfeature. Luckily they were few.

== Implementation details ==
I decided to move some tests from the doctest to the unit tests for better coverage. Also, testing POTMsgSet.setTranslationCreditsToTranslated separately does not make sense anymore because the factory method will already call it. So it is now tested as part of the creation test.

One of the call sites for createMessageSetFromText was in the old test_vpoexport.py whose content I could move to test_pofile.py completely, thereby removing this relict.

== Test ==

Run the new tests and those affected by the change. I ran all of lp.translations tests to find out which were affected by the test. (A full ec2 test run has taken place since then, too.)

bin/test -vvt potmsgset.txt -t TestTranslationCredits -t getTranslationRows_sequence -t shared_potemplate

== QA/Demo ==

1. Download an existing potemplate that does not have translator-credits.
2. Add translator-credits to the template and import it again.
3. Filter for untranslated messages in any of the languages that this template has translations in.
4. The translator-credits message should not appear among the untranslated messages.

= Launchpad lint =

Checking for conflicts. and issues in doctests and templates.
Running jslint, xmllint, pyflakes, and pylint.
Using normal rules.

Linting changed files:
  lib/lp/testing/factory.py
  lib/lp/translations/doc/potmsgset.txt
  lib/lp/translations/interfaces/potemplate.py
  lib/lp/translations/model/potemplate.py
  lib/lp/translations/tests/test_pofile.py
  lib/lp/translations/tests/test_potmsgset.py
  lib/lp/translations/tests/test_shared_potemplate.py

== Pyli...

Read more...

Revision history for this message
Henning Eggers (henninge) wrote :

I missed a test...

Directly related:
bin/test -vvt potmsgset.txt -t TestPOTMsgSetTranslationCredits

Indirectly related:
bin/test -vvt TestTranslationCredits -t getTranslationRows_sequence -t shared_potemplate

Revision history for this message
Jeroen T. Vermeulen (jtv) wrote :

Looks good; I particularly like the tech debt payoff component in this branch.

It's not really explicit, but I take it the "half" of the bug that you're not solving here is the one where you mark credits as translated when you create a new POFile. If so, there really ought to be a separate bug about that. Could you see to it?

One nit: _launchpad_credits_text is a really horrible name for a function. The leading underscore isn't needed since it's not in __all__, and the name should start with a verb. Personally I'd call this compose_launchpad_credits_text.

Jeroen

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/testing/factory.py'
--- lib/lp/testing/factory.py 2009-10-23 13:51:40 +0000
+++ lib/lp/testing/factory.py 2009-10-26 15:28:11 +0000
@@ -1566,14 +1566,12 @@
1566 create_sharing=create_sharing)1566 create_sharing=create_sharing)
15671567
1568 def makePOTMsgSet(self, potemplate, singular=None, plural=None,1568 def makePOTMsgSet(self, potemplate, singular=None, plural=None,
1569 context=None, sequence=None):1569 context=None, sequence=0):
1570 """Make a new `POTMsgSet` in the given template."""1570 """Make a new `POTMsgSet` in the given template."""
1571 if singular is None and plural is None:1571 if singular is None and plural is None:
1572 singular = self.getUniqueString()1572 singular = self.getUniqueString()
1573 potmsgset = potemplate.createMessageSetFromText(1573 potmsgset = potemplate.createMessageSetFromText(
1574 singular, plural, context=context)1574 singular, plural, context, sequence)
1575 if sequence is not None:
1576 potmsgset.setSequence(potemplate, sequence)
1577 naked_potmsgset = removeSecurityProxy(potmsgset)1575 naked_potmsgset = removeSecurityProxy(potmsgset)
1578 naked_potmsgset.sync()1576 naked_potmsgset.sync()
1579 return potmsgset1577 return potmsgset
15801578
=== modified file 'lib/lp/translations/doc/potmsgset.txt'
--- lib/lp/translations/doc/potmsgset.txt 2009-10-22 15:51:58 +0000
+++ lib/lp/translations/doc/potmsgset.txt 2009-10-26 15:28:11 +0000
@@ -34,79 +34,17 @@
34is_translation_credit indicates if the POTMsgSet is translation credits. The34is_translation_credit indicates if the POTMsgSet is translation credits. The
35property translation_credit_type contains the type of translation credits.35property translation_credit_type contains the type of translation credits.
3636
37 >>> def print_credits(credits):37 >>> print potmsgset.is_translation_credit
38 ... print credits.is_translation_credit
39 ... print credits.translation_credits_type.title
40
41 >>> print_credits(factory.makePOTMsgSet(potemplate))
42 False38 False
39 >>> print potmsgset.translation_credits_type.title
43 Not a translation credits message40 Not a translation credits message
4441
45 >>> print_credits(factory.makePOTMsgSet(42 >>> credits = factory.makePOTMsgSet(
46 ... potemplate, singular=u'translator-credits'))
47 True
48 Gnome credits message
49
50 >>> print_credits(factory.makePOTMsgSet(
51 ... potemplate, singular=u'translation-credits'))
52 True
53 Gnome credits message
54
55 >>> print_credits(factory.makePOTMsgSet(
56 ... potemplate,
57 ... singular=u'Your emails', context=u'EMAIL OF TRANSLATORS'))
58 True
59 KDE emails credits message
60
61 >>> print_credits(factory.makePOTMsgSet(
62 ... potemplate, singular=u'_: EMAIL OF TRANSLATORS\nYour emails'))
63 True
64 KDE emails credits message
65
66
67== POTMsgSet.setTranslationCreditsToTranslated ==
68
69If a message is a translation credits message, its translations must be set
70to some dummy value so that they are counted as "translated" and don't
71mess up the statistics.
72
73 >>> eo_pofile = factory.makePOFile('eo', potemplate=potemplate)
74 >>> eo_language = eo_pofile.language
75 >>> gnome_credits = factory.makePOTMsgSet(
76 ... potemplate, singular=u'translator-credits')43 ... potemplate, singular=u'translator-credits')
77 >>> current = gnome_credits.getCurrentTranslationMessage(potemplate,44 >>> print credits.is_translation_credit
78 ... eo_language)45 True
79 >>> print current46 >>> print credits.translation_credits_type.title
80 None47 Gnome credits message
81 >>> login("foo.bar@canonical.com")
82 >>> gnome_credits.setTranslationCreditsToTranslated(eo_pofile)
83 >>> current = gnome_credits.getCurrentTranslationMessage(potemplate,
84 ... eo_language)
85 >>> print current.msgstr0.translation
86 This is a dummy translation so that the credits are counted as translated.
87
88An imported translation credits message will already contain a translation
89and is therefore left untouched.
90
91 >>> from zope.security.proxy import removeSecurityProxy
92 >>> sr_pofile = removeSecurityProxy(factory.makePOFile('sr', potemplate=potemplate))
93 >>> sr_language = sr_pofile.language
94 >>> sr_credits = factory.makeTranslationMessage(
95 ... potmsgset=gnome_credits, pofile=sr_pofile, is_imported=True,
96 ... translations=[u"Some translations credits for Serbian."])
97 >>> gnome_credits.setTranslationCreditsToTranslated(sr_pofile)
98 >>> current = gnome_credits.getCurrentTranslationMessage(potemplate,
99 ... sr_language)
100 >>> print current.msgstr0.translation
101 Some translations credits for Serbian.
102
103Normal messages will be left untouched, too.
104
105 >>> potmsgset.setTranslationCreditsToTranslated(sr_language)
106 >>> current = potmsgset.getCurrentTranslationMessage(potemplate,
107 ... sr_pofile)
108 >>> print current
109 None
11048
11149
112== POTMsgSet.normalizeWhitespaces ==50== POTMsgSet.normalizeWhitespaces ==
11351
=== modified file 'lib/lp/translations/interfaces/potemplate.py'
--- lib/lp/translations/interfaces/potemplate.py 2009-10-23 21:50:23 +0000
+++ lib/lp/translations/interfaces/potemplate.py 2009-10-26 15:28:11 +0000
@@ -463,27 +463,35 @@
463 """463 """
464464
465 def createPOTMsgSetFromMsgIDs(msgid_singular, msgid_plural=None,465 def createPOTMsgSetFromMsgIDs(msgid_singular, msgid_plural=None,
466 context=None):466 context=None, sequence=0):
467 """Creates a new template message in the database.467 """Creates a new template message in the database.
468468
469 :param msgid_singular: A reference to a singular msgid.469 :param msgid_singular: A reference to a singular msgid.
470 :param msgid_plural: A reference to a plural msgid. Can be None470 :param msgid_plural: A reference to a plural msgid. Can be None
471 if the message is not a plural message.471 if the message is not a plural message.
472 :param context: A context for the template message differentiating472 :param context: A context for the template message differentiating
473 it from other template messages with exactly the same `msgid`.473 it from other template messages with exactly the same `msgid`.
474 :param sequence: The sequence number of this POTMsgSet within this
475 POTemplate. If 0, it is considered obsolete.
474 :return: The newly created message set.476 :return: The newly created message set.
475 """477 """
476478
477 def createMessageSetFromText(singular_text, plural_text, context=None):479 def createMessageSetFromText(singular_text, plural_text,
480 context=None, sequence=0):
478 """Creates a new template message in the database using strings.481 """Creates a new template message in the database using strings.
479482
480 Similar to createMessageSetFromMessageID, but takes text objects483 Similar to createMessageSetFromMessageID, but takes text objects
481 (unicode or string) along with textual context, rather than a484 (unicode or string) along with textual context, rather than a
482 message IDs.485 message IDs.
483486
484 For non-plural messages, plural_text should be None.487 :param singular_text: The string for the singular msgid.
485488 :param msgid_plural: The string for the plural msgid. Must be None
486 Returns the newly created message set.489 if the message is not a plural message.
490 :param context: A context for the template message differentiating
491 it from other template messages with exactly the same `msgid`.
492 :param sequence: The sequence number of this POTMsgSet within this
493 POTemplate. If 0, it is considered obsolete.
494 :return: The newly created message set.
487 """495 """
488496
489 def getOrCreateSharedPOTMsgSet(singular_text, plural_text, context=None):497 def getOrCreateSharedPOTMsgSet(singular_text, plural_text, context=None):
490498
=== modified file 'lib/lp/translations/model/potemplate.py'
--- lib/lp/translations/model/potemplate.py 2009-10-23 21:50:23 +0000
+++ lib/lp/translations/model/potemplate.py 2009-10-26 15:28:11 +0000
@@ -799,9 +799,9 @@
799 return DummyPOFile(self, language, variant=variant, owner=requester)799 return DummyPOFile(self, language, variant=variant, owner=requester)
800800
801 def createPOTMsgSetFromMsgIDs(self, msgid_singular, msgid_plural=None,801 def createPOTMsgSetFromMsgIDs(self, msgid_singular, msgid_plural=None,
802 context=None):802 context=None, sequence=0):
803 """See `IPOTemplate`."""803 """See `IPOTemplate`."""
804 return POTMsgSet(804 potmsgset = POTMsgSet(
805 context=context,805 context=context,
806 msgid_singular=msgid_singular,806 msgid_singular=msgid_singular,
807 msgid_plural=msgid_plural,807 msgid_plural=msgid_plural,
@@ -812,6 +812,15 @@
812 sourcecomment=None,812 sourcecomment=None,
813 flagscomment=None)813 flagscomment=None)
814814
815 potmsgset.setSequence(self, sequence)
816 if potmsgset.is_translation_credit:
817 for language in self.languages():
818 pofile = self.getPOFileByLang(language.code)
819 if pofile is not None:
820 potmsgset.setTranslationCreditsToTranslated(pofile)
821
822 return potmsgset
823
815 def getOrCreatePOMsgID(self, text):824 def getOrCreatePOMsgID(self, text):
816 """Creates or returns existing POMsgID for given `text`."""825 """Creates or returns existing POMsgID for given `text`."""
817 try:826 try:
@@ -824,7 +833,7 @@
824 return msgid833 return msgid
825834
826 def createMessageSetFromText(self, singular_text, plural_text,835 def createMessageSetFromText(self, singular_text, plural_text,
827 context=None):836 context=None, sequence=0):
828 """See `IPOTemplate`."""837 """See `IPOTemplate`."""
829838
830 msgid_singular = self.getOrCreatePOMsgID(singular_text)839 msgid_singular = self.getOrCreatePOMsgID(singular_text)
@@ -837,7 +846,7 @@
837 " primary msgid and context '%r'" % context)846 " primary msgid and context '%r'" % context)
838847
839 return self.createPOTMsgSetFromMsgIDs(msgid_singular, msgid_plural,848 return self.createPOTMsgSetFromMsgIDs(msgid_singular, msgid_plural,
840 context)849 context, sequence)
841850
842 def getOrCreateSharedPOTMsgSet(self, singular_text, plural_text,851 def getOrCreateSharedPOTMsgSet(self, singular_text, plural_text,
843 context=None):852 context=None):
@@ -851,8 +860,7 @@
851 context, sharing_templates=True)860 context, sharing_templates=True)
852 if potmsgset is None:861 if potmsgset is None:
853 potmsgset = self.createMessageSetFromText(862 potmsgset = self.createMessageSetFromText(
854 singular_text, plural_text, context)863 singular_text, plural_text, context, sequence=0)
855 potmsgset.setSequence(self, 0)
856 return potmsgset864 return potmsgset
857865
858 def importFromQueue(self, entry_to_import, logger=None, txn=None):866 def importFromQueue(self, entry_to_import, logger=None, txn=None):
859867
=== modified file 'lib/lp/translations/tests/test_pofile.py'
--- lib/lp/translations/tests/test_pofile.py 2009-10-20 19:34:26 +0000
+++ lib/lp/translations/tests/test_pofile.py 2009-10-26 15:28:11 +0000
@@ -926,6 +926,14 @@
926 self.credits_potmsgset = self.factory.makePOTMsgSet(926 self.credits_potmsgset = self.factory.makePOTMsgSet(
927 potemplate=self.potemplate, singular=u'translator-credits')927 potemplate=self.potemplate, singular=u'translator-credits')
928928
929 def compose_launchpad_credits_text(self, imported_credits_text):
930 return u"%s\n\nLaunchpad Contributions:\n %s" % (
931 imported_credits_text,
932 "\n ".join(["%s %s" % (person.displayname,
933 canonical_url(person))
934 for person in self.pofile.contributors])
935 )
936
929 def test_prepareTranslationCredits_extending(self):937 def test_prepareTranslationCredits_extending(self):
930 # This test ensures that continuous updates to the translation credits938 # This test ensures that continuous updates to the translation credits
931 # don't result in duplicate entries.939 # don't result in duplicate entries.
@@ -933,10 +941,6 @@
933 person = self.factory.makePerson()941 person = self.factory.makePerson()
934942
935 imported_credits_text = u"Imported Contributor <name@project.org>"943 imported_credits_text = u"Imported Contributor <name@project.org>"
936 launchpad_credits_text = (
937 u"%s\n\nLaunchpad Contributions:\n %s %s" % (
938 imported_credits_text, person.displayname,
939 canonical_url(person)))
940944
941 # Import a translation credits message to 'translator-credits'.945 # Import a translation credits message to 'translator-credits'.
942 self.factory.makeTranslationMessage(946 self.factory.makeTranslationMessage(
@@ -954,7 +958,9 @@
954 # The first translation credits export.958 # The first translation credits export.
955 credits_text = self.pofile.prepareTranslationCredits(959 credits_text = self.pofile.prepareTranslationCredits(
956 self.credits_potmsgset)960 self.credits_potmsgset)
957 self.assertEquals(launchpad_credits_text, credits_text)961 self.assertEquals(
962 self.compose_launchpad_credits_text(imported_credits_text),
963 credits_text)
958964
959 # Now, re-import this generated message.965 # Now, re-import this generated message.
960 self.factory.makeTranslationMessage(966 self.factory.makeTranslationMessage(
@@ -965,7 +971,9 @@
965971
966 credits_text = self.pofile.prepareTranslationCredits(972 credits_text = self.pofile.prepareTranslationCredits(
967 self.credits_potmsgset)973 self.credits_potmsgset)
968 self.assertEquals(launchpad_credits_text, credits_text)974 self.assertEquals(
975 self.compose_launchpad_credits_text(imported_credits_text),
976 credits_text)
969977
970978
971class TestTranslationPOFilePOTMsgSetOrdering(TestCaseWithFactory):979class TestTranslationPOFilePOTMsgSetOrdering(TestCaseWithFactory):
@@ -1487,21 +1495,49 @@
14871495
1488 layer = ZopelessDatabaseLayer1496 layer = ZopelessDatabaseLayer
14891497
1498 # The sequence number 0 is put at the beginning of the data to verify that
1499 # it really gets sorted to the end.
1500 TEST_MESSAGES = [
1501 {'msgid':'computer', 'string':'komputilo', 'sequence':0},
1502 {'msgid':'mouse', 'string':'muso', 'sequence':0},
1503 {'msgid':'Good morning', 'string':'Bonan matenon', 'sequence':2},
1504 {'msgid':'Thank you', 'string':'Dankon', 'sequence':1},
1505 ]
1506 EXPECTED_SEQUENCE = [1, 2, 0, 0]
1507
1490 def setUp(self):1508 def setUp(self):
1491 # Create a POFile to calculate statistics on.1509 # Create a POFile to calculate statistics on.
1492 super(TestPOFile, self).setUp()1510 super(TestPOFile, self).setUp()
1493 self.pofile = self.factory.makePOFile('sr')1511 self.pofile = self.factory.makePOFile('eo')
1494 self.potemplate = self.pofile.potemplate1512 self.potemplate = self.pofile.potemplate
14951513
1496 # Create a single POTMsgSet that is used across all tests.
1497 self.potmsgset = self.factory.makePOTMsgSet(self.potemplate,
1498 sequence=1)
1499
1500 def test_makeTranslatableMessage(self):1514 def test_makeTranslatableMessage(self):
1501 # TranslatableMessages can be created from the PO file1515 # TranslatableMessages can be created from the PO file
1502 message = self.pofile.makeTranslatableMessage(self.potmsgset)1516 potmsgset = self.factory.makePOTMsgSet(self.potemplate,
1517 sequence=1)
1518 message = self.pofile.makeTranslatableMessage(potmsgset)
1503 verifyObject(ITranslatableMessage, message)1519 verifyObject(ITranslatableMessage, message)
15041520
1521 def _createMessageSet(self, testmsg):
1522 # Create a message set from the test data.
1523 pomsgset = self.factory.makePOTMsgSet(
1524 self.potemplate, testmsg['msgid'], sequence=testmsg['sequence'])
1525 pomsgset.updateTranslation(
1526 self.pofile, self.pofile.owner,
1527 {0:testmsg['string'],},
1528 True, None, force_edition_rights=True)
1529
1530 def test_getTranslationRows_sequence(self):
1531 # Test for correct sorting of obsolete messages (where sequence=0).
1532 msgsets = [
1533 self._createMessageSet(msg) for msg in self.TEST_MESSAGES]
1534 for rownum, row in enumerate(
1535 self.pofile.getTranslationRows()):
1536 self.failUnlessEqual(
1537 row.sequence, self.EXPECTED_SEQUENCE[rownum],
1538 "getTranslationRows does not sort obsolete messages "
1539 "(sequence=0) to the end of the file.")
1540
15051541
1506def test_suite():1542def test_suite():
1507 return unittest.TestLoader().loadTestsFromName(__name__)1543 return unittest.TestLoader().loadTestsFromName(__name__)
15081544
=== modified file 'lib/lp/translations/tests/test_potmsgset.py'
--- lib/lp/translations/tests/test_potmsgset.py 2009-08-26 16:24:02 +0000
+++ lib/lp/translations/tests/test_potmsgset.py 2009-10-26 15:28:11 +0000
@@ -20,7 +20,7 @@
20from lp.registry.interfaces.person import IPersonSet20from lp.registry.interfaces.person import IPersonSet
21from lp.services.worlddata.interfaces.language import ILanguageSet21from lp.services.worlddata.interfaces.language import ILanguageSet
22from lp.translations.interfaces.potmsgset import (22from lp.translations.interfaces.potmsgset import (
23 POTMsgSetInIncompatibleTemplatesError)23 POTMsgSetInIncompatibleTemplatesError, TranslationCreditsType)
24from lp.translations.interfaces.translationfileformat import (24from lp.translations.interfaces.translationfileformat import (
25 TranslationFileFormat)25 TranslationFileFormat)
26from lp.translations.interfaces.translationmessage import TranslationConflict26from lp.translations.interfaces.translationmessage import TranslationConflict
@@ -1078,5 +1078,99 @@
1078 self.assertFalse(tm2.is_imported)1078 self.assertFalse(tm2.is_imported)
10791079
10801080
1081class TestPOTMsgSetTranslationCredits(TestCaseWithFactory):
1082 """Test methods related to TranslationCredits."""
1083
1084 layer = ZopelessDatabaseLayer
1085
1086 def setUp(self):
1087 super(TestPOTMsgSetTranslationCredits, self).setUp()
1088 self.potemplate = self.factory.makePOTemplate()
1089
1090 def test_creation_credits(self):
1091 # Upon creation of a translation credits message,
1092 # dummy translations are inserted for each POFile.
1093 eo_pofile = self.factory.makePOFile('eo', potemplate=self.potemplate)
1094 sr_pofile = self.factory.makePOFile('sr', potemplate=self.potemplate)
1095
1096 credits = self.factory.makePOTMsgSet(
1097 self.potemplate, u'translator-credits', sequence=1)
1098
1099 eo_translation = credits.getCurrentTranslationMessage(
1100 self.potemplate, eo_pofile.language)
1101 self.assertIsNot(None, eo_translation,
1102 "Translation credits are not translated upon creation.")
1103
1104 sr_translation = credits.getCurrentTranslationMessage(
1105 self.potemplate, sr_pofile.language)
1106 self.assertIsNot(None, sr_translation,
1107 "Translation credits are not translated upon "
1108 "creation in 2nd POFile.")
1109
1110 def test_creation_not_translated(self):
1111 # Normal messages do not receive a dummy translation.
1112 eo_pofile = self.factory.makePOFile('eo', potemplate=self.potemplate)
1113
1114 potmsgset = self.factory.makePOTMsgSet(self.potemplate, sequence=1)
1115 eo_translation = potmsgset.getCurrentTranslationMessage(
1116 self.potemplate, eo_pofile.language)
1117 self.assertIs(None, eo_translation)
1118
1119 def test_creation_not_imported(self):
1120 # Dummy translation for translation credits are not created as
1121 # imported and can therefore be overwritten by later imports.
1122 eo_pofile = self.factory.makePOFile('eo', potemplate=self.potemplate)
1123 imported_credits = u'Imported credits.'
1124
1125 credits = self.factory.makePOTMsgSet(
1126 self.potemplate, u'translator-credits', sequence=1)
1127 translation = self.factory.makeTranslationMessage(eo_pofile, credits,
1128 translations=[imported_credits], is_imported=True)
1129
1130 eo_translation = credits.getCurrentTranslationMessage(
1131 self.potemplate, eo_pofile.language)
1132 self.assertEqual(imported_credits, eo_translation.msgstr0.translation,
1133 "Imported translation credits do not replace dummy credits.")
1134
1135 def test_translation_credits_gnome(self):
1136 # Detect all known variations of Gnome translator credits.
1137 gnome_credits = [
1138 u'translator-credits',
1139 u'translator_credits',
1140 u'translation-credits',
1141 ]
1142 for sequence, credits_string in enumerate(gnome_credits):
1143 credits = self.factory.makePOTMsgSet(
1144 self.potemplate, credits_string, sequence=sequence+1)
1145 self.assertTrue(credits.is_translation_credit)
1146 self.assertEqual(TranslationCreditsType.GNOME,
1147 credits.translation_credits_type)
1148
1149 def test_translation_credits_kde(self):
1150 # Detect all known variations of KDE translator credits.
1151 kde_credits = [
1152 (u'Your emails', u'EMAIL OF TRANSLATORS',
1153 TranslationCreditsType.KDE_EMAILS),
1154 (u'Your names', u'NAME OF TRANSLATORS',
1155 TranslationCreditsType.KDE_NAMES),
1156 ]
1157 sequence = 0
1158 for credits_string, context, credits_type in kde_credits:
1159 sequence += 1
1160 credits = self.factory.makePOTMsgSet(
1161 self.potemplate, credits_string,
1162 context=context, sequence=sequence)
1163 self.assertTrue(credits.is_translation_credit)
1164 self.assertEqual(credits_type, credits.translation_credits_type)
1165
1166 # Old KDE style.
1167 sequence += 1
1168 credits = self.factory.makePOTMsgSet(
1169 self.potemplate, u'_: %s\n%s' % (context, credits_string),
1170 sequence=sequence)
1171 self.assertTrue(credits.is_translation_credit)
1172 self.assertEqual(credits_type, credits.translation_credits_type)
1173
1174
1081def test_suite():1175def test_suite():
1082 return unittest.TestLoader().loadTestsFromName(__name__)1176 return unittest.TestLoader().loadTestsFromName(__name__)
10831177
=== modified file 'lib/lp/translations/tests/test_shared_potemplate.py'
--- lib/lp/translations/tests/test_shared_potemplate.py 2009-07-17 00:26:05 +0000
+++ lib/lp/translations/tests/test_shared_potemplate.py 2009-10-26 15:28:11 +0000
@@ -53,32 +53,20 @@
5353
54 def test_getPOTMsgSetByMsgIDText(self):54 def test_getPOTMsgSetByMsgIDText(self):
55 potmsgset = self.factory.makePOTMsgSet(self.devel_potemplate,55 potmsgset = self.factory.makePOTMsgSet(self.devel_potemplate,
56 singular="Open file")56 singular="Open file",
5757 sequence=2)
58 # It's still not present in the PO template.58
59 read_potmsgset = self.devel_potemplate.getPOTMsgSetByMsgIDText(59 # We can retrieve the potmsgset by its ID text.
60 "Open file")
61 self.assertEquals(read_potmsgset, None)
62
63 # To actually insert it into a POTemplate, it needs
64 # a sequence to be set.
65 potmsgset.setSequence(self.devel_potemplate, 2)
66 read_potmsgset = self.devel_potemplate.getPOTMsgSetByMsgIDText(60 read_potmsgset = self.devel_potemplate.getPOTMsgSetByMsgIDText(
67 "Open file")61 "Open file")
68 self.assertEquals(potmsgset, read_potmsgset)62 self.assertEquals(potmsgset, read_potmsgset)
6963
70 def test_getPOTMsgSetBySequence(self):64 def test_getPOTMsgSetBySequence(self):
71 potmsgset = self.factory.makePOTMsgSet(self.devel_potemplate)
72 sequence = self.factory.getUniqueInteger()65 sequence = self.factory.getUniqueInteger()
7366 potmsgset = self.factory.makePOTMsgSet(self.devel_potemplate,
74 # It's still not present in the PO template.67 sequence=sequence)
75 read_potmsgset = self.devel_potemplate.getPOTMsgSetBySequence(68
76 sequence)69 # We can retrieve the potmsgset by its sequence.
77 self.assertEquals(read_potmsgset, None)
78
79 # Now we set the appropriate sequence in a potemplate and see that
80 # it works.
81 potmsgset.setSequence(self.devel_potemplate, sequence)
82 read_potmsgset = self.devel_potemplate.getPOTMsgSetBySequence(70 read_potmsgset = self.devel_potemplate.getPOTMsgSetBySequence(
83 sequence)71 sequence)
84 self.assertEquals(potmsgset, read_potmsgset)72 self.assertEquals(potmsgset, read_potmsgset)
@@ -89,16 +77,11 @@
89 self.assertEquals(read_potmsgset, None)77 self.assertEquals(read_potmsgset, None)
9078
91 def test_getPOTMsgSetByID(self):79 def test_getPOTMsgSetByID(self):
92 potmsgset = self.factory.makePOTMsgSet(self.devel_potemplate)80 potmsgset = self.factory.makePOTMsgSet(self.devel_potemplate,
81 sequence=3)
93 id = potmsgset.id82 id = potmsgset.id
9483
95 # It's still not present in the PO template.84 # We can retrieve the potmsgset by its ID.
96 read_potmsgset = self.devel_potemplate.getPOTMsgSetByID(id)
97 self.assertEquals(read_potmsgset, None)
98
99 # Now we set the appropriate sequence in a potemplate and see that
100 # we can get it by ID.
101 potmsgset.setSequence(self.devel_potemplate, 3)
102 read_potmsgset = self.devel_potemplate.getPOTMsgSetByID(id)85 read_potmsgset = self.devel_potemplate.getPOTMsgSetByID(id)
103 self.assertEquals(potmsgset, read_potmsgset)86 self.assertEquals(potmsgset, read_potmsgset)
10487
@@ -122,16 +105,6 @@
122 present_msgid_singular, present_msgid_plural, present_context)105 present_msgid_singular, present_msgid_plural, present_context)
123 self.assertEquals(has_message_id, True)106 self.assertEquals(has_message_id, True)
124107
125 # A new POTMsgSet that is not part of the POTemplate cannot
126 # be gotten using hasMessageID on a POTemplate.
127 absent_potmsgset = self.factory.makePOTMsgSet(self.devel_potemplate)
128 absent_msgid_singular = absent_potmsgset.msgid_singular
129 absent_msgid_plural = absent_potmsgset.msgid_plural
130 absent_context = absent_potmsgset.msgid_plural
131 has_message_id = naked_potemplate.hasMessageID(
132 absent_msgid_singular, absent_msgid_plural, absent_context)
133 self.assertEquals(has_message_id, False)
134
135 def test_hasPluralMessage(self):108 def test_hasPluralMessage(self):
136 naked_potemplate = removeSecurityProxy(self.devel_potemplate)109 naked_potemplate = removeSecurityProxy(self.devel_potemplate)
137110
138111
=== removed file 'lib/lp/translations/tests/test_vpoexport.py'
--- lib/lp/translations/tests/test_vpoexport.py 2009-07-22 11:52:40 +0000
+++ lib/lp/translations/tests/test_vpoexport.py 1970-01-01 00:00:00 +0000
@@ -1,62 +0,0 @@
1# Copyright 2009 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).
3
4"""PO file export view tests."""
5
6__metaclass__ = type
7
8import unittest
9import transaction
10
11from lp.testing.factory import LaunchpadObjectFactory
12from canonical.testing import LaunchpadZopelessLayer
13
14# The sequence number 0 is put at the beginning of the data to verify that
15# it really gets sorted to the end.
16TEST_MESSAGES = [
17 {'msgid':'computer', 'string':'komputilo', 'sequence':0},
18 {'msgid':'mouse', 'string':'muso', 'sequence':0},
19 {'msgid':'Good morning', 'string':'Bonan matenon', 'sequence':2},
20 {'msgid':'Thank you', 'string':'Dankon', 'sequence':1},
21 ]
22EXPECTED_SEQUENCE = [1, 2, 0, 0]
23
24class VPOExportSetTestCase(unittest.TestCase):
25 """Test the PO file export view."""
26 layer = LaunchpadZopelessLayer
27
28 def _createMessageSet(self, testmsg):
29 # Create a message set from the test data.
30 msgset = self.potemplate.createMessageSetFromText(
31 testmsg['msgid'], None)
32 msgset.setSequence(self.potemplate, testmsg['sequence'])
33 msgset.updateTranslation(
34 self.pofile, self.submitter_person,
35 {0:testmsg['string'],},
36 True, None, force_edition_rights=True)
37
38 def setUp(self):
39 factory = LaunchpadObjectFactory()
40
41 # Create a PO file and fill with test data.
42 self.potemplate = factory.makePOTemplate()
43 self.pofile = factory.makePOFile('eo', self.potemplate)
44 self.submitter_person = factory.makePerson()
45 self.msgsets = [
46 self._createMessageSet(msg) for msg in TEST_MESSAGES]
47
48 transaction.commit()
49
50 def test_getTranslationRows_sequence(self):
51 # Test for correct sorting of obsolete messages (where sequence=0).
52 for rownum, row in enumerate(
53 self.pofile.getTranslationRows()):
54 self.failUnlessEqual(
55 row.sequence, EXPECTED_SEQUENCE[rownum],
56 "VPOExportSet does not sort obsolete messages (sequence=0) "
57 "to the end of the file.")
58
59def test_suite():
60 suite = unittest.TestSuite()
61 suite.addTest(unittest.makeSuite(VPOExportSetTestCase))
62 return suite