From 0922a4ae0d2803e3a4e9f3d2ccd217364cfd700e Mon Sep 17 00:00:00 2001 From: "Tomas R." Date: Sun, 27 Oct 2024 17:52:31 +0100 Subject: [PATCH] gh-124295: Add translation tests for argparse (GH-124803) --- Lib/test/test_argparse.py | 58 +++++++++++++++++++ Lib/test/translationdata/argparse/msgids.txt | 41 +++++++++++++ Makefile.pre.in | 2 + ...-09-30-22-52-44.gh-issue-124295.VZy5kx.rst | 1 + 4 files changed, 102 insertions(+) create mode 100644 Lib/test/translationdata/argparse/msgids.txt create mode 100644 Misc/NEWS.d/next/Tests/2024-09-30-22-52-44.gh-issue-124295.VZy5kx.rst diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index ed1c5c34e52..06b616069c6 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -7,8 +7,10 @@ import io import operator import os import py_compile +import re import shutil import stat +import subprocess import sys import textwrap import tempfile @@ -17,9 +19,13 @@ 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 unittest import mock @@ -7014,6 +7020,54 @@ class TestProgName(TestCase): def test_directory_in_zipfile_compiled(self): self.test_directory_in_zipfile(compiled=True) +# ================= +# 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): + + def test_translations(self): + # Test messages extracted from the argparse module against a snapshot + 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)) + def tearDownModule(): # Remove global references to avoid looking like we have refleaks. @@ -7022,4 +7076,8 @@ def tearDownModule(): if __name__ == '__main__': + # To regenerate translation snapshots + if len(sys.argv) > 1 and sys.argv[1] == '--snapshot-update': + update_translation_snapshots() + sys.exit(0) unittest.main() diff --git a/Lib/test/translationdata/argparse/msgids.txt b/Lib/test/translationdata/argparse/msgids.txt new file mode 100644 index 00000000000..f4d0a05635c --- /dev/null +++ b/Lib/test/translationdata/argparse/msgids.txt @@ -0,0 +1,41 @@ + (default: %(default)s) +%(heading)s: +%(prog)s: error: %(message)s\n +%(prog)s: warning: %(message)s\n +%r is not callable +'required' is an invalid argument for positionals +.__call__() not defined +ambiguous option: %(option)s could match %(matches)s +argument "-" with mode %r +argument %(argument_name)s: %(message)s +argument '%(argument_name)s' is deprecated +can't open '%(filename)s': %(error)s +cannot have multiple subparser arguments +cannot merge actions - two groups are named %r +command '%(parser_name)s' is deprecated +conflicting subparser alias: %s +conflicting subparser: %s +dest= is required for options like %r +expected at least one argument +expected at most one argument +expected one argument +ignored explicit argument %r +invalid %(type)s value: %(value)r +invalid choice: %(value)r (choose from %(choices)s) +invalid choice: %(value)r, maybe you meant %(closest)r? (choose from %(choices)s) +invalid conflict_resolution value: %r +invalid option string %(option)r: must start with a character %(prefix_chars)r +mutually exclusive arguments must be optional +not allowed with argument %s +one of the arguments %s is required +option '%(option)s' is deprecated +options +positional arguments +show program's version number and exit +show this help message and exit +subcommands +the following arguments are required: %s +unexpected option string: %s +unknown parser %(parser_name)r (choices: %(choices)s) +unrecognized arguments: %s +usage: \ No newline at end of file diff --git a/Makefile.pre.in b/Makefile.pre.in index d6f75a931a3..751e7ab8b42 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -2548,6 +2548,8 @@ TESTSUBDIRS= idlelib/idle_test \ test/tkinterdata \ test/tokenizedata \ test/tracedmodules \ + test/translationdata \ + test/translationdata/argparse \ test/typinganndata \ test/wheeldata \ test/xmltestdata \ diff --git a/Misc/NEWS.d/next/Tests/2024-09-30-22-52-44.gh-issue-124295.VZy5kx.rst b/Misc/NEWS.d/next/Tests/2024-09-30-22-52-44.gh-issue-124295.VZy5kx.rst new file mode 100644 index 00000000000..3c2455cfc8c --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2024-09-30-22-52-44.gh-issue-124295.VZy5kx.rst @@ -0,0 +1 @@ +Add translation tests to the :mod:`argparse` module.