Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
4 changes: 2 additions & 2 deletions babel/messages/pofile.py
Original file line number Diff line number Diff line change
Expand Up @@ -637,8 +637,8 @@ def generate_po(
# provide the same behaviour
comment_width = width if width and width > 0 else 76

comment_wrapper = TextWrapper(width=comment_width)
header_wrapper = TextWrapper(width=width, subsequent_indent="# ")
comment_wrapper = TextWrapper(width=comment_width, break_long_words=False)
header_wrapper = TextWrapper(width=width, subsequent_indent="# ", break_long_words=False)

def _format_comment(comment, prefix=''):
for line in comment_wrapper.wrap(comment):
Expand Down
22 changes: 21 additions & 1 deletion babel/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import textwrap
import warnings
from collections.abc import Generator, Iterable
from itertools import chain
from typing import IO, Any, TypeVar

from babel import dates, localtime
Expand Down Expand Up @@ -205,10 +206,29 @@ class TextWrapper(textwrap.TextWrapper):
r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))', # em-dash
)

# e.g. '\u2068foo bar.py\u2069:42'
_enclosed_filename_re = re.compile(r'(\u2068[^\u2068]+?\u2069(?::-?\d+)?)')

def _split(self, text):
"""Splits the text into indivisible chunks while ensuring that file names
containing spaces are not broken up.
"""
enclosed_filename_start = '\u2068'
if enclosed_filename_start not in text:
# There are no file names which contain spaces, fallback to the default implementation
return super()._split(text)

super_ = super() # Python 3.9 fix, super() does not work in list comprehension
chunks = re.split(self._enclosed_filename_re, text)
chunks = [[c] if c.startswith(enclosed_filename_start) else super_._split(c) for c in chunks]
chunks = [c for c in chain.from_iterable(chunks) if c]
return chunks


def wraptext(text: str, width: int = 70, initial_indent: str = '', subsequent_indent: str = '') -> list[str]:
"""Simple wrapper around the ``textwrap.wrap`` function in the standard
library. This version does not wrap lines on hyphens in words.
library. This version does not wrap lines on hyphens in words. It also
does not wrap PO file locations containing spaces.

:param text: the text to wrap
:param width: the maximum line width
Expand Down
13 changes: 13 additions & 0 deletions tests/messages/test_pofile.py
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,19 @@ def test_tab_in_location_already_enclosed(self):
msgstr ""'''


def test_wrap_with_enclosed_file_locations(self):
# Ensure that file names containing white space are not wrapped regardless of the --width parameter
catalog = Catalog()
catalog.add('foo', locations=[('\u2068test utils.py\u2069', 1)])
catalog.add('foo', locations=[('\u2068test utils.py\u2069', 3)])
buf = BytesIO()
pofile.write_po(buf, catalog, omit_header=True, include_lineno=True, width=1)
assert buf.getvalue().strip() == b'''#: \xe2\x81\xa8test utils.py\xe2\x81\xa9:1
#: \xe2\x81\xa8test utils.py\xe2\x81\xa9:3
msgid "foo"
msgstr ""'''


class RoundtripPoTestCase(unittest.TestCase):

def test_enclosed_filenames_in_location_comment(self):
Expand Down