|
5 | 5 | import unittest |
6 | 6 | from textwrap import dedent |
7 | 7 |
|
8 | | -from test.support.script_helper import assert_python_ok |
| 8 | +from test.support.script_helper import assert_python_ok, assert_python_failure |
9 | 9 | from test.test_tools import skip_if_missing, toolsdir |
10 | | -from test.support import temp_cwd, temp_dir |
| 10 | +from test.support import temp_cwd, temp_dir, unload, change_cwd |
11 | 11 |
|
12 | 12 |
|
13 | 13 | skip_if_missing() |
@@ -243,3 +243,184 @@ def test_files_list(self): |
243 | 243 | self.assertIn(f'msgid "{text1}"', data) |
244 | 244 | self.assertIn(f'msgid "{text2}"', data) |
245 | 245 | self.assertNotIn(text3, data) |
| 246 | + |
| 247 | + |
| 248 | +class Test_msgfmt(unittest.TestCase): |
| 249 | + """Tests for the msgfmt.py tool |
| 250 | + bpo-35335 - bpo-9741 |
| 251 | + """ |
| 252 | + |
| 253 | + script = os.path.join(toolsdir,'i18n', 'msgfmt.py') |
| 254 | + |
| 255 | + # binary images of tiny po files |
| 256 | + # windows end of lines for first one |
| 257 | + file1_fr_po = b'''# French translations for python package.\r |
| 258 | +# Copyright (C) 2018 THE python\'S COPYRIGHT HOLDER\r |
| 259 | +# This file is distributed under the same license as the python package.\r |
| 260 | +# s-ball <[email protected]>, 2018.\r |
| 261 | +#\r |
| 262 | +msgid ""\r |
| 263 | +msgstr ""\r |
| 264 | +"Project-Id-Version: python 3.8\\n"\r |
| 265 | +"Report-Msgid-Bugs-To: \\n"\r |
| 266 | +"POT-Creation-Date: 2018-11-30 23:46+0100\\n"\r |
| 267 | +"PO-Revision-Date: 2018-11-30 23:47+0100\\n"\r |
| 268 | +"Last-Translator: s-ball <[email protected]>\\n"\r |
| 269 | +"Language-Team: French\\n"\r\n"Language: fr\\n"\r |
| 270 | +"MIME-Version: 1.0\\n"\r |
| 271 | +"Content-Type: text/plain; charset=UTF-8\\n"\r |
| 272 | +"Content-Transfer-Encoding: 8bit\\n"\r |
| 273 | +"Plural-Forms: nplurals=2; plural=(n > 1);\\n"\r |
| 274 | +\r |
| 275 | +#: file1.py:6\r |
| 276 | +msgid "Hello!"\r |
| 277 | +msgstr "Bonjour !"\r |
| 278 | +\r |
| 279 | +#: file1.py:7\r |
| 280 | +#, python-brace-format\r |
| 281 | +msgid "{n} horse"\r |
| 282 | +msgid_plural "{n} horses"\r |
| 283 | +msgstr[0] "{n} cheval"\r |
| 284 | +msgstr[1] "{n} chevaux"\r |
| 285 | +''' |
| 286 | + |
| 287 | + # Unix end of file and a non ascii character for second one |
| 288 | + file2_fr_po = rb'''# French translations for python package. |
| 289 | +# Copyright (C) 2018 THE python'S COPYRIGHT HOLDER |
| 290 | +# This file is distributed under the same license as the python package. |
| 291 | +# s-ball <[email protected]>, 2018. |
| 292 | +# |
| 293 | +msgid "" |
| 294 | +msgstr "" |
| 295 | +"Project-Id-Version: python 3.8\n" |
| 296 | +"Report-Msgid-Bugs-To: \n" |
| 297 | +"POT-Creation-Date: 2018-11-30 23:57+0100\n" |
| 298 | +"PO-Revision-Date: 2018-11-30 23:57+0100\n" |
| 299 | +"Last-Translator: s-ball <[email protected]>\n" |
| 300 | +"Language-Team: French\n" |
| 301 | +"Language: fr\n" |
| 302 | +"MIME-Version: 1.0\n" |
| 303 | +"Content-Type: text/plain; charset=UTF-8\n" |
| 304 | +"Content-Transfer-Encoding: 8bit\n" |
| 305 | +"Plural-Forms: nplurals=2; plural=(n > 1);\n" |
| 306 | +
|
| 307 | +#: file2.py:6 |
| 308 | +msgid "It's over." |
| 309 | +msgstr "C'est termin\xc3\xa9." |
| 310 | +
|
| 311 | +#: file2.py:7 |
| 312 | +msgid "Bye..." |
| 313 | +msgstr "Au revoir ..." |
| 314 | +''' |
| 315 | + |
| 316 | + # binary images of corresponding compiled mo files |
| 317 | + file1_fr_mo = b'\xde\x12\x04\x95\x00\x00\x00\x00\x03\x00\x00\x00\x1c' \ |
| 318 | + b'\x00\x00\x004\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' \ |
| 319 | + b'\x00\x00\x00\x00\x00L\x00\x00\x00\x06\x00\x00\x00M' \ |
| 320 | + b'\x00\x00\x00\x14\x00\x00\x00T\x00\x00\x00[\x01\x00' \ |
| 321 | + b'\x00i\x00\x00\x00\t\x00\x00\x00\xc5\x01\x00\x00\x16' \ |
| 322 | + b'\x00\x00\x00\xcf\x01\x00\x00\x00Hello!\x00{n} horse' \ |
| 323 | + b'\x00{n} horses\x00Project-Id-Version: python 3.8\n' \ |
| 324 | + b'Report-Msgid-Bugs-To: \nPOT-Creation-Date: 2018-11-30 ' \ |
| 325 | + b'23:46+0100\nPO-Revision-Date: 2018-11-30 23:47+0100\n'\ |
| 326 | + b'Last-Translator: s-ball <[email protected]>\n' \ |
| 327 | + b'Language-Team: French\nLanguage: fr\nMIME-Version: 1.0' \ |
| 328 | + b'\nContent-Type: text/plain; charset=UTF-8\nContent-' \ |
| 329 | + b'Transfer-Encoding: 8bit\nPlural-Forms: nplurals=2' \ |
| 330 | + b'; plural=(n > 1);\n\x00Bonjour !\x00{n} cheval\x00{n' \ |
| 331 | + b'} chevaux\x00' |
| 332 | + file2_fr_mo = b"\xde\x12\x04\x95\x00\x00\x00\x00\x03\x00\x00\x00" \ |
| 333 | + b"\x1c\x00\x00\x004\x00\x00\x00\x00\x00\x00\x00\x00" \ |
| 334 | + b"\x00\x00\x00\x00\x00\x00\x00L\x00\x00\x00\x06\x00" \ |
| 335 | + b"\x00\x00M\x00\x00\x00\n\x00\x00\x00T\x00\x00\x00[" \ |
| 336 | + b"\x01\x00\x00_\x00\x00\x00\r\x00\x00\x00\xbb\x01" \ |
| 337 | + b"\x00\x00\x0f\x00\x00\x00\xc9\x01\x00\x00\x00Bye.." \ |
| 338 | + b".\x00It's over.\x00Project-Id-Version: python 3.8" \ |
| 339 | + b"\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: 2018" \ |
| 340 | + b"-11-30 23:57+0100\nPO-Revision-Date: 2018-11-30 2" \ |
| 341 | + b"3:57+0100\nLast-Translator: s-ball <s-ball@lapost" \ |
| 342 | + b"e.net>\nLanguage-Team: French\nLanguage: fr\nMIME" \ |
| 343 | + b"-Version: 1.0\nContent-Type: text/plain; charset=" \ |
| 344 | + b"UTF-8\nContent-Transfer-Encoding: 8bit\nPlural-Fo" \ |
| 345 | + b"rms: nplurals=2; plural=(n > 1);\n\x00Au revoir ." \ |
| 346 | + b"..\x00C'est termin\xc3\xa9.\x00" |
| 347 | + |
| 348 | + # image of merging both po files keeping second header |
| 349 | + file12_fr_mo = b"\xde\x12\x04\x95\x00\x00\x00\x00\x05\x00\x00\x00" \ |
| 350 | + b"\x1c\x00\x00\x00D\x00\x00\x00\x00\x00\x00\x00\x00" \ |
| 351 | + b"\x00\x00\x00\x00\x00\x00\x00l\x00\x00\x00\x06\x00" \ |
| 352 | + b"\x00\x00m\x00\x00\x00\x06\x00\x00\x00t\x00\x00\x00" \ |
| 353 | + b"\n\x00\x00\x00{\x00\x00\x00\x14\x00\x00\x00\x86" \ |
| 354 | + b"\x00\x00\x00[\x01\x00\x00\x9b\x00\x00\x00\r\x00" \ |
| 355 | + b"\x00\x00\xf7\x01\x00\x00\t\x00\x00\x00\x05\x02\x00" \ |
| 356 | + b"\x00\x0f\x00\x00\x00\x0f\x02\x00\x00\x16\x00\x00" \ |
| 357 | + b"\x00\x1f\x02\x00\x00\x00Bye...\x00Hello!\x00It's " \ |
| 358 | + b"over.\x00{n} horse\x00{n} horses\x00Project-Id-Ver" \ |
| 359 | + b"sion: python 3.8\nReport-Msgid-Bugs-To: \nPOT-Crea" \ |
| 360 | + b"tion-Date: 2018-11-30 23:57+0100\nPO-Revision-Date" \ |
| 361 | + b": 2018-11-30 23:57+0100\nLast-Translator: s-ball <" \ |
| 362 | + b"[email protected]>\nLanguage-Team: French\nLangua" \ |
| 363 | + b"ge: fr\nMIME-Version: 1.0\nContent-Type: text/plai" \ |
| 364 | + b"n; charset=UTF-8\nContent-Transfer-Encoding: 8bit" \ |
| 365 | + b"\nPlural-Forms: nplurals=2; plural=(n > 1);\n\x00A" \ |
| 366 | + b"u revoir ...\x00Bonjour !\x00C'est termin\xc3\xa9." \ |
| 367 | + b"\x00{n} cheval\x00{n} chevaux\x00" |
| 368 | + def imp(self): |
| 369 | + i18ndir = os.path.join(toolsdir, 'i18n') |
| 370 | + sys.path.append(i18ndir) |
| 371 | + import msgfmt |
| 372 | + sys.path.remove(i18ndir) |
| 373 | + return msgfmt |
| 374 | + |
| 375 | + def test_help(self): |
| 376 | + """Test option -h""" |
| 377 | + rc, stdout, stderr = assert_python_ok(self.script, '-h') |
| 378 | + self.assertEqual(0, rc) |
| 379 | + self.assertTrue(stderr.startswith( |
| 380 | + b'Generate binary message catalog from textual' |
| 381 | + b' translation description.' |
| 382 | + ) |
| 383 | + ) |
| 384 | + |
| 385 | + def test_wrong(self): |
| 386 | + """Test wrong option""" |
| 387 | + rc, stdout, stderr = assert_python_failure(self.script, '-x') |
| 388 | + self.assertEqual(1, rc) |
| 389 | + self.assertTrue(stderr.startswith( |
| 390 | + b'Generate binary message catalog from textual' |
| 391 | + b' translation description.' |
| 392 | + ) |
| 393 | + ) |
| 394 | + |
| 395 | + def test_outputfile(self): |
| 396 | + """Test script with -o option - 1 single file, Windows EOL""" |
| 397 | + with temp_cwd(None): |
| 398 | + with open("file1_fr.po", "wb") as out: |
| 399 | + out.write(self.file1_fr_po) |
| 400 | + assert_python_ok(self.script, '-o', 'file1.mo', 'file1_fr.po') |
| 401 | + with open('file1.mo', 'rb') as fin: |
| 402 | + self.assertEqual(self.file1_fr_mo, fin.read()) |
| 403 | + |
| 404 | + def test_no_outputfile(self): |
| 405 | + """Test script without -o option - 1 single file, Unix EOL""" |
| 406 | + with temp_cwd(None): |
| 407 | + with open("file2_fr.po", "wb") as out: |
| 408 | + out.write(self.file2_fr_po) |
| 409 | + assert_python_ok(self.script, 'file2_fr.po') |
| 410 | + with open('file2_fr.mo', 'rb') as fin: |
| 411 | + self.assertEqual(self.file2_fr_mo, fin.read()) |
| 412 | + |
| 413 | + def test_both_with_outputfile(self): |
| 414 | + """Test script with -o option and 2 input files""" |
| 415 | + # msgfmt.py version 1.2 behaviour is to correctly merge the input |
| 416 | + # files and to keep last entry when same entry occurs in more than |
| 417 | + # one file |
| 418 | + with temp_cwd(None): |
| 419 | + with open("file1_fr.po", "wb") as out: |
| 420 | + out.write(self.file1_fr_po) |
| 421 | + with open("file2_fr.po", "wb") as out: |
| 422 | + out.write(self.file2_fr_po) |
| 423 | + assert_python_ok(self.script, '-o', 'file1.mo', |
| 424 | + 'file1_fr.po', 'file2_fr.po') |
| 425 | + with open('file1.mo', 'rb') as fin: |
| 426 | + self.assertEqual(self.file12_fr_mo, fin.read()) |
0 commit comments