From 22249e82e448e13e0a0afe41375f3cdc2102898f Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Tue, 11 Feb 2025 22:40:42 +0100 Subject: [PATCH 01/12] pygettext: Support translator comments --- Lib/test/test_tools/i18n_data/comments.pot | 103 +++++++++++++++++++++ Lib/test/test_tools/i18n_data/comments.py | 72 ++++++++++++++ Lib/test/test_tools/test_i18n.py | 6 +- Tools/i18n/pygettext.py | 100 +++++++++++++++++--- 4 files changed, 265 insertions(+), 16 deletions(-) create mode 100644 Lib/test/test_tools/i18n_data/comments.pot create mode 100644 Lib/test/test_tools/i18n_data/comments.py diff --git a/Lib/test/test_tools/i18n_data/comments.pot b/Lib/test/test_tools/i18n_data/comments.pot new file mode 100644 index 00000000000000..0cc2fe0ef1fed6 --- /dev/null +++ b/Lib/test/test_tools/i18n_data/comments.pot @@ -0,0 +1,103 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR ORGANIZATION +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2000-01-01 00:00+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: pygettext.py 1.5\n" + + +#: comments.py:4 +msgid "foo" +msgstr "" + +#. i18n: This is a translator comment +#: comments.py:7 +msgid "bar" +msgstr "" + +#. i18n: This is a translator comment +#. i18n: This is another translator comment +#: comments.py:11 +msgid "baz" +msgstr "" + +#. i18n: This is a translator comment +#. with multiple +#. lines +#: comments.py:16 +msgid "qux" +msgstr "" + +#. i18n: This is a translator comment +#: comments.py:21 +msgid "quux" +msgstr "" + +#. i18n: This is a translator comment +#. with multiple lines +#. i18n: This is another translator comment +#. with multiple lines +#: comments.py:27 +msgid "corge" +msgstr "" + +#: comments.py:31 +msgid "grault" +msgstr "" + +#. i18n: This is another translator comment +#: comments.py:36 +msgid "garply" +msgstr "" + +#: comments.py:40 +msgid "george" +msgstr "" + +#. i18n: This is another translator comment +#: comments.py:45 +msgid "waldo" +msgstr "" + +#. i18n: This is a translator comment +#. i18n: This is also a translator comment +#. i18n: This is another translator comment +#: comments.py:50 +msgid "waldo2" +msgstr "" + +#. i18n: This is a translator comment +#. i18n: This is another translator comment +#. i18n: This is yet another translator comment +#. i18n: This is a translator comment +#. with multiple lines +#: comments.py:53 comments.py:56 comments.py:59 comments.py:63 +msgid "fred" +msgstr "" + +#: comments.py:65 +msgid "plugh" +msgstr "" + +#: comments.py:67 +msgid "foobar" +msgstr "" + +#. i18n: This is a translator comment +#: comments.py:71 +msgid "xyzzy" +msgstr "" + +#: comments.py:72 +msgid "thud" +msgstr "" + diff --git a/Lib/test/test_tools/i18n_data/comments.py b/Lib/test/test_tools/i18n_data/comments.py new file mode 100644 index 00000000000000..59d3da60ac5d60 --- /dev/null +++ b/Lib/test/test_tools/i18n_data/comments.py @@ -0,0 +1,72 @@ +from gettext import gettext as _ + +# Not a translator comment +_('foo') + +# i18n: This is a translator comment +_('bar') + +# i18n: This is a translator comment +# i18n: This is another translator comment +_('baz') + +# i18n: This is a translator comment +# with multiple +# lines +_('qux') + +# This comment should not be included because +# it does not start with the prefix +# i18n: This is a translator comment +_('quux') + +# i18n: This is a translator comment +# with multiple lines +# i18n: This is another translator comment +# with multiple lines +_('corge') + +# i18n: This comment should be ignored + +_('grault') + +# i18n: This comment should be ignored + +# i18n: This is another translator comment +_('garply') + +# i18n: comment should be ignored +x = 1 +_('george') + +# i18n: This comment should be ignored +x = 1 +# i18n: This is another translator comment +_('waldo') + +# i18n: This is a translator comment +x = 1 # i18n: This is also a translator comment +# i18n: This is another translator comment +_('waldo2') + +# i18n: This is a translator comment +_('fred') + +# i18n: This is another translator comment +_('fred') + +# i18n: This is yet another translator comment +_('fred') + +# i18n: This is a translator comment +# with multiple lines +_('fred') + +_('plugh') # i18n: This comment should be ignored + +_('foo' # i18n: This comment should be ignored + 'bar') # i18n: This comment should be ignored + +# i18n: This is a translator comment +_('xyzzy') +_('thud') diff --git a/Lib/test/test_tools/test_i18n.py b/Lib/test/test_tools/test_i18n.py index d23479104d438d..ea2fa9bd764882 100644 --- a/Lib/test/test_tools/test_i18n.py +++ b/Lib/test/test_tools/test_i18n.py @@ -381,7 +381,8 @@ def test_pygettext_output(self): contents = input_file.read_text(encoding='utf-8') with temp_cwd(None): Path(input_file.name).write_text(contents) - assert_python_ok('-Xutf8', self.script, '--docstrings', input_file.name) + assert_python_ok('-Xutf8', self.script, '--docstrings', + '--add-comments=i18n:', input_file.name) output = Path('messages.pot').read_text(encoding='utf-8') expected = output_file.read_text(encoding='utf-8') @@ -438,7 +439,8 @@ def update_POT_snapshots(): contents = input_file.read_bytes() with temp_cwd(None): Path(input_file.name).write_bytes(contents) - assert_python_ok('-Xutf8', Test_pygettext.script, '--docstrings', input_file.name) + assert_python_ok('-Xutf8', Test_pygettext.script, '--docstrings', + '--add-comments=i18n:', input_file.name) output = Path('messages.pot').read_text(encoding='utf-8') output = normalize_POT_file(output) diff --git a/Tools/i18n/pygettext.py b/Tools/i18n/pygettext.py index 4720aecbdc515a..85d1abb3e39a30 100755 --- a/Tools/i18n/pygettext.py +++ b/Tools/i18n/pygettext.py @@ -46,6 +46,12 @@ --extract-all Extract all strings. + -cTAG + --add-comments=TAG + Extract translator comments. Comments must start with TAG and + must precede the gettext call. Multiple -cTAG options are allowed. + In that case, any comment matching any of the TAGs will be extracted. + -d name --default-domain=name Rename the default output file from messages.pot to name.pot. @@ -140,7 +146,9 @@ import os import sys import time +import tokenize from dataclasses import dataclass, field +from io import BytesIO from operator import itemgetter __version__ = '1.5' @@ -301,12 +309,28 @@ class Message: msgctxt: str | None locations: set[Location] = field(default_factory=set) is_docstring: bool = False + comments: list[str] = field(default_factory=list) - def add_location(self, filename, lineno, msgid_plural=None, *, is_docstring=False): + def add_location(self, filename, lineno, msgid_plural=None, *, + is_docstring=False, comments=None): if self.msgid_plural is None: self.msgid_plural = msgid_plural self.locations.add(Location(filename, lineno)) self.is_docstring |= is_docstring + if comments: + self.comments.extend(comments) + + +def get_source_comments(source): + """ + Return a dictionary mapping line numbers to + comments in the source code. + """ + comments = {} + for token in tokenize.tokenize(BytesIO(source).readline): + if token.type == tokenize.COMMENT: + comments[token.start[0]] = token.string.removeprefix('#').strip() + return comments class GettextVisitor(ast.NodeVisitor): @@ -315,10 +339,17 @@ def __init__(self, options): self.options = options self.filename = None self.messages = {} + self.comments = {} + + def visit_file(self, source, filename): + try: + module_tree = ast.parse(source) + except SyntaxError: + return - def visit_file(self, node, filename): self.filename = filename - self.visit(node) + self.comments = get_source_comments(source) + self.visit(module_tree) def visit_Module(self, node): self._extract_docstring(node) @@ -371,14 +402,51 @@ def _extract_message(self, node): msg_data[arg_type] = arg.value lineno = node.lineno - self._add_message(lineno, **msg_data) + comments = self._extract_comments(node) + self._add_message(lineno, **msg_data, comments=comments) + + def _extract_comments(self, node): + """Extract translator comments. + + Translator comments must precede the gettext call and + start with one of the comment prefixes defined by + --add-comments=TAG. See the tests for examples. + """ + if not self.options.comment_tags: + return [] + + comments = [] + lineno = node.lineno - 1 + # Collect an unbroken sequence of comments starting from + # the line above the gettext call. + while lineno >= 1: + comment = self.comments.get(lineno) + if comment is None: + break + comments.append(comment) + lineno -= 1 + + # Find the first translator comment in the sequence and + # return all comments starting from that comment. + comments = comments[::-1] + first_index = next((i for i, comment in enumerate(comments) + if self._is_translator_comment(comment)), None) + if first_index is None: + return [] + return comments[first_index:] + + def _is_translator_comment(self, comment): + return comment.startswith(tuple(self.options.comment_tags)) def _add_message( self, lineno, msgid, msgid_plural=None, msgctxt=None, *, - is_docstring=False): + is_docstring=False, comments=None): if msgid in self.options.toexclude: return + if not comments: + comments = [] + key = self._key_for(msgid, msgctxt) message = self.messages.get(key) if message: @@ -387,6 +455,7 @@ def _add_message( lineno, msgid_plural, is_docstring=is_docstring, + comments=comments, ) else: self.messages[key] = Message( @@ -395,6 +464,7 @@ def _add_message( msgctxt=msgctxt, locations={Location(self.filename, lineno)}, is_docstring=is_docstring, + comments=comments, ) @staticmethod @@ -434,6 +504,10 @@ def write_pot_file(messages, options, fp): for key, locations in sorted_keys: msg = messages[key] + + for comment in msg.comments: + print(f'#. {comment}', file=fp) + if options.writelocations: # location comments are different b/w Solaris and GNU: if options.locationstyle == options.SOLARIS: @@ -472,9 +546,9 @@ def main(): try: opts, args = getopt.getopt( sys.argv[1:], - 'ad:DEhk:Kno:p:S:Vvw:x:X:', - ['extract-all', 'default-domain=', 'escape', 'help', - 'keyword=', 'no-default-keywords', + 'ac:d:DEhk:Kno:p:S:Vvw:x:X:', + ['extract-all', 'add-comments=', 'default-domain=', 'escape', + 'help', 'keyword=', 'no-default-keywords', 'add-location', 'no-location', 'output=', 'output-dir=', 'style=', 'verbose', 'version', 'width=', 'exclude-file=', 'docstrings', 'no-docstrings', @@ -500,6 +574,7 @@ class Options: excludefilename = '' docstrings = 0 nodocstrings = {} + comment_tags = set() options = Options() locations = {'gnu' : options.GNU, @@ -512,6 +587,8 @@ class Options: usage(0) elif opt in ('-a', '--extract-all'): options.extractall = 1 + elif opt in ('-c', '--add-comments'): + options.comment_tags.add(arg) elif opt in ('-d', '--default-domain'): options.outfile = arg + '.pot' elif opt in ('-E', '--escape'): @@ -599,12 +676,7 @@ class Options: with open(filename, 'rb') as fp: source = fp.read() - try: - module_tree = ast.parse(source) - except SyntaxError: - continue - - visitor.visit_file(module_tree, filename) + visitor.visit_file(source, filename) # write the output if options.outfile == '-': From cab4b7a37e0d23907494b21643cf59b015a21756 Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Wed, 12 Feb 2025 23:24:44 +0100 Subject: [PATCH 02/12] Add news entry --- .../Tools-Demos/2025-02-12-23-24-37.gh-issue-130057.TKUKI6.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Tools-Demos/2025-02-12-23-24-37.gh-issue-130057.TKUKI6.rst diff --git a/Misc/NEWS.d/next/Tools-Demos/2025-02-12-23-24-37.gh-issue-130057.TKUKI6.rst b/Misc/NEWS.d/next/Tools-Demos/2025-02-12-23-24-37.gh-issue-130057.TKUKI6.rst new file mode 100644 index 00000000000000..0e89fa652dcbba --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2025-02-12-23-24-37.gh-issue-130057.TKUKI6.rst @@ -0,0 +1 @@ +Add support for translator comments in :program:`pygettext.py`. From a86fb596dda43d3b100072664f62f5bc992ede2e Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Thu, 13 Feb 2025 08:57:59 +0100 Subject: [PATCH 03/12] Make linter happy --- Tools/i18n/pygettext.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/i18n/pygettext.py b/Tools/i18n/pygettext.py index 85d1abb3e39a30..988c418fefb6d0 100755 --- a/Tools/i18n/pygettext.py +++ b/Tools/i18n/pygettext.py @@ -434,7 +434,7 @@ def _extract_comments(self, node): if first_index is None: return [] return comments[first_index:] - + def _is_translator_comment(self, comment): return comment.startswith(tuple(self.options.comment_tags)) From 396a7bec50e6437ba604dd86cdc6687f83c6e14a Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Fri, 14 Feb 2025 21:04:29 +0100 Subject: [PATCH 04/12] Only process comments when needed --- Tools/i18n/pygettext.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Tools/i18n/pygettext.py b/Tools/i18n/pygettext.py index 988c418fefb6d0..05a94ca3bc6cb6 100755 --- a/Tools/i18n/pygettext.py +++ b/Tools/i18n/pygettext.py @@ -348,7 +348,8 @@ def visit_file(self, source, filename): return self.filename = filename - self.comments = get_source_comments(source) + if self.options.comment_tags: + self.comments = get_source_comments(source) self.visit(module_tree) def visit_Module(self, node): @@ -436,7 +437,7 @@ def _extract_comments(self, node): return comments[first_index:] def _is_translator_comment(self, comment): - return comment.startswith(tuple(self.options.comment_tags)) + return comment.startswith(self.options.comment_tags) def _add_message( self, lineno, msgid, msgid_plural=None, msgctxt=None, *, @@ -634,6 +635,8 @@ class Options: finally: fp.close() + options.comment_tags = tuple(options.comment_tags) + # calculate escapes make_escapes(not options.escape) From feb11456bf2688cdb5788f7bb479cb239b38f76e Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Fri, 14 Feb 2025 21:16:59 +0100 Subject: [PATCH 05/12] Make --add-comments optional --- Lib/test/test_tools/test_i18n.py | 24 ++++++++++++++++++++---- Tools/i18n/pygettext.py | 4 ++-- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_tools/test_i18n.py b/Lib/test/test_tools/test_i18n.py index ea2fa9bd764882..7376675f35e74d 100644 --- a/Lib/test/test_tools/test_i18n.py +++ b/Lib/test/test_tools/test_i18n.py @@ -87,7 +87,8 @@ def assert_POT_equal(self, expected, actual): self.maxDiff = None self.assertEqual(normalize_POT_file(expected), normalize_POT_file(actual)) - def extract_from_str(self, module_content, *, args=(), strict=True, with_stderr=False): + def extract_from_str(self, module_content, *, args=(), strict=True, + with_stderr=False, raw=False): """Return all msgids extracted from module_content.""" filename = 'test.py' with temp_cwd(None): @@ -98,10 +99,11 @@ def extract_from_str(self, module_content, *, args=(), strict=True, with_stderr= self.assertEqual(res.err, b'') with open('messages.pot', encoding='utf-8') as fp: data = fp.read() - msgids = self.get_msgids(data) + if not raw: + data = self.get_msgids(data) if not with_stderr: - return msgids - return msgids, res.err + return data + return data, res.err def extract_docstrings_from_str(self, module_content): """Return all docstrings extracted from module_content.""" @@ -432,6 +434,20 @@ def test_error_messages(self): "*** test.py:3: Variable positional arguments are not allowed in gettext calls\n" ) + def test_extract_all_comments(self): + """ + Test that the --add-comments option without an + explicit tag extracts all translator comments. + """ + + for arg in ('--add-comments', '-c'): + with self.subTest(arg=arg): + data = self.extract_from_str(dedent('''\ + # Translator comment + _("foo") + '''), args=(arg,), raw=True) + self.assertIn('#. Translator comment', data) + def update_POT_snapshots(): for input_file in DATA_DIR.glob('*.py'): diff --git a/Tools/i18n/pygettext.py b/Tools/i18n/pygettext.py index 05a94ca3bc6cb6..6a281aca3adbc2 100755 --- a/Tools/i18n/pygettext.py +++ b/Tools/i18n/pygettext.py @@ -547,8 +547,8 @@ def main(): try: opts, args = getopt.getopt( sys.argv[1:], - 'ac:d:DEhk:Kno:p:S:Vvw:x:X:', - ['extract-all', 'add-comments=', 'default-domain=', 'escape', + 'ac::d:DEhk:Kno:p:S:Vvw:x:X:', + ['extract-all', 'add-comments=?', 'default-domain=', 'escape', 'help', 'keyword=', 'no-default-keywords', 'add-location', 'no-location', 'output=', 'output-dir=', 'style=', 'verbose', 'version', 'width=', 'exclude-file=', From fd480bbb6a9d6f22798c8955f3d589e22b3e3cd4 Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Fri, 14 Feb 2025 21:30:37 +0100 Subject: [PATCH 06/12] Strip any leading '#' and whitespace from comments --- Lib/test/test_tools/i18n_data/comments.pot | 7 +++++++ Lib/test/test_tools/i18n_data/comments.py | 6 ++++++ Tools/i18n/pygettext.py | 5 ++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_tools/i18n_data/comments.pot b/Lib/test/test_tools/i18n_data/comments.pot index 0cc2fe0ef1fed6..a1df46d453c546 100644 --- a/Lib/test/test_tools/i18n_data/comments.pot +++ b/Lib/test/test_tools/i18n_data/comments.pot @@ -101,3 +101,10 @@ msgstr "" msgid "thud" msgstr "" +#. i18n: This is a translator comment +#. i18n: This is another translator comment +#. i18n: This is yet another translator comment +#: comments.py:78 +msgid "foos" +msgstr "" + diff --git a/Lib/test/test_tools/i18n_data/comments.py b/Lib/test/test_tools/i18n_data/comments.py index 59d3da60ac5d60..c0b73d19fc4820 100644 --- a/Lib/test/test_tools/i18n_data/comments.py +++ b/Lib/test/test_tools/i18n_data/comments.py @@ -70,3 +70,9 @@ # i18n: This is a translator comment _('xyzzy') _('thud') + + +## i18n: This is a translator comment +# # i18n: This is another translator comment +### ### i18n: This is yet another translator comment +_('foos') \ No newline at end of file diff --git a/Tools/i18n/pygettext.py b/Tools/i18n/pygettext.py index 6a281aca3adbc2..20cea3367a972d 100755 --- a/Tools/i18n/pygettext.py +++ b/Tools/i18n/pygettext.py @@ -144,6 +144,7 @@ import importlib.machinery import importlib.util import os +import re import sys import time import tokenize @@ -329,7 +330,9 @@ def get_source_comments(source): comments = {} for token in tokenize.tokenize(BytesIO(source).readline): if token.type == tokenize.COMMENT: - comments[token.start[0]] = token.string.removeprefix('#').strip() + # Remove any leading combination of '#' and whitespace + comment = re.sub(r'^[#\s]+', '', token.string) + comments[token.start[0]] = comment return comments From b3f6b486fbf15276ea0c6094a8e7e5ba38af5479 Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Fri, 14 Feb 2025 21:31:56 +0100 Subject: [PATCH 07/12] Add missing newline --- Lib/test/test_tools/i18n_data/comments.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_tools/i18n_data/comments.py b/Lib/test/test_tools/i18n_data/comments.py index c0b73d19fc4820..dca4dfa57b1dd9 100644 --- a/Lib/test/test_tools/i18n_data/comments.py +++ b/Lib/test/test_tools/i18n_data/comments.py @@ -75,4 +75,4 @@ ## i18n: This is a translator comment # # i18n: This is another translator comment ### ### i18n: This is yet another translator comment -_('foos') \ No newline at end of file +_('foos') From 91f5e9747b48f6335f71bae166d1774fcb608989 Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Fri, 14 Feb 2025 21:32:47 +0100 Subject: [PATCH 08/12] Remove extra newline --- Lib/test/test_tools/test_i18n.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Lib/test/test_tools/test_i18n.py b/Lib/test/test_tools/test_i18n.py index 7376675f35e74d..1f50f466998c74 100644 --- a/Lib/test/test_tools/test_i18n.py +++ b/Lib/test/test_tools/test_i18n.py @@ -439,7 +439,6 @@ def test_extract_all_comments(self): Test that the --add-comments option without an explicit tag extracts all translator comments. """ - for arg in ('--add-comments', '-c'): with self.subTest(arg=arg): data = self.extract_from_str(dedent('''\ From aef1e0bae73364e8c6dc4cad5558098e50219671 Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Sat, 15 Feb 2025 12:06:43 +0100 Subject: [PATCH 09/12] Use string.lstrip instead of re.sub --- Tools/i18n/pygettext.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Tools/i18n/pygettext.py b/Tools/i18n/pygettext.py index 20cea3367a972d..279c766a308ace 100755 --- a/Tools/i18n/pygettext.py +++ b/Tools/i18n/pygettext.py @@ -144,7 +144,6 @@ import importlib.machinery import importlib.util import os -import re import sys import time import tokenize @@ -331,7 +330,7 @@ def get_source_comments(source): for token in tokenize.tokenize(BytesIO(source).readline): if token.type == tokenize.COMMENT: # Remove any leading combination of '#' and whitespace - comment = re.sub(r'^[#\s]+', '', token.string) + comment = token.string.lstrip('# \t') comments[token.start[0]] = comment return comments From 7b98ba8ff8c3f29f3c45746d45fcdea4e3be068b Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Sat, 15 Feb 2025 12:14:41 +0100 Subject: [PATCH 10/12] Test multiple comment tags --- Lib/test/test_tools/test_i18n.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Lib/test/test_tools/test_i18n.py b/Lib/test/test_tools/test_i18n.py index 1f50f466998c74..2c5835347fb60b 100644 --- a/Lib/test/test_tools/test_i18n.py +++ b/Lib/test/test_tools/test_i18n.py @@ -447,6 +447,23 @@ def test_extract_all_comments(self): '''), args=(arg,), raw=True) self.assertIn('#. Translator comment', data) + def test_comments_with_multiple_tags(self): + """ + Test that multiple --add-comments tags can be specified. + """ + for arg in ('--add-comments={}', '-c{}'): + with self.subTest(arg=arg): + args = (arg.format('foo:'), arg.format('bar:')) + data = self.extract_from_str(dedent('''\ + # foo: comment + _("foo") + + # bar: comment + _("bar") + '''), args=args, raw=True) + self.assertIn('#. foo: comment', data) + self.assertIn('#. bar: comment', data) + def update_POT_snapshots(): for input_file in DATA_DIR.glob('*.py'): From d9ae56350f59c37bdd7cc5034f7186c77f0653c6 Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Sat, 15 Feb 2025 12:17:09 +0100 Subject: [PATCH 11/12] Test comments are not extracted unless a tag is given --- Lib/test/test_tools/test_i18n.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Lib/test/test_tools/test_i18n.py b/Lib/test/test_tools/test_i18n.py index 2c5835347fb60b..3d1be7e7cfe8b4 100644 --- a/Lib/test/test_tools/test_i18n.py +++ b/Lib/test/test_tools/test_i18n.py @@ -464,6 +464,17 @@ def test_comments_with_multiple_tags(self): self.assertIn('#. foo: comment', data) self.assertIn('#. bar: comment', data) + def test_comments_not_extracted_without_tags(self): + """ + Test that translator comments are not extracted without + specifying --add-comments. + """ + data = self.extract_from_str(dedent('''\ + # Translator comment + _("foo") + '''), raw=True) + self.assertNotIn('#.', data) + def update_POT_snapshots(): for input_file in DATA_DIR.glob('*.py'): From 56999b4997c5a60283affe1d062e0500c84be90a Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Sun, 16 Feb 2025 11:28:08 +0100 Subject: [PATCH 12/12] Add more tests --- Lib/test/test_tools/test_i18n.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Lib/test/test_tools/test_i18n.py b/Lib/test/test_tools/test_i18n.py index 3d1be7e7cfe8b4..208f08445773a8 100644 --- a/Lib/test/test_tools/test_i18n.py +++ b/Lib/test/test_tools/test_i18n.py @@ -460,9 +460,13 @@ def test_comments_with_multiple_tags(self): # bar: comment _("bar") + + # baz: comment + _("baz") '''), args=args, raw=True) self.assertIn('#. foo: comment', data) self.assertIn('#. bar: comment', data) + self.assertNotIn('#. baz: comment', data) def test_comments_not_extracted_without_tags(self): """