1import os 2import warnings 3from io import BytesIO 4 5from pytest import mark 6 7from translate.convert import oo2po, po2oo, test_convert 8from translate.storage import po 9 10 11class TestPO2OO: 12 def setup_method(self, method): 13 warnings.resetwarnings() 14 15 def teardown_method(self, method): 16 warnings.resetwarnings() 17 18 def convertoo(self, posource, ootemplate, language="en-US"): 19 """helper to exercise the command line function""" 20 inputfile = BytesIO(posource.encode()) 21 outputfile = BytesIO() 22 templatefile = BytesIO(ootemplate.encode()) 23 assert po2oo.convertoo( 24 inputfile, outputfile, templatefile, targetlanguage=language, timestamp=0 25 ) 26 return outputfile.getvalue() 27 28 def roundtripstring(self, entitystring): 29 oointro, oooutro = ( 30 r"svx source\dialog\numpages.src 0 string RID_SVXPAGE_NUM_OPTIONS STR_BULLET 0 en-US ", 31 " 2002-02-02 02:02:02" + "\r\n", 32 ) 33 oosource = oointro + entitystring + oooutro 34 ooinputfile = BytesIO(oosource.encode()) 35 ooinputfile2 = BytesIO(oosource.encode()) 36 pooutputfile = BytesIO() 37 oo2po.convertoo(ooinputfile, pooutputfile, ooinputfile2, targetlanguage="en-US") 38 posource = pooutputfile.getvalue() 39 poinputfile = BytesIO(posource) 40 ootemplatefile = BytesIO(oosource.encode()) 41 oooutputfile = BytesIO() 42 po2oo.convertoo( 43 poinputfile, oooutputfile, ootemplatefile, targetlanguage="en-US" 44 ) 45 ooresult = oooutputfile.getvalue().decode("utf-8") 46 print( 47 "original oo:\n", 48 oosource, 49 "po version:\n", 50 posource, 51 "output oo:\n", 52 ooresult, 53 ) 54 assert ooresult.startswith(oointro) and ooresult.endswith(oooutro) 55 return ooresult[len(oointro) : -len(oooutro)] 56 57 def check_roundtrip(self, oosource): 58 """Checks that the round-tripped string is the same as the original""" 59 assert self.roundtripstring(oosource) == oosource 60 61 @mark.skipif(os.name == "nt", reason="test or storage broken on Windows") 62 def test_convertoo(self): 63 """checks that the convertoo function is working""" 64 oobase = ( 65 r"svx source\dialog\numpages.src 0 string RID_SVXPAGE_NUM_OPTIONS STR_BULLET 0 %s %s 20050924 09:13:58" 66 + "\r\n" 67 ) 68 posource = """#: numpages.src#RID_SVXPAGE_NUM_OPTIONS.STR_BULLET.string.text\nmsgid "Simple String"\nmsgstr "Dimpled Ring"\n""" 69 ootemplate = oobase % ("en-US", "Simple String") 70 ooexpected = oobase % ("zu", "Dimpled Ring") 71 newoo = self.convertoo(posource, ootemplate, language="zu") 72 assert newoo.decode("utf-8") == ootemplate + ooexpected 73 74 def test_pofilter(self): 75 """Tests integration with pofilter""" 76 # Some bad po with a few errors: 77 posource = b'#: sourcefile.bla#ID_NUMBER.txet.gnirts\nmsgid "<tag cow=\\"3\\">Mistake."\nmsgstr " <etiket koei=\\"3\\">(fout) "' 78 filter = po2oo.filter 79 pofile = po.pofile() 80 pofile.parse(posource) 81 assert not filter.validelement(pofile.units[0], "dummyname.po", "exclude-all") 82 83 def test_roundtrip_simple(self): 84 """checks that simple strings make it through a oo->po->oo roundtrip""" 85 self.check_roundtrip("Hello") 86 self.check_roundtrip('"Hello"') 87 self.check_roundtrip('"Hello Everybody"') 88 89 def test_roundtrip_escape(self): 90 """checks that escapes in strings make it through a oo->po->oo roundtrip""" 91 self.check_roundtrip(r'"Simple Escape \ \n \\ \: \t \r "') 92 self.check_roundtrip(r'"More escapes \\n \\t \\r \\: "') 93 self.check_roundtrip(r'"More escapes \\\n \\\t \\\r \\\: "') 94 self.check_roundtrip(r'"More escapes \\\\n \\\\t \\\\r \\\\: "') 95 self.check_roundtrip(r'"End Line Escape \"') 96 self.check_roundtrip(r'"\\rangle \\langle') 97 self.check_roundtrip(r"\\\\<") 98 self.check_roundtrip(r"\\\<") 99 self.check_roundtrip(r"\\<") 100 self.check_roundtrip(r"\<") 101 102 def test_roundtrip_quotes(self): 103 """checks that (escaped) quotes in strings make it through a oo->po->oo roundtrip""" 104 self.check_roundtrip(r"""'Quote Escape "" '""") 105 self.check_roundtrip(r'''"Single-Quote ' "''') 106 self.check_roundtrip(r'''"Single-Quote Escape \' "''') 107 self.check_roundtrip(r"""'Both Quotes "" '' '""") 108 109 def test_roundtrip_spaces(self): 110 # FIXME: this test fails because the resultant PO file returns as po.isempty since .isblank returns true 111 # which is caused by isblankmsgtr returning True. Its a complete mess which would mean unravelling lots 112 # of yuch in pypo. Until we have time to do that unravelling we're diabling this test. You can reenable 113 # once we've fixed that. 114 """checks that (escaped) quotes in strings make it through a oo->po->oo roundtrip""" 115 self.check_roundtrip(" ") 116 self.check_roundtrip("\u00a0") 117 118 def test_default_timestamp(self): 119 """test to ensure that we revert to the default timestamp""" 120 oointro, oooutro = ( 121 r"svx source\dialog\numpages.src 0 string RID_SVXPAGE_NUM_OPTIONS STR_BULLET 0 en-US Text ", 122 "\r\n", 123 ) 124 posource = """#: numpages.src#RID_SVXPAGE_NUM_OPTIONS.STR_BULLET.string.text\nmsgid "Text"\nmsgstr "Text"\n""" 125 inputfile = BytesIO(posource.encode()) 126 outputfile = BytesIO() 127 templatefile = BytesIO((oointro + "20050924 09:13:58" + oooutro).encode()) 128 assert po2oo.convertoo( 129 inputfile, outputfile, templatefile, targetlanguage="en-US" 130 ) 131 assert ( 132 outputfile.getvalue().decode("utf-8") 133 == oointro + "2002-02-02 02:02:02" + oooutro 134 ) 135 136 def test_escape_conversion(self): 137 """test to ensure that we convert escapes correctly""" 138 oosource = ( 139 r"svx source\dialog\numpages.src 0 string RID_SVXPAGE_NUM_OPTIONS STR_BULLET 0 en-US Column1\tColumn2\r\n 2002-02-02 02:02:02" 140 + "\r\n" 141 ) 142 posource = """#: numpages.src#RID_SVXPAGE_NUM_OPTIONS.STR_BULLET.string.text\nmsgid "Column1\\tColumn2\\r\\n"\nmsgstr "Kolom1\\tKolom2\\r\\n"\n""" 143 inputfile = BytesIO(posource.encode()) 144 outputfile = BytesIO() 145 templatefile = BytesIO(oosource.encode()) 146 assert po2oo.convertoo( 147 inputfile, outputfile, templatefile, targetlanguage="af-ZA" 148 ) 149 assert b"\tKolom1\\tKolom2\\r\\n\t" in outputfile.getvalue() 150 151 def test_helpcontent_escapes(self): 152 """test to ensure that we convert helpcontent escapes correctly""" 153 # Note how this test specifically uses incorrect spacing in the 154 # translation. The extra space before 'hid' and an extra space before 155 # the closing tag should not confuse us. 156 oosource = ( 157 r"helpcontent2 source\text\shared\3dsettings_toolbar.xhp 0 help par_idN1056A 0 en-US \<ahelp hid=\".\"\>The 3D-Settings toolbar controls properties of selected 3D objects.\</ahelp\> 2002-02-02 02:02:02" 158 + "\r\n" 159 ) 160 posource = r"""#: 3dsettings_toolbar.xhp#par_idN1056A.help.text 161msgid "" 162"<ahelp hid=\".\">The 3D-Settings toolbar controls properties of selected 3D " 163"ob jects.</ahelp>" 164msgstr "" 165"<ahelp hid=\".\" >Zeee 3DDDD-Settings toolbar controls properties of selected 3D " 166"objects.</ahelp>" 167""" 168 inputfile = BytesIO(posource.encode()) 169 outputfile = BytesIO() 170 templatefile = BytesIO(oosource.encode()) 171 assert po2oo.convertoo( 172 inputfile, outputfile, templatefile, targetlanguage="af-ZA" 173 ) 174 assert ( 175 br"\<ahelp hid=\".\" \>Zeee 3DDDD-Settings toolbar controls properties of selected 3D objects.\</ahelp\>" 176 in outputfile.getvalue() 177 ) 178 179 def test_helpcontent_escapes2(self): 180 """test to ensure that we convert helpcontent escapes correctly""" 181 oosource = ( 182 r"helpcontent2 source\text\scalc\05\empty_cells.xhp 0 help par_id2629474 0 en-US A1: <empty> 2002-02-02 02:02:02" 183 + "\r\n" 184 ) 185 posource = r"""#: empty_cells.xhp#par_id2629474.help.text 186msgid "A1: <empty>" 187msgstr "Aa1: <empty>" 188""" 189 inputfile = BytesIO(posource.encode()) 190 outputfile = BytesIO() 191 templatefile = BytesIO(oosource.encode()) 192 assert po2oo.convertoo( 193 inputfile, outputfile, templatefile, targetlanguage="af-ZA" 194 ) 195 assert b"Aa1: <empty>" in outputfile.getvalue() 196 197 198class TestPO2OOCommand(test_convert.TestConvertCommand, TestPO2OO): 199 """Tests running actual po2oo commands on files""" 200 201 convertmodule = po2oo 202 203 def test_help(self, capsys): 204 """tests getting help""" 205 options = super().test_help(capsys) 206 options = self.help_check(options, "--source-language=LANG") 207 options = self.help_check(options, "--language=LANG") 208 options = self.help_check(options, "-T, --keeptimestamp") 209 options = self.help_check(options, "--nonrecursiveoutput") 210 options = self.help_check(options, "--nonrecursivetemplate") 211 options = self.help_check(options, "--filteraction") 212 options = self.help_check(options, "--skipsource") 213 options = self.help_check(options, "--threshold=PERCENT") 214 options = self.help_check(options, "--fuzzy") 215 options = self.help_check(options, "--nofuzzy") 216 options = self.help_check(options, "-t TEMPLATE, --template=TEMPLATE") 217 options = self.help_check(options, "--multifile=MULTIFILESTYLE", last=True) 218 219 def convertoo(self, posource, ootemplate, language="en-US"): 220 """helper to exercise the command line function""" 221 self.create_testfile( 222 os.path.join("input", "svx", "source", "dialog.po"), posource 223 ) 224 self.create_testfile("input.oo", ootemplate) 225 self.run_command( 226 "input", 227 "output.oo", 228 template="input.oo", 229 language=language, 230 keeptimestamp=True, 231 ) 232 return self.read_testfile("output.oo") 233