1import sys 2from io import BytesIO 3 4from pytest import importorskip, mark, raises 5 6from translate.misc.multistring import multistring 7from translate.storage import test_po 8 9 10pytestmark = mark.skipif( 11 not sys.platform.startswith("linux"), reason="cpo is only available on Linux" 12) 13 14 15cpo = importorskip("translate.storage.cpo") 16 17 18class TestCPOUnit(test_po.TestPOUnit): 19 UnitClass = cpo.pounit 20 21 def test_plurals(self): 22 """Tests that plurals are handled correctly.""" 23 unit = self.UnitClass("Cow") 24 unit.msgid_plural = ["Cows"] 25 assert isinstance(unit.source, multistring) 26 assert unit.source.strings == ["Cow", "Cows"] 27 assert unit.source == "Cow" 28 29 unit.target = ["Koei", "Koeie"] 30 assert isinstance(unit.target, multistring) 31 assert unit.target.strings == ["Koei", "Koeie"] 32 assert unit.target == "Koei" 33 34 unit.target = {0: "Koei", 3: "Koeie"} 35 assert isinstance(unit.target, multistring) 36 assert unit.target.strings == ["Koei", "Koeie"] 37 assert unit.target == "Koei" 38 39 unit.target = ["Sk\u00ear", "Sk\u00eare"] 40 assert isinstance(unit.target, multistring) 41 assert unit.target.strings == ["Sk\u00ear", "Sk\u00eare"] 42 assert unit.target.strings == ["Sk\u00ear", "Sk\u00eare"] 43 assert unit.target == "Sk\u00ear" 44 45 def test_plural_reduction(self): 46 """checks that reducing the number of plurals supplied works""" 47 unit = self.UnitClass("Tree") 48 unit.msgid_plural = ["Trees"] 49 assert isinstance(unit.source, multistring) 50 assert unit.source.strings == ["Tree", "Trees"] 51 unit.target = multistring(["Boom", "Bome", "Baie Bome"]) 52 assert isinstance(unit.source, multistring) 53 assert unit.target.strings == ["Boom", "Bome", "Baie Bome"] 54 unit.target = multistring(["Boom", "Bome"]) 55 assert unit.target.strings == ["Boom", "Bome"] 56 unit.target = "Boom" 57 # FIXME: currently assigning the target to the same as the first string won't change anything 58 # we need to verify that this is the desired behaviour... 59 assert unit.target.strings[0] == "Boom" 60 unit.target = "Een Boom" 61 assert unit.target.strings == ["Een Boom"] 62 63 def test_notes(self): 64 """tests that the generic notes API works""" 65 unit = self.UnitClass("File") 66 assert unit.getnotes() == "" 67 unit.addnote("Which meaning of file?") 68 assert unit.getnotes("translator") == "Which meaning of file?" 69 assert unit.getnotes("developer") == "" 70 unit.addnote("Verb", origin="programmer") 71 assert unit.getnotes("developer") == "Verb" 72 unit.addnote("Thank you", origin="translator") 73 assert unit.getnotes("translator") == "Which meaning of file?\nThank you" 74 assert unit.getnotes() == "Which meaning of file?\nThank you\nVerb" 75 with raises(ValueError): 76 unit.getnotes("devteam") 77 78 def test_notes_withcomments(self): 79 """tests that when we add notes that look like comments that we treat them properly""" 80 unit = self.UnitClass("File") 81 unit.addnote("# Double commented comment") 82 assert unit.getnotes() == "# Double commented comment" 83 assert not unit.hastypecomment("c-format") 84 85 86class TestCPOFile(test_po.TestPOFile): 87 StoreClass = cpo.pofile 88 89 def test_msgidcomments(self): 90 """checks that we handle msgid comments""" 91 posource = 'msgid "test me"\nmsgstr ""' 92 pofile = self.poparse(posource) 93 thepo = pofile.units[0] 94 thepo.msgidcomment = "first comment" 95 print(pofile) 96 print("Blah", thepo.source) 97 assert thepo.source == "test me" 98 thepo.msgidcomment = "second comment" 99 assert bytes(pofile).count(b"_:") == 1 100 101 @mark.xfail(reason="Were disabled during port of Pypo to cPO - they might work") 102 def test_merge_duplicates_msgctxt(self): 103 """checks that merging duplicates works for msgctxt""" 104 posource = '#: source1\nmsgid "test me"\nmsgstr ""\n\n#: source2\nmsgid "test me"\nmsgstr ""\n' 105 pofile = self.poparse(posource) 106 assert len(pofile.units) == 2 107 pofile.removeduplicates("msgctxt") 108 print(pofile) 109 assert len(pofile.units) == 2 110 assert str(pofile.units[0]).count("source1") == 2 111 assert str(pofile.units[1]).count("source2") == 2 112 113 @mark.xfail(reason="Were disabled during port of Pypo to cPO - they might work") 114 def test_merge_blanks(self): 115 """checks that merging adds msgid_comments to blanks""" 116 posource = ( 117 '#: source1\nmsgid ""\nmsgstr ""\n\n#: source2\nmsgid ""\nmsgstr ""\n' 118 ) 119 pofile = self.poparse(posource) 120 assert len(pofile.units) == 2 121 pofile.removeduplicates("merge") 122 assert len(pofile.units) == 2 123 print(pofile.units[0].msgidcomments) 124 print(pofile.units[1].msgidcomments) 125 assert cpo.unquotefrompo(pofile.units[0].msgidcomments) == "_: source1\n" 126 assert cpo.unquotefrompo(pofile.units[1].msgidcomments) == "_: source2\n" 127 128 @mark.xfail(reason="Were disabled during port of Pypo to cPO - they might work") 129 def test_msgid_comment(self): 130 """checks that when adding msgid_comments we place them on a newline""" 131 posource = '#: source0\nmsgid "Same"\nmsgstr ""\n\n#: source1\nmsgid "Same"\nmsgstr ""\n' 132 pofile = self.poparse(posource) 133 assert len(pofile.units) == 2 134 pofile.removeduplicates("msgid_comment") 135 assert len(pofile.units) == 2 136 assert cpo.unquotefrompo(pofile.units[0].msgidcomments) == "_: source0\n" 137 assert cpo.unquotefrompo(pofile.units[1].msgidcomments) == "_: source1\n" 138 # Now lets check for formating 139 for i in (0, 1): 140 expected = ( 141 """#: source%d\nmsgid ""\n"_: source%d\\n"\n"Same"\nmsgstr ""\n""" 142 % (i, i) 143 ) 144 assert pofile.units[i].__str__() == expected 145 146 @mark.xfail(reason="Were disabled during port of Pypo to cPO - they might work") 147 def test_keep_blanks(self): 148 """checks that keeping keeps blanks and doesn't add msgid_comments""" 149 posource = ( 150 '#: source1\nmsgid ""\nmsgstr ""\n\n#: source2\nmsgid ""\nmsgstr ""\n' 151 ) 152 pofile = self.poparse(posource) 153 assert len(pofile.units) == 2 154 pofile.removeduplicates("keep") 155 assert len(pofile.units) == 2 156 # check we don't add msgidcomments 157 assert cpo.unquotefrompo(pofile.units[0].msgidcomments) == "" 158 assert cpo.unquotefrompo(pofile.units[1].msgidcomments) == "" 159 160 def test_output_str_unicode(self): 161 """checks that we can serialize pofile, unit content is in unicode""" 162 posource = """#: nb\nmsgid "Norwegian Bokmål"\nmsgstr ""\n""" 163 pofile = self.StoreClass(BytesIO(posource.encode("UTF-8")), encoding="UTF-8") 164 assert len(pofile.units) == 1 165 print(bytes(pofile)) 166 thepo = pofile.units[0] 167 # assert bytes(pofile) == posource.encode("UTF-8") 168 # extra test: what if we set the msgid to a unicode? this happens in prop2po etc 169 thepo.source = "Norwegian Bokm\xe5l" 170 # assert str(thepo) == posource.encode("UTF-8") 171 # Now if we set the msgstr to Unicode 172 # this is an escaped half character (1/2) 173 halfstr = b"\xbd ...".decode("latin-1") 174 thepo.target = halfstr 175 # assert halfstr in bytes(pofile).decode("UTF-8") 176 thepo.target = halfstr.encode("UTF-8") 177 178 # assert halfstr.encode("UTF-8") in bytes(pofile) 179 180 def test_posections(self): 181 """checks the content of all the expected sections of a PO message""" 182 posource = '# other comment\n#. automatic comment\n#: source comment\n#, fuzzy\nmsgid "One"\nmsgstr "Een"\n' 183 pofile = self.poparse(posource) 184 print(pofile) 185 assert len(pofile.units) == 1 186 assert bytes(pofile).decode("utf-8") == posource 187 188 def test_multiline_obsolete(self): 189 """Tests for correct output of mulitline obsolete messages""" 190 posource = '#~ msgid ""\n#~ "Old thing\\n"\n#~ "Second old thing"\n#~ msgstr ""\n#~ "Ou ding\\n"\n#~ "Tweede ou ding"\n' 191 pofile = self.poparse(posource) 192 print("Source:\n%s" % posource) 193 print("Output:\n%s" % bytes(pofile)) 194 assert len(pofile.units) == 1 195 assert pofile.units[0].isobsolete() 196 assert not pofile.units[0].istranslatable() 197 assert bytes(pofile).decode("utf-8") == posource 198 199 def test_unassociated_comments(self): 200 """tests behaviour of unassociated comments.""" 201 oldsource = '# old lonesome comment\n\nmsgid "one"\nmsgstr "een"\n' 202 oldfile = self.poparse(oldsource) 203 print("serialize", bytes(oldfile)) 204 assert len(oldfile.units) == 1 205 assert "# old lonesome comment\nmsgid" in bytes(oldfile).decode("utf-8") 206 207 @mark.xfail(reason="removal not working in cPO") 208 def test_remove(self): 209 super().test_remove() 210