1import re 2import subprocess 3import sys 4import unittest 5from pathlib import Path 6from test.support import REPO_ROOT, TEST_HOME_DIR, requires_subprocess 7from test.test_tools import skip_if_missing 8 9 10pygettext = Path(REPO_ROOT) / 'Tools' / 'i18n' / 'pygettext.py' 11 12msgid_pattern = re.compile(r'msgid(.*?)(?:msgid_plural|msgctxt|msgstr)', 13 re.DOTALL) 14msgid_string_pattern = re.compile(r'"((?:\\"|[^"])*)"') 15 16 17def _generate_po_file(path, *, stdout_only=True): 18 res = subprocess.run([sys.executable, pygettext, 19 '--no-location', '-o', '-', path], 20 stdout=subprocess.PIPE, stderr=subprocess.PIPE, 21 text=True) 22 if stdout_only: 23 return res.stdout 24 return res 25 26 27def _extract_msgids(po): 28 msgids = [] 29 for msgid in msgid_pattern.findall(po): 30 msgid_string = ''.join(msgid_string_pattern.findall(msgid)) 31 msgid_string = msgid_string.replace(r'\"', '"') 32 if msgid_string: 33 msgids.append(msgid_string) 34 return sorted(msgids) 35 36 37def _get_snapshot_path(module_name): 38 return Path(TEST_HOME_DIR) / 'translationdata' / module_name / 'msgids.txt' 39 40 41@requires_subprocess() 42class TestTranslationsBase(unittest.TestCase): 43 44 def assertMsgidsEqual(self, module): 45 '''Assert that msgids extracted from a given module match a 46 snapshot. 47 48 ''' 49 skip_if_missing('i18n') 50 res = _generate_po_file(module.__file__, stdout_only=False) 51 self.assertEqual(res.returncode, 0) 52 self.assertEqual(res.stderr, '') 53 msgids = _extract_msgids(res.stdout) 54 snapshot_path = _get_snapshot_path(module.__name__) 55 snapshot = snapshot_path.read_text().splitlines() 56 self.assertListEqual(msgids, snapshot) 57 58 59def update_translation_snapshots(module): 60 contents = _generate_po_file(module.__file__) 61 msgids = _extract_msgids(contents) 62 snapshot_path = _get_snapshot_path(module.__name__) 63 snapshot_path.write_text('\n'.join(msgids)) 64