Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 4 additions & 2 deletions babel/messages/catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from difflib import SequenceMatcher
from email import message_from_string
from heapq import nlargest
from itertools import groupby
from string import Formatter
from typing import TYPE_CHECKING, TypedDict

Expand Down Expand Up @@ -181,8 +182,9 @@ def __init__(
self.flags.add('python-brace-format')
else:
self.flags.discard('python-brace-format')
self.auto_comments = list(dict.fromkeys(auto_comments)) if auto_comments else []
self.user_comments = list(dict.fromkeys(user_comments)) if user_comments else []
# Collapse consecutive repeats without losing repeated wrapped fragments.
self.auto_comments = [comment for comment, _ in groupby(auto_comments)] if auto_comments else []
self.user_comments = [comment for comment, _ in groupby(user_comments)] if user_comments else []
if previous_id:
if isinstance(previous_id, str):
self.previous_id = [previous_id]
Expand Down
19 changes: 19 additions & 0 deletions tests/messages/test_catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import pickle
from io import StringIO

import pytest

from babel.dates import UTC, format_datetime
from babel.messages import catalog, pofile
from babel.util import FixedOffsetTimezone
Expand Down Expand Up @@ -66,6 +68,23 @@ def test_message_translator_comments():
assert mess.auto_comments == ['Comment 1 About `foo`', 'Comment 2 About `foo`']


@pytest.mark.parametrize('attribute', ['auto_comments', 'user_comments'])
@pytest.mark.parametrize(
('comments', 'expected'),
[
([], []),
(['KEY:', 'KEY:', 'KEY:'], ['KEY:']),
(['KEY:', 'first', 'KEY:', 'second'], ['KEY:', 'first', 'KEY:', 'second']),
(['KEY:', 'KEY:', 'first', 'KEY:', 'KEY:'], ['KEY:', 'first', 'KEY:']),
(['', '', 'text', ''], ['', 'text', '']),
],
)
def test_message_collapses_only_consecutive_comment_lines(attribute, comments, expected):
message = catalog.Message('foo', **{attribute: iter(comments)})
assert getattr(message, attribute) == expected
assert getattr(message.clone(), attribute) == expected


def test_message_clone_message_object():
msg = catalog.Message('foo', locations=[('foo.py', 42)])
clone = msg.clone()
Expand Down
31 changes: 31 additions & 0 deletions tests/messages/test_pofile.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,37 @@
from babel.messages.pofile import _enclose_filename_if_necessary, _extract_locations


@pytest.mark.parametrize(
('prefix', 'attribute'),
[('#.', 'auto_comments'), ('#', 'user_comments')],
)
@pytest.mark.parametrize('obsolete', [False, True])
def test_read_po_preserves_repeated_comment_lines(prefix, attribute, obsolete):
comments = ['KEY:', 'first.long.key', 'KEY:', 'second.long.key']
source = '\n'.join(f'{prefix} {line}' for line in comments) + '\n'
message_prefix = '#~ ' if obsolete else ''
source += f'{message_prefix}msgid "Example"\n{message_prefix}msgstr ""\n'

catalog = pofile.read_po(StringIO(source))
message = catalog.obsolete['Example'] if obsolete else catalog['Example']
assert getattr(message, attribute) == comments


@pytest.mark.parametrize('attribute', ['auto_comments', 'user_comments'])
def test_wrapped_comments_roundtrip(attribute):
catalog = Catalog()
comments = ['KEY: ' + 'foo.' * 20, 'KEY: ' + 'bar.' * 20]
catalog.add('Example', **{attribute: comments})
first = BytesIO()
pofile.write_po(first, catalog, omit_header=True)
first.seek(0)

restored = pofile.read_po(first)
second = BytesIO()
pofile.write_po(second, restored, omit_header=True)
assert second.getvalue() == first.getvalue()


def test_enclosed_filenames_in_location_comment():
catalog = Catalog()
catalog.add("foo", lineno=2, locations=[("main 1.py", 1)], string="")
Expand Down