3 from translate
.convert
import po2dtd
4 from translate
.convert
import dtd2po
5 from translate
.convert
import test_convert
6 from translate
.misc
import wStringIO
7 from translate
.storage
import po
8 from translate
.storage
import dtd
13 def setup_method(self
, method
):
14 warnings
.resetwarnings()
16 def teardown_method(self
, method
):
17 warnings
.resetwarnings()
19 def po2dtd(self
, posource
):
20 """helper that converts po source to dtd source without requiring files"""
21 inputfile
= wStringIO
.StringIO(posource
)
22 inputpo
= po
.pofile(inputfile
)
23 convertor
= po2dtd
.po2dtd()
24 outputdtd
= convertor
.convertstore(inputpo
)
27 def merge2dtd(self
, dtdsource
, posource
):
28 """helper that merges po translations to dtd source without requiring files"""
29 inputfile
= wStringIO
.StringIO(posource
)
30 inputpo
= po
.pofile(inputfile
)
31 templatefile
= wStringIO
.StringIO(dtdsource
)
32 templatedtd
= dtd
.dtdfile(templatefile
)
33 convertor
= po2dtd
.redtd(templatedtd
)
34 outputdtd
= convertor
.convertstore(inputpo
)
37 def convertdtd(self
, posource
, dtdtemplate
):
38 """helper to exercise the command line function"""
39 inputfile
= wStringIO
.StringIO(posource
)
40 outputfile
= wStringIO
.StringIO()
41 templatefile
= wStringIO
.StringIO(dtdtemplate
)
42 assert po2dtd
.convertdtd(inputfile
, outputfile
, templatefile
)
43 return outputfile
.getvalue()
45 def roundtripsource(self
, dtdsource
):
46 """converts dtd source to po and back again, returning the resulting source"""
47 dtdinputfile
= wStringIO
.StringIO(dtdsource
)
48 dtdinputfile2
= wStringIO
.StringIO(dtdsource
)
49 pooutputfile
= wStringIO
.StringIO()
50 dtd2po
.convertdtd(dtdinputfile
, pooutputfile
, dtdinputfile2
)
51 posource
= pooutputfile
.getvalue()
52 poinputfile
= wStringIO
.StringIO(posource
)
53 dtdtemplatefile
= wStringIO
.StringIO(dtdsource
)
54 dtdoutputfile
= wStringIO
.StringIO()
55 po2dtd
.convertdtd(poinputfile
, dtdoutputfile
, dtdtemplatefile
)
56 dtdresult
= dtdoutputfile
.getvalue()
57 print "original dtd:\n", dtdsource
, "po version:\n", posource
, "output dtd:\n", dtdresult
60 def roundtripstring(self
, entitystring
):
61 """Just takes the contents of a ENTITY definition (with quotes) and does a roundtrip on that"""
62 dtdintro
, dtdoutro
= '<!ENTITY Test.RoundTrip ', '>\n'
63 dtdsource
= dtdintro
+ entitystring
+ dtdoutro
64 dtdresult
= self
.roundtripsource(dtdsource
)
65 assert dtdresult
.startswith(dtdintro
) and dtdresult
.endswith(dtdoutro
)
66 return dtdresult
[len(dtdintro
):-len(dtdoutro
)]
68 def check_roundtrip(self
, dtdsource
):
69 """Checks that the round-tripped string is the same as the original"""
70 assert self
.roundtripstring(dtdsource
) == dtdsource
72 def test_joinlines(self
):
73 """tests that po lines are joined seamlessly (bug 16)"""
74 multilinepo
= '''#: pref.menuPath\nmsgid ""\n"<span>Tools > Options</"\n"span>"\nmsgstr ""\n'''
75 dtdfile
= self
.po2dtd(multilinepo
)
76 dtdsource
= str(dtdfile
)
77 assert "</span>" in dtdsource
79 def test_escapedstr(self
):
80 """tests that \n in msgstr is escaped correctly in dtd"""
81 multilinepo
= '''#: pref.menuPath\nmsgid "Hello\\nEveryone"\nmsgstr "Good day\\nAll"\n'''
82 dtdfile
= self
.po2dtd(multilinepo
)
83 dtdsource
= str(dtdfile
)
84 assert "Good day\nAll" in dtdsource
86 def test_ampersandwarning(self
):
87 """tests that proper warnings are given if invalid ampersands occur"""
88 simplestring
= '''#: simple.warningtest\nmsgid "Simple String"\nmsgstr "Dimpled &Ring"\n'''
89 warnings
.simplefilter("error")
90 assert test
.raises(Warning, po2dtd
.removeinvalidamps
, "simple.warningtest", "Dimpled &Ring")
92 def test_missingaccesskey(self
):
93 """tests that proper warnings are given if access key is missing"""
94 simplepo
= '''#: simple.label\n#: simple.accesskey\nmsgid "Simple &String"\nmsgstr "Dimpled Ring"\n'''
95 simpledtd
= '''<!ENTITY simple.label "Simple String">\n<!ENTITY simple.accesskey "S">'''
96 warnings
.simplefilter("error")
97 assert test
.raises(Warning, self
.merge2dtd
, simpledtd
, simplepo
)
99 def test_accesskeycase(self
):
100 """tests that access keys come out with the same case as the original, regardless"""
101 simplepo_template
= '''#: simple.label\n#: simple.accesskey\nmsgid "Simple &%s"\nmsgstr "Dimpled &%s"\n'''
102 simpledtd_template
= '''<!ENTITY simple.label "Simple %s">\n<!ENTITY simple.accesskey "%s">'''
103 # we test each combination of label case and accelerator case
104 for srcword
in ("String", "string"):
105 for destword
in ("Ring", "ring"):
106 for srcaccel
, destaccel
in ("SR", "sr"):
107 simplepo
= simplepo_template
% (srcword
, destword
)
108 simpledtd
= simpledtd_template
% (srcword
, srcaccel
)
109 dtdfile
= self
.merge2dtd(simpledtd
, simplepo
)
111 accel
= dtd
.unquotefromdtd(dtdfile
.index
["simple.accesskey"].definition
)
112 assert accel
== destaccel
114 def test_accesskey_types(self
):
115 """tests that we can detect the various styles of accesskey"""
116 simplepo_template
= '''#: simple.%s\n#: simple.%s\nmsgid "&File"\nmsgstr "F&aele"\n'''
117 simpledtd_template
= '''<!ENTITY simple.%s "File">\n<!ENTITY simple.%s "a">'''
118 for label
in ("label", "title"):
119 for accesskey
in ("accesskey", "accessKey", "akey"):
120 simplepo
= simplepo_template
% (label
, accesskey
)
121 simpledtd
= simpledtd_template
% (label
, accesskey
)
122 dtdfile
= self
.merge2dtd(simpledtd
, simplepo
)
124 assert dtd
.unquotefromdtd(dtdfile
.index
["simple.%s" % accesskey
].definition
) == "a"
126 def test_ampersandfix(self
):
127 """tests that invalid ampersands are fixed in the dtd"""
128 simplestring
= '''#: simple.string\nmsgid "Simple String"\nmsgstr "Dimpled &Ring"\n'''
129 dtdfile
= self
.po2dtd(simplestring
)
130 dtdsource
= str(dtdfile
)
131 assert "Dimpled Ring" in dtdsource
133 def test_entities_two(self
):
134 """test the error ouput when we find two entities"""
135 simplestring
= '''#: simple.string second.string\nmsgid "Simple String"\nmsgstr "Dimpled Ring"\n'''
136 dtdfile
= self
.po2dtd(simplestring
)
137 dtdsource
= str(dtdfile
)
138 assert "CONVERSION NOTE - multiple entities" in dtdsource
140 def test_entities(self
):
141 """tests that entities are correctly idnetified in the dtd"""
142 simplestring
= '''#: simple.string\nmsgid "Simple String"\nmsgstr "Dimpled Ring"\n'''
143 dtdfile
= self
.po2dtd(simplestring
)
144 dtdsource
= str(dtdfile
)
145 assert dtdsource
.startswith("<!ENTITY simple.string")
147 def test_comments_translator(self
):
148 """tests for translator comments"""
149 simplestring
= '''# Comment1\n# Comment2\n#: simple.string\nmsgid "Simple String"\nmsgstr "Dimpled Ring"\n'''
150 dtdfile
= self
.po2dtd(simplestring
)
151 dtdsource
= str(dtdfile
)
152 assert dtdsource
.startswith("<!-- Comment1 -->")
154 def test_retains_hashprefix(self
):
155 """tests that hash prefixes in the dtd are retained"""
156 hashpo
= '''#: lang.version\nmsgid "__MOZILLA_LOCALE_VERSION__"\nmsgstr "__MOZILLA_LOCALE_VERSION__"\n'''
157 hashdtd
= '#expand <!ENTITY lang.version "__MOZILLA_LOCALE_VERSION__">\n'
158 dtdfile
= self
.merge2dtd(hashdtd
, hashpo
)
159 regendtd
= str(dtdfile
)
160 assert regendtd
== hashdtd
162 def test_convertdtd(self
):
163 """checks that the convertdtd function is working"""
164 posource
= '''#: simple.label\n#: simple.accesskey\nmsgid "Simple &String"\nmsgstr "Dimpled &Ring"\n'''
165 dtdtemplate
= '''<!ENTITY simple.label "Simple String">\n<!ENTITY simple.accesskey "S">\n'''
166 dtdexpected
= '''<!ENTITY simple.label "Dimpled Ring">\n<!ENTITY simple.accesskey "R">\n'''
167 newdtd
= self
.convertdtd(posource
, dtdtemplate
)
169 assert newdtd
== dtdexpected
171 def test_newlines_escapes(self
):
172 """check that we can handle a \n in the PO file"""
173 posource
= '''#: simple.label\n#: simple.accesskey\nmsgid "A hard coded newline.\\n"\nmsgstr "Hart gekoeerde nuwe lyne\\n"\n'''
174 dtdtemplate
= '<!ENTITY simple.label "A hard coded newline.\n">\n'
175 dtdexpected
= '''<!ENTITY simple.label "Hart gekoeerde nuwe lyne\n">\n'''
176 dtdfile
= self
.merge2dtd(dtdtemplate
, posource
)
178 assert str(dtdfile
) == dtdexpected
180 def test_roundtrip_simple(self
):
181 """checks that simple strings make it through a dtd->po->dtd roundtrip"""
182 self
.check_roundtrip('"Hello"')
183 self
.check_roundtrip('"Hello Everybody"')
185 def test_roundtrip_escape(self
):
186 """checks that escapes in strings make it through a dtd->po->dtd roundtrip"""
187 self
.check_roundtrip(r
'"Simple Escape \ \n \\ \: \t \r "')
188 self
.check_roundtrip(r
'"End Line Escape \"')
190 def test_roundtrip_quotes(self
):
191 """checks that (escaped) quotes in strings make it through a dtd->po->dtd roundtrip"""
192 self
.check_roundtrip(r
"""'Quote Escape "" '""")
193 self
.check_roundtrip(r
'''"Single-Quote ' "''')
194 self
.check_roundtrip(r
'''"Single-Quote Escape \' "''')
195 # NOTE: if both quote marks are present, than ' is converted to '
196 self.check_roundtrip(r"""'Both Quotes "" '' '""")
198 def test_merging_entries_with_spaces_removed(self):
199 """dtd2po removes pretty printed spaces, this tests that we can merge this back into the pretty printed dtd"""
200 posource = '''#: simple.label\nmsgid "First line then
"\n"next lines
."\nmsgstr "Eerste lyne en dan volgende lyne
."\n'''
201 dtdtemplate = '<!ENTITY simple.label "First line then
\n' + \
203 dtdexpected = '<!ENTITY simple.label "Eerste lyne en dan volgende lyne
.">\n'
204 dtdfile = self.merge2dtd(dtdtemplate, posource)
206 assert str(dtdfile) == dtdexpected
208 def test_comments(self):
209 """test that we preserve comments, bug 351"""
210 posource = '''#: name\nmsgid "Text
"\nmsgstr "Teks
"'''
211 dtdtemplate = '''<!ENTITY name "%s">\n<!-- \n\nexample -->\n'''
212 dtdfile = self.merge2dtd(dtdtemplate % "Text
", posource)
214 assert str(dtdfile) == dtdtemplate % "Teks
"
216 class TestPO2DTDCommand(test_convert.TestConvertCommand, TestPO2DTD):
217 """Tests running actual po2dtd commands on files"""
218 convertmodule = po2dtd
219 defaultoptions = {"progress
": "none
"}
220 # TODO: because of having 2 base classes, we need to call all their setup and teardown methods
221 # (otherwise we won't reset the warnings etc)
222 def setup_method(self, method):
223 """call both base classes setup_methods"""
224 test_convert.TestConvertCommand.setup_method(self, method)
225 TestPO2DTD.setup_method(self, method)
226 def teardown_method(self, method):
227 """call both base classes teardown_methods"""
228 test_convert.TestConvertCommand.teardown_method(self, method)
229 TestPO2DTD.teardown_method(self, method)
232 """tests getting help"""
233 options = test_convert.TestConvertCommand.test_help(self)
234 options = self.help_check(options, "-t TEMPLATE
, --template
=TEMPLATE
")
235 options = self.help_check(options, "--fuzzy
")
236 options = self.help_check(options, "--nofuzzy
", last=True)