https://github.com/python/cpython/commit/945dcb05cede24e9d03b8a816558ba70d67d6d67
commit: 945dcb05cede24e9d03b8a816558ba70d67d6d67
branch: 3.13
author: Miss Islington (bot) <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2025-02-16T13:20:49Z
summary:

[3.13] gh-127488: Add tests for Tools/i18n/msgfmt.py (GH-127540) (GH-130182)

(cherry picked from commit 361083b84b0db975058b2d1f50dcbfd36f072caf)

Co-authored-by: Tomas R <[email protected]>

files:
A Lib/test/test_tools/msgfmt_data/fuzzy.mo
A Lib/test/test_tools/msgfmt_data/fuzzy.po
A Lib/test/test_tools/msgfmt_data/general.mo
A Lib/test/test_tools/msgfmt_data/general.po
A Lib/test/test_tools/test_msgfmt.py
M 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
index 00000000000000..4b144831cf5f75
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
index 00000000000000..05e8354948ac0d
--- /dev/null
+++ b/Lib/test/test_tools/msgfmt_data/fuzzy.po
@@ -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
index 00000000000000..bc0683a62d0dda
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
index 00000000000000..8f840426824138
--- /dev/null
+++ b/Lib/test/test_tools/msgfmt_data/general.po
@@ -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 <[email protected]>\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
index 00000000000000..e3e3035c4f4395
--- /dev/null
+++ b/Lib/test/test_tools/test_msgfmt.py
@@ -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()
diff --git a/Makefile.pre.in b/Makefile.pre.in
index 46a37ded970573..ae1538c211f643 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -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 \

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to