From dff074d1446bab23578a6b228b0c59a17006299c Mon Sep 17 00:00:00 2001 From: "Tomas R." Date: Mon, 11 Nov 2024 23:16:39 +0100 Subject: [PATCH] gh-126413: Add translation tests for getopt and optparse (GH-126698) --- Lib/test/support/i18n_helper.py | 63 ++++++++++++++++++++ Lib/test/test_argparse.py | 54 ++--------------- Lib/test/test_getopt.py | 19 ++++-- Lib/test/test_optparse.py | 11 +++- Lib/test/translationdata/getopt/msgids.txt | 6 ++ Lib/test/translationdata/optparse/msgids.txt | 14 +++++ Makefile.pre.in | 2 + 7 files changed, 114 insertions(+), 55 deletions(-) create mode 100644 Lib/test/support/i18n_helper.py create mode 100644 Lib/test/translationdata/getopt/msgids.txt create mode 100644 Lib/test/translationdata/optparse/msgids.txt diff --git a/Lib/test/support/i18n_helper.py b/Lib/test/support/i18n_helper.py new file mode 100644 index 00000000000..2e304f29e8b --- /dev/null +++ b/Lib/test/support/i18n_helper.py @@ -0,0 +1,63 @@ +import re +import subprocess +import sys +import unittest +from pathlib import Path +from test.support import REPO_ROOT, TEST_HOME_DIR, requires_subprocess +from test.test_tools import skip_if_missing + + +pygettext = Path(REPO_ROOT) / 'Tools' / 'i18n' / 'pygettext.py' + +msgid_pattern = re.compile(r'msgid(.*?)(?:msgid_plural|msgctxt|msgstr)', + re.DOTALL) +msgid_string_pattern = re.compile(r'"((?:\\"|[^"])*)"') + + +def _generate_po_file(path, *, stdout_only=True): + res = subprocess.run([sys.executable, pygettext, + '--no-location', '-o', '-', path], + stdout=subprocess.PIPE, stderr=subprocess.PIPE, + text=True) + if stdout_only: + return res.stdout + return res + + +def _extract_msgids(po): + msgids = [] + for msgid in msgid_pattern.findall(po): + msgid_string = ''.join(msgid_string_pattern.findall(msgid)) + msgid_string = msgid_string.replace(r'\"', '"') + if msgid_string: + msgids.append(msgid_string) + return sorted(msgids) + + +def _get_snapshot_path(module_name): + return Path(TEST_HOME_DIR) / 'translationdata' / module_name / 'msgids.txt' + + +@requires_subprocess() +class TestTranslationsBase(unittest.TestCase): + + def assertMsgidsEqual(self, module): + '''Assert that msgids extracted from a given module match a + snapshot. + + ''' + skip_if_missing('i18n') + res = _generate_po_file(module.__file__, stdout_only=False) + self.assertEqual(res.returncode, 0) + self.assertEqual(res.stderr, '') + msgids = _extract_msgids(res.stdout) + snapshot_path = _get_snapshot_path(module.__name__) + snapshot = snapshot_path.read_text().splitlines() + self.assertListEqual(msgids, snapshot) + + +def update_translation_snapshots(module): + contents = _generate_po_file(module.__file__) + msgids = _extract_msgids(contents) + snapshot_path = _get_snapshot_path(module.__name__) + snapshot_path.write_text('\n'.join(msgids)) diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index cbf119ed2da..358cfb1c56a 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -7,10 +7,8 @@ import io import operator import os import py_compile -import re import shutil import stat -import subprocess import sys import textwrap import tempfile @@ -19,15 +17,11 @@ import argparse import warnings from enum import StrEnum -from pathlib import Path -from test.support import REPO_ROOT -from test.support import TEST_HOME_DIR from test.support import captured_stderr from test.support import import_helper from test.support import os_helper -from test.support import requires_subprocess from test.support import script_helper -from test.test_tools import skip_if_missing +from test.support.i18n_helper import TestTranslationsBase, update_translation_snapshots from unittest import mock @@ -7056,50 +7050,10 @@ class TestProgName(TestCase): # Translation tests # ================= -pygettext = Path(REPO_ROOT) / 'Tools' / 'i18n' / 'pygettext.py' -snapshot_path = Path(TEST_HOME_DIR) / 'translationdata' / 'argparse' / 'msgids.txt' - -msgid_pattern = re.compile(r'msgid(.*?)(?:msgid_plural|msgctxt|msgstr)', re.DOTALL) -msgid_string_pattern = re.compile(r'"((?:\\"|[^"])*)"') - - -@requires_subprocess() -class TestTranslations(unittest.TestCase): +class TestTranslations(TestTranslationsBase): def test_translations(self): - # Test messages extracted from the argparse module against a snapshot - skip_if_missing('i18n') - res = generate_po_file(stdout_only=False) - self.assertEqual(res.returncode, 0) - self.assertEqual(res.stderr, '') - msgids = extract_msgids(res.stdout) - snapshot = snapshot_path.read_text().splitlines() - self.assertListEqual(msgids, snapshot) - - -def generate_po_file(*, stdout_only=True): - res = subprocess.run([sys.executable, pygettext, - '--no-location', '-o', '-', argparse.__file__], - stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) - if stdout_only: - return res.stdout - return res - - -def extract_msgids(po): - msgids = [] - for msgid in msgid_pattern.findall(po): - msgid_string = ''.join(msgid_string_pattern.findall(msgid)) - msgid_string = msgid_string.replace(r'\"', '"') - if msgid_string: - msgids.append(msgid_string) - return sorted(msgids) - - -def update_translation_snapshots(): - contents = generate_po_file() - msgids = extract_msgids(contents) - snapshot_path.write_text('\n'.join(msgids)) + self.assertMsgidsEqual(argparse) def tearDownModule(): @@ -7111,6 +7065,6 @@ def tearDownModule(): if __name__ == '__main__': # To regenerate translation snapshots if len(sys.argv) > 1 and sys.argv[1] == '--snapshot-update': - update_translation_snapshots() + update_translation_snapshots(argparse) sys.exit(0) unittest.main() diff --git a/Lib/test/test_getopt.py b/Lib/test/test_getopt.py index 984bdb73f34..0675bcbb4e8 100644 --- a/Lib/test/test_getopt.py +++ b/Lib/test/test_getopt.py @@ -1,11 +1,12 @@ # test_getopt.py # David Goodger 2000-08-19 -from test.support.os_helper import EnvironmentVarGuard import doctest -import unittest - import getopt +import sys +import unittest +from test.support.i18n_helper import TestTranslationsBase, update_translation_snapshots +from test.support.os_helper import EnvironmentVarGuard sentinel = object() @@ -224,10 +225,20 @@ def test_libref_examples(): ['a1', 'a2'] """ + +class TestTranslations(TestTranslationsBase): + def test_translations(self): + self.assertMsgidsEqual(getopt) + + def load_tests(loader, tests, pattern): tests.addTest(doctest.DocTestSuite()) return tests -if __name__ == "__main__": +if __name__ == '__main__': + # To regenerate translation snapshots + if len(sys.argv) > 1 and sys.argv[1] == '--snapshot-update': + update_translation_snapshots(getopt) + sys.exit(0) unittest.main() diff --git a/Lib/test/test_optparse.py b/Lib/test/test_optparse.py index 28b27446238..8655a0537a5 100644 --- a/Lib/test/test_optparse.py +++ b/Lib/test/test_optparse.py @@ -15,7 +15,7 @@ import unittest from io import StringIO from test import support from test.support import os_helper - +from test.support.i18n_helper import TestTranslationsBase, update_translation_snapshots import optparse from optparse import make_option, Option, \ @@ -1656,5 +1656,14 @@ class MiscTestCase(unittest.TestCase): support.check__all__(self, optparse, not_exported=not_exported) +class TestTranslations(TestTranslationsBase): + def test_translations(self): + self.assertMsgidsEqual(optparse) + + if __name__ == '__main__': + # To regenerate translation snapshots + if len(sys.argv) > 1 and sys.argv[1] == '--snapshot-update': + update_translation_snapshots(optparse) + sys.exit(0) unittest.main() diff --git a/Lib/test/translationdata/getopt/msgids.txt b/Lib/test/translationdata/getopt/msgids.txt new file mode 100644 index 00000000000..1ffab1f31ab --- /dev/null +++ b/Lib/test/translationdata/getopt/msgids.txt @@ -0,0 +1,6 @@ +option -%s not recognized +option -%s requires argument +option --%s must not have an argument +option --%s not a unique prefix +option --%s not recognized +option --%s requires argument \ No newline at end of file diff --git a/Lib/test/translationdata/optparse/msgids.txt b/Lib/test/translationdata/optparse/msgids.txt new file mode 100644 index 00000000000..ac5317c736a --- /dev/null +++ b/Lib/test/translationdata/optparse/msgids.txt @@ -0,0 +1,14 @@ +%prog [options] +%s option does not take a value +Options +Usage +Usage: %s\n +ambiguous option: %s (%s?) +complex +floating-point +integer +no such option: %s +option %s: invalid %s value: %r +option %s: invalid choice: %r (choose from %s) +show program's version number and exit +show this help message and exit \ No newline at end of file diff --git a/Makefile.pre.in b/Makefile.pre.in index a337223d4d8..8d94ba361fd 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -2567,6 +2567,8 @@ TESTSUBDIRS= idlelib/idle_test \ test/tracedmodules \ test/translationdata \ test/translationdata/argparse \ + test/translationdata/getopt \ + test/translationdata/optparse \ test/typinganndata \ test/wheeldata \ test/xmltestdata \