77import operator
88import os
99import py_compile
10+ import re
1011import shutil
1112import stat
13+ import subprocess
1214import sys
1315import textwrap
1416import tempfile
1719import warnings
1820
1921from enum import StrEnum
22+ from pathlib import Path
23+ from test .support import REPO_ROOT
24+ from test .support import TEST_HOME_DIR
2025from test .support import captured_stderr
2126from test .support import import_helper
2227from test .support import os_helper
28+ from test .support import requires_subprocess
2329from test .support import script_helper
2430from unittest import mock
2531
@@ -7014,6 +7020,54 @@ def test_directory_in_zipfile(self, compiled=False):
70147020 def test_directory_in_zipfile_compiled (self ):
70157021 self .test_directory_in_zipfile (compiled = True )
70167022
7023+ # =================
7024+ # Translation tests
7025+ # =================
7026+
7027+ pygettext = Path (REPO_ROOT ) / 'Tools' / 'i18n' / 'pygettext.py'
7028+ snapshot_path = Path (TEST_HOME_DIR ) / 'translationdata' / 'argparse' / 'msgids.txt'
7029+
7030+ msgid_pattern = re .compile (r'msgid(.*?)(?:msgid_plural|msgctxt|msgstr)' , re .DOTALL )
7031+ msgid_string_pattern = re .compile (r'"((?:\\"|[^"])*)"' )
7032+
7033+
7034+ @requires_subprocess ()
7035+ class TestTranslations (unittest .TestCase ):
7036+
7037+ def test_translations (self ):
7038+ # Test messages extracted from the argparse module against a snapshot
7039+ res = generate_po_file (stdout_only = False )
7040+ self .assertEqual (res .returncode , 0 )
7041+ self .assertEqual (res .stderr , '' )
7042+ msgids = extract_msgids (res .stdout )
7043+ snapshot = snapshot_path .read_text ().splitlines ()
7044+ self .assertListEqual (msgids , snapshot )
7045+
7046+
7047+ def generate_po_file (* , stdout_only = True ):
7048+ res = subprocess .run ([sys .executable , pygettext ,
7049+ '--no-location' , '-o' , '-' , argparse .__file__ ],
7050+ stdout = subprocess .PIPE , stderr = subprocess .PIPE , text = True )
7051+ if stdout_only :
7052+ return res .stdout
7053+ return res
7054+
7055+
7056+ def extract_msgids (po ):
7057+ msgids = []
7058+ for msgid in msgid_pattern .findall (po ):
7059+ msgid_string = '' .join (msgid_string_pattern .findall (msgid ))
7060+ msgid_string = msgid_string .replace (r'\"' , '"' )
7061+ if msgid_string :
7062+ msgids .append (msgid_string )
7063+ return sorted (msgids )
7064+
7065+
7066+ def update_translation_snapshots ():
7067+ contents = generate_po_file ()
7068+ msgids = extract_msgids (contents )
7069+ snapshot_path .write_text ('\n ' .join (msgids ))
7070+
70177071
70187072def tearDownModule ():
70197073 # Remove global references to avoid looking like we have refleaks.
@@ -7022,4 +7076,8 @@ def tearDownModule():
70227076
70237077
70247078if __name__ == '__main__' :
7079+ # To regenerate translation snapshots
7080+ if len (sys .argv ) > 1 and sys .argv [1 ] == '--snapshot-update' :
7081+ update_translation_snapshots ()
7082+ sys .exit (0 )
70257083 unittest .main ()
0 commit comments