]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.13] gh-127488: Add tests for Tools/i18n/msgfmt.py (GH-127540) (GH-130182)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Sun, 16 Feb 2025 13:20:49 +0000 (14:20 +0100)
committerGitHub <noreply@github.com>
Sun, 16 Feb 2025 13:20:49 +0000 (13:20 +0000)
(cherry picked from commit 361083b84b0db975058b2d1f50dcbfd36f072caf)

Co-authored-by: Tomas R <tomas.roun8@gmail.com>
Lib/test/test_tools/msgfmt_data/fuzzy.mo [new file with mode: 0644]
Lib/test/test_tools/msgfmt_data/fuzzy.po [new file with mode: 0644]
Lib/test/test_tools/msgfmt_data/general.mo [new file with mode: 0644]
Lib/test/test_tools/msgfmt_data/general.po [new file with mode: 0644]
Lib/test/test_tools/test_msgfmt.py [new file with mode: 0644]
Makefile.pre.in

diff --git a/Lib/test/test_tools/msgfmt_data/fuzzy.mo b/Lib/test/test_tools/msgfmt_data/fuzzy.mo
new file mode 100644 (file)
index 0000000..4b14483
Binary files /dev/null and b/Lib/test/test_tools/msgfmt_data/fuzzy.mo differ
diff --git a/Lib/test/test_tools/msgfmt_data/fuzzy.po b/Lib/test/test_tools/msgfmt_data/fuzzy.po
new file mode 100644 (file)
index 0000000..05e8354
--- /dev/null
@@ -0,0 +1,23 @@
+# Fuzzy translations are not written to the .mo file.
+#, fuzzy
+msgid "foo"
+msgstr "bar"
+
+# comment
+#, fuzzy
+msgctxt "abc"
+msgid "foo"
+msgstr "bar"
+
+#, fuzzy
+# comment
+msgctxt "xyz"
+msgid "foo"
+msgstr "bar"
+
+#, fuzzy
+msgctxt "abc"
+msgid "One email sent."
+msgid_plural "%d emails sent."
+msgstr[0] "One email sent."
+msgstr[1] "%d emails sent."
diff --git a/Lib/test/test_tools/msgfmt_data/general.mo b/Lib/test/test_tools/msgfmt_data/general.mo
new file mode 100644 (file)
index 0000000..bc0683a
Binary files /dev/null and b/Lib/test/test_tools/msgfmt_data/general.mo differ
diff --git a/Lib/test/test_tools/msgfmt_data/general.po b/Lib/test/test_tools/msgfmt_data/general.po
new file mode 100644 (file)
index 0000000..8f84042
--- /dev/null
@@ -0,0 +1,47 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2024-10-26 18:06+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "foo"
+msgstr ""
+
+msgid "bar"
+msgstr "baz"
+
+msgctxt "abc"
+msgid "foo"
+msgstr "bar"
+
+# comment
+msgctxt "xyz"
+msgid "foo"
+msgstr "bar"
+
+msgid "Multiline"
+"string"
+msgstr "Multiline"
+"translation"
+
+msgid "\"escapes\""
+msgstr "\"translated\""
+
+msgid "\n newlines \n"
+msgstr "\n translated \n"
+
+msgid "One email sent."
+msgid_plural "%d emails sent."
+msgstr[0] "One email sent."
+msgstr[1] "%d emails sent."
+
+msgctxt "abc"
+msgid "One email sent."
+msgid_plural "%d emails sent."
+msgstr[0] "One email sent."
+msgstr[1] "%d emails sent."
diff --git a/Lib/test/test_tools/test_msgfmt.py b/Lib/test/test_tools/test_msgfmt.py
new file mode 100644 (file)
index 0000000..e3e3035
--- /dev/null
@@ -0,0 +1,126 @@
+"""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_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()
index 46a37ded9705734a5bf3f292c6bbfe7a5d843250..ae1538c211f6437045a7b7de42d20a1a6f3a29b2 100644 (file)
@@ -2459,6 +2459,7 @@ TESTSUBDIRS=      idlelib/idle_test \
                test/test_tomllib/data/valid/multiline-basic-str \
                test/test_tools \
                test/test_tools/i18n_data \
+               test/test_tools/msgfmt_data \
                test/test_ttk \
                test/test_unittest \
                test/test_unittest/testmock \