| """Tests for the Tools/i18n/msgfmt.py tool.""" |
| |
| import sys |
| import unittest |
| from gettext import GNUTranslations |
| from pathlib import Path |
| |
| from test.support.os_helper import temp_cwd |
| from test.support.script_helper import assert_python_failure, assert_python_ok |
| from test.test_tools import skip_if_missing, toolsdir |
| |
| |
| skip_if_missing('i18n') |
| |
| data_dir = (Path(__file__).parent / 'msgfmt_data').resolve() |
| script_dir = Path(toolsdir) / 'i18n' |
| msgfmt = script_dir / 'msgfmt.py' |
| |
| |
| def compile_messages(po_file, mo_file): |
| assert_python_ok(msgfmt, '-o', mo_file, po_file) |
| |
| |
| class CompilationTest(unittest.TestCase): |
| |
| def test_compilation(self): |
| self.maxDiff = None |
| with temp_cwd(): |
| for po_file in data_dir.glob('*.po'): |
| with self.subTest(po_file=po_file): |
| mo_file = po_file.with_suffix('.mo') |
| with open(mo_file, 'rb') as f: |
| expected = GNUTranslations(f) |
| |
| tmp_mo_file = mo_file.name |
| compile_messages(po_file, tmp_mo_file) |
| with open(tmp_mo_file, 'rb') as f: |
| actual = GNUTranslations(f) |
| |
| self.assertDictEqual(actual._catalog, expected._catalog) |
| |
| def test_po_with_bom(self): |
| with temp_cwd(): |
| Path('bom.po').write_bytes(b'\xef\xbb\xbfmsgid "Python"\nmsgstr "Pioton"\n') |
| |
| res = assert_python_failure(msgfmt, 'bom.po') |
| err = res.err.decode('utf-8') |
| self.assertIn('The file bom.po starts with a UTF-8 BOM', err) |
| |
| def test_invalid_msgid_plural(self): |
| with temp_cwd(): |
| Path('invalid.po').write_text('''\ |
| msgid_plural "plural" |
| msgstr[0] "singular" |
| ''') |
| |
| res = assert_python_failure(msgfmt, 'invalid.po') |
| err = res.err.decode('utf-8') |
| self.assertIn('msgid_plural not preceded by msgid', err) |
| |
| def test_plural_without_msgid_plural(self): |
| with temp_cwd(): |
| Path('invalid.po').write_text('''\ |
| msgid "foo" |
| msgstr[0] "bar" |
| ''') |
| |
| res = assert_python_failure(msgfmt, 'invalid.po') |
| err = res.err.decode('utf-8') |
| self.assertIn('plural without msgid_plural', err) |
| |
| def test_indexed_msgstr_without_msgid_plural(self): |
| with temp_cwd(): |
| Path('invalid.po').write_text('''\ |
| msgid "foo" |
| msgid_plural "foos" |
| msgstr "bar" |
| ''') |
| |
| res = assert_python_failure(msgfmt, 'invalid.po') |
| err = res.err.decode('utf-8') |
| self.assertIn('indexed msgstr required for plural', err) |
| |
| def test_generic_syntax_error(self): |
| with temp_cwd(): |
| Path('invalid.po').write_text('''\ |
| "foo" |
| ''') |
| |
| res = assert_python_failure(msgfmt, 'invalid.po') |
| err = res.err.decode('utf-8') |
| self.assertIn('Syntax error', err) |
| |
| class CLITest(unittest.TestCase): |
| |
| def test_help(self): |
| for option in ('--help', '-h'): |
| res = assert_python_ok(msgfmt, option) |
| err = res.err.decode('utf-8') |
| self.assertIn('Generate binary message catalog from textual translation description.', err) |
| |
| def test_version(self): |
| for option in ('--version', '-V'): |
| res = assert_python_ok(msgfmt, option) |
| out = res.out.decode('utf-8').strip() |
| self.assertEqual('msgfmt.py 1.2', out) |
| |
| def test_invalid_option(self): |
| res = assert_python_failure(msgfmt, '--invalid-option') |
| err = res.err.decode('utf-8') |
| self.assertIn('Generate binary message catalog from textual translation description.', err) |
| self.assertIn('option --invalid-option not recognized', err) |
| |
| def test_no_input_file(self): |
| res = assert_python_ok(msgfmt) |
| err = res.err.decode('utf-8').replace('\r\n', '\n') |
| self.assertIn('No input file given\n' |
| "Try `msgfmt --help' for more information.", err) |
| |
| def test_nonexistent_file(self): |
| assert_python_failure(msgfmt, 'nonexistent.po') |
| |
| |
| def update_catalog_snapshots(): |
| for po_file in data_dir.glob('*.po'): |
| mo_file = po_file.with_suffix('.mo') |
| compile_messages(po_file, mo_file) |
| |
| |
| if __name__ == '__main__': |
| if len(sys.argv) > 1 and sys.argv[1] == '--snapshot-update': |
| update_catalog_snapshots() |
| sys.exit(0) |
| unittest.main() |