Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

gh-79516: allow msgfmt.py to compile multiple input po files#10875

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
s-ball wants to merge68 commits intopython:main
base:main
Choose a base branch
Loading
froms-ball:multi_inputs
Open
Show file tree
Hide file tree
Changes fromall commits
Commits
Show all changes
68 commits
Select commitHold shift + click to select a range
73b5ac8
Add test for current behaviour of msgfmt.py
s-ballDec 2, 2018
5fb1575
Final fix for bpo-9741, with tests proving it.
s-ballDec 2, 2018
b1968e9
Update docstrings for the script and make function
s-ballDec 2, 2018
0bc4ad3
Give make a simpler and more consistent interface.
s-ballDec 4, 2018
a9e67b4
Add a Misc/NEWS.d entry.
s-ballDec 5, 2018
6c59d6c
Merge branch 'multi_inputs' of https://github.com/s-ball/cpython into…
s-ballDec 5, 2018
1ce22c0
Merge branch 'main' into multi_inputs
s-ballJan 23, 2025
863bd97
Merge branch 'main' into multi_inputs
s-ballJan 23, 2025
4390ede
Fix an import error in test_i18n.py .
s-ballJan 23, 2025
008ea27
Fix another import error.
s-ballJan 23, 2025
8744743
Merge branch 'main' into multi_inputs
s-ballJan 23, 2025
93a6eb7
Merge branch 'main' into multi_inputs
s-ballFeb 23, 2025
ba26b80
Revert version number to 1.2
s-ballFeb 23, 2025
150cea1
Merge branch 'main' into multi_inputs
s-ballFeb 23, 2025
d9afabb
Merge branch 'main' into multi_inputs
s-ballFeb 24, 2025
9004387
Merge branch 'main' into multi_inputs
s-ballFeb 24, 2025
7556f79
Merge branch 'multi_inputs' of https://github.com/s-ball/cpython into…
s-ballFeb 27, 2025
80947d1
Merge branch 'main' into multi_inputs
s-ballFeb 27, 2025
12acb83
Merge branch 'main' into multi_inputs
s-ballFeb 27, 2025
1ecc1f3
Fix a merge error
s-ballFeb 27, 2025
e59ba68
Merge branch 'multi_inputs' of https://github.com/s-ball/cpython into…
s-ballFeb 27, 2025
4ffd20a
Merge branch 'main' into multi_inputs
s-ballFeb 27, 2025
7505f2b
Merge branch 'main' into multi_inputs
s-ballFeb 28, 2025
2c27120
Merge branch 'main' into multi_inputs
s-ballFeb 28, 2025
1f4e5ac
fix details
merwokFeb 28, 2025
4170796
Merge branch 'main' into multi_inputs
s-ballMar 1, 2025
46c08c5
Move tests for the gh-79516 issue to test_msgfmt.py
s-ballMar 1, 2025
24d89a6
Cosmetic improvements after review.
s-ballMar 1, 2025
17b4e05
Fix an import error
s-ballMar 1, 2025
bfc8a44
Merge branch 'main' into multi_inputs
s-ballMar 1, 2025
106dd40
Apply suggestions from code review
s-ballMar 2, 2025
9cb9395
Cosmetic improvements after review.
s-ballMar 2, 2025
08bc8d7
In test_msgfmt move data files to the data folder.
s-ballMar 2, 2025
9d992cd
Remove duplicate tests from test_msgfmt.
s-ballMar 2, 2025
31fd434
Merge branch 'main' into multi_inputs
s-ballMar 2, 2025
916aec7
Merge branch 'main' into multi_inputs
s-ballMar 2, 2025
51fcf09
Rename data files for test_msgfmt.Test_multi_input
s-ballMar 3, 2025
d51ad50
Apply suggestions from code review
s-ballMar 3, 2025
677f720
Cosmetic improvements after review.
s-ballMar 3, 2025
b4ea80a
compile_messages now accepts several input files
s-ballMar 4, 2025
3120add
whitespace nit
merwokMar 4, 2025
d642923
Merge branch 'main' into multi_inputs
s-ballMar 4, 2025
9d91f12
Make explicit how mo files can be re-generated.
s-ballMar 4, 2025
4d83cb7
Merge branch 'multi_inputs' of https://github.com/s-ball/cpython into…
s-ballMar 4, 2025
421272b
Apply suggestions from code review
s-ballMar 4, 2025
09b97d9
Update Lib/test/test_tools/test_msgfmt.py
s-ballMar 4, 2025
12cae51
Merge branch 'main' into multi_inputs
s-ballMar 5, 2025
3760851
Merge branch 'main' into multi_inputs
s-ballMar 15, 2025
d45039c
Generate json files for MultiInputTest data files.
s-ballMar 16, 2025
dde5ef1
Apply suggestions from code review
s-ballMar 16, 2025
bb6e0c5
Cosmetic improvements (long lines...)
s-ballMar 16, 2025
797990a
Merge branch 'multi_inputs' of https://github.com/s-ball/cpython into…
s-ballMar 16, 2025
c95af16
Merge branch 'main' into multi_inputs
s-ballMar 17, 2025
905ec70
Revert an unwanted change.
s-ballMar 17, 2025
b7a7c48
Simplifies the general logic of msgfmt.py
s-ballMar 18, 2025
1b3b73e
Update Tools/i18n/msgfmt.py
s-ballMar 18, 2025
1db2c66
Changes per review.
s-ballMar 18, 2025
3a6e1ef
Merge branch 'multi_inputs' of https://github.com/s-ball/cpython into…
s-ballMar 18, 2025
743bdc5
Removes the now unused get_names function.
s-ballMar 19, 2025
50e7145
Tests for extension corner cases for msgfmt.py
s-ballMar 19, 2025
caa8955
Merge branch 'main' into multi_inputs
s-ballApr 4, 2025
a4f1769
Fix a parameter inversion in test_msgfmt.py
s-ballApr 4, 2025
11f6e69
Merge branch 'main' into multi_inputs
s-ballApr 4, 2025
0ed3107
Merge branch 'main' into multi_inputs
s-ballApr 8, 2025
d1e0a26
Merge branch 'main' into multi_inputs
s-ballApr 8, 2025
213afcb
Merge branch 'main' into multi_inputs
s-ballMay 20, 2025
4d54e50
Merge main into multi_inputs
s-ballMay 22, 2025
ab97edd
Merge branch 'main' into multi_inputs
s-ballMay 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletionsLib/test/test_tools/msgfmt_data/.gitattributes
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
file1_fr_crlf.po eol=crlf
file2_fr_lf.po eol=lf
32 changes: 32 additions & 0 deletionsLib/test/test_tools/msgfmt_data/file12_fr.json
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
[
[
"",
"Project-Id-Version: PACKAGE VERSION\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: 2018-11-30 23:57+0100\nPO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\nLast-Translator: FULL NAME <EMAIL@ADDRESS>\nLanguage-Team: French\nLanguage: fr\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nPlural-Forms: nplurals=2; plural=(n > 1);\n"
],
[
"Bye...",
"Au revoir ..."
],
[
"Hello!",
"Bonjour !"
],
[
"It's over.",
"C'est termin\u00e9."
],
[
[
"{n} horse",
0
],
"{n} cheval"
],
[
[
"{n} horse",
1
],
"{n} chevaux"
]
]
Binary file addedLib/test/test_tools/msgfmt_data/file12_fr.mo
View file
Open in desktop
Binary file not shown.
24 changes: 24 additions & 0 deletionsLib/test/test_tools/msgfmt_data/file1_fr_crlf.json
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
[
[
"",
"Project-Id-Version: PACKAGE VERSION\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: 2018-11-30 23:46+0100\nPO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\nLast-Translator: FULL NAME <EMAIL@ADDRESS>\nLanguage-Team: French\nLanguage: fr\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nPlural-Forms: nplurals=2; plural=(n > 1);\n"
],
[
"Hello!",
"Bonjour !"
],
[
[
"{n} horse",
0
],
"{n} cheval"
],
[
[
"{n} horse",
1
],
"{n} chevaux"
]
]
Binary file addedLib/test/test_tools/msgfmt_data/file1_fr_crlf.mo
View file
Open in desktop
Binary file not shown.
26 changes: 26 additions & 0 deletionsLib/test/test_tools/msgfmt_data/file1_fr_crlf.po
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
# Example of French translations, crlf end of lines
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-11-30 23:46+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: French\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"

#: file1.py:6
msgid "Hello!"
msgstr "Bonjour !"

#: file1.py:7
#, python-brace-format
msgid "{n} horse"
msgid_plural "{n} horses"
msgstr[0] "{n} cheval"
msgstr[1] "{n} chevaux"
14 changes: 14 additions & 0 deletionsLib/test/test_tools/msgfmt_data/file2_fr_lf.json
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
[
[
"",
"Project-Id-Version: PACKAGE VERSION\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: 2018-11-30 23:57+0100\nPO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\nLast-Translator: FULL NAME <EMAIL@ADDRESS>\nLanguage-Team: French\nLanguage: fr\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nPlural-Forms: nplurals=2; plural=(n > 1);\n"
],
[
"Bye...",
"Au revoir ..."
],
[
"It's over.",
"C'est termin\u00e9."
]
]
Binary file addedLib/test/test_tools/msgfmt_data/file2_fr_lf.mo
View file
Open in desktop
Binary file not shown.
23 changes: 23 additions & 0 deletionsLib/test/test_tools/msgfmt_data/file2_fr_lf.po
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
# Example of French translations, lf end of lines
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-11-30 23:57+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: French\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"

#: file2.py:6
msgid "It's over."
msgstr "C'est terminé."

#: file2.py:7
msgid "Bye..."
msgstr "Au revoir ..."
115 changes: 92 additions & 23 deletionsLib/test/test_tools/test_msgfmt.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
"""Tests for the Tools/i18n/msgfmt.py tool."""
"""Tests for the Tools/i18n/msgfmt.py tool.

These tests use data files (po and mo) in the msgfmt_data folder.
The mo files can be generated (if the po file changes, or if msgfmt.py
slightly changes its output format) by using the --snapshot-update flag
with this script:

python test_msgfmt.py --snapshot-update
"""

import filecmp
import json
import os.path
import shutil
import struct
import sys
import unittest
Expand All@@ -11,7 +22,6 @@
from test.support.script_helper import assert_python_failure, assert_python_ok
from test.test_tools import imports_under_tool, skip_if_missing, toolsdir


skip_if_missing('i18n')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Accidentally removed line here


data_dir = (Path(__file__).parent / 'msgfmt_data').resolve()
Expand All@@ -22,6 +32,10 @@
import msgfmt


def compile_many_messages(mo_file, *po_files):
assert_python_ok(msgfmt_py, '-o', mo_file, *po_files)


def compile_messages(po_file, mo_file):
assert_python_ok(msgfmt_py, '-o', mo_file, po_file)

Expand DownExpand Up@@ -145,12 +159,6 @@ def test_generic_syntax_error(self):


class POParserTest(unittest.TestCase):
@classmethod
def tearDownClass(cls):
# msgfmt uses a global variable to store messages,
# clear it after the tests.
msgfmt.MESSAGES.clear()

def test_strings(self):
# Test that the PO parser correctly handles and unescape
# strings in the PO file.
Expand DownExpand Up@@ -202,9 +210,7 @@ def test_strings(self):
# check the result.
po = f'msgid {po_string}\nmsgstr "translation"'
Path('messages.po').write_text(po)
# Reset the global MESSAGES dictionary
msgfmt.MESSAGES.clear()
msgfmt.make('messages.po', 'messages.mo')
msgfmt.make(('messages.po',), 'messages.mo')

with open('messages.mo', 'rb') as f:
actual = GNUTranslations(f)
Expand DownExpand Up@@ -238,7 +244,7 @@ def test_strings(self):
# Reset the global MESSAGES dictionary
msgfmt.MESSAGES.clear()
with self.assertRaises(Exception):
msgfmt.make('messages.po', 'messages.mo')
msgfmt.make(('messages.po',), 'messages.mo')


class CLITest(unittest.TestCase):
Expand DownExpand Up@@ -271,20 +277,83 @@ def test_nonexistent_file(self):
assert_python_failure(msgfmt_py, 'nonexistent.po')


class MultiInputTest(unittest.TestCase):
"""Tests for multiple input files
"""

def test_both_with_outputfile(self):
"""Test script with -o option and 2 input files

The current behaviour is to merge entries having distinct ids
and keep last one if the same id occurs in multiple files.

Here the first file has Windows endings (cflr) while second has
Unix endings (lf)
"""
with temp_cwd(None):
assert_python_ok(msgfmt_py, '-o', 'file12.mo',
data_dir / 'file1_fr_crlf.po',
data_dir / 'file2_fr_lf.po')
self.assertTrue(filecmp.cmp(data_dir / 'file12_fr.mo',
'file12.mo'))

def test_both_without_outputfile(self):
"""Test script without -o option and 2 input files"""

with temp_cwd(None):
shutil.copy(data_dir / 'file1_fr_crlf.po', '.')
shutil.copy(data_dir / 'file2_fr_lf.po', '.')
assert_python_ok(msgfmt_py, 'file1_fr_crlf.po', 'file2_fr_lf.po')
self.assertTrue(filecmp.cmp(data_dir / 'file1_fr_crlf.mo',
'file1_fr_crlf.mo'))
self.assertTrue(filecmp.cmp(data_dir / 'file2_fr_lf.mo',
'file2_fr_lf.mo'))


class PONamesTest(unittest.TestCase):
def test_no_extension(self):
with temp_cwd(None):
shutil.copy(data_dir / 'file1_fr_crlf.po', 'file1.fr.po')
assert_python_ok(msgfmt_py, 'file1.fr')
self.assertTrue(os.path.exists('file1.fr.mo'))

def test_wrong_extension(self):
with temp_cwd(None):
shutil.copy(data_dir / 'file1_fr_crlf.po', 'file1_fr.pox')
assert_python_failure(msgfmt_py, 'file1_fr.pox')
self.assertFalse(os.path.exists('file1_fr.mo'))
self.assertFalse(os.path.exists('file1_fr.pox.mo'))

@unittest.skipUnless(sys.platform.startswith("win"), "uppercase on Windows")
def test_MAJ_on_Windows(self):
with temp_cwd(None):
shutil.copy(data_dir / 'file1_fr_crlf.po', 'File1.PO')
assert_python_ok(msgfmt_py, 'FIle1.Po')
self.assertTrue(os.path.exists('file1.mo'))


def make_message_files(mo_file, *po_files):
compile_many_messages(mo_file, *po_files)
# Create a human-readable JSON file which is
# easier to review than the binary .mo file.
with open(mo_file, 'rb') as f:
translations = GNUTranslations(f)
catalog_file = mo_file.with_suffix('.json')
with open(catalog_file, 'w') as f:
data = translations._catalog.items()
data = sorted(data, key=lambda x: (isinstance(x[0], tuple), x[0]))
json.dump(data, f, indent=4)
f.write('\n')


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)
# Create a human-readable JSON file which is
# easier to review than the binary .mo file.
with open(mo_file, 'rb') as f:
translations = GNUTranslations(f)
catalog_file = po_file.with_suffix('.json')
with open(catalog_file, 'w') as f:
data = translations._catalog.items()
data = sorted(data, key=lambda x: (isinstance(x[0], tuple), x[0]))
json.dump(data, f, indent=4)
f.write('\n')
make_message_files(mo_file, po_file)
# special processing for file12_fr.mo which results from 2 input files
make_message_files(data_dir / 'file12_fr.mo',
data_dir / 'file1_fr_crlf.po',
data_dir / 'file2_fr_lf.po')


if __name__ == '__main__':
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
:program:`msgfmt.py` is now able to merge more than one po file into a compiled mo
file. When an entry exists in more than on input file, the last file wins.
Loading
Loading

[8]ページ先頭

©2009-2025 Movatter.jp