Skip to content

Commit 9d25e67

Browse files
tomasr8akx
andauthored
Prevent wrapping file locations containing white space (#1120)
Co-authored-by: Aarni Koskela <[email protected]>
1 parent b3c105e commit 9d25e67

File tree

3 files changed

+37
-3
lines changed

3 files changed

+37
-3
lines changed

babel/messages/pofile.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -637,8 +637,8 @@ def generate_po(
637637
# provide the same behaviour
638638
comment_width = width if width and width > 0 else 76
639639

640-
comment_wrapper = TextWrapper(width=comment_width)
641-
header_wrapper = TextWrapper(width=width, subsequent_indent="# ")
640+
comment_wrapper = TextWrapper(width=comment_width, break_long_words=False)
641+
header_wrapper = TextWrapper(width=width, subsequent_indent="# ", break_long_words=False)
642642

643643
def _format_comment(comment, prefix=''):
644644
for line in comment_wrapper.wrap(comment):

babel/util.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,10 +205,31 @@ class TextWrapper(textwrap.TextWrapper):
205205
r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))', # em-dash
206206
)
207207

208+
# e.g. '\u2068foo bar.py\u2069:42'
209+
_enclosed_filename_re = re.compile(r'(\u2068[^\u2068]+?\u2069(?::-?\d+)?)')
210+
211+
def _split(self, text):
212+
"""Splits the text into indivisible chunks while ensuring that file names
213+
containing spaces are not broken up.
214+
"""
215+
enclosed_filename_start = '\u2068'
216+
if enclosed_filename_start not in text:
217+
# There are no file names which contain spaces, fallback to the default implementation
218+
return super()._split(text)
219+
220+
chunks = []
221+
for chunk in re.split(self._enclosed_filename_re, text):
222+
if chunk.startswith(enclosed_filename_start):
223+
chunks.append(chunk)
224+
else:
225+
chunks.extend(super()._split(chunk))
226+
return [c for c in chunks if c]
227+
208228

209229
def wraptext(text: str, width: int = 70, initial_indent: str = '', subsequent_indent: str = '') -> list[str]:
210230
"""Simple wrapper around the ``textwrap.wrap`` function in the standard
211-
library. This version does not wrap lines on hyphens in words.
231+
library. This version does not wrap lines on hyphens in words. It also
232+
does not wrap PO file locations containing spaces.
212233
213234
:param text: the text to wrap
214235
:param width: the maximum line width

tests/messages/test_pofile.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -948,6 +948,19 @@ def test_tab_in_location_already_enclosed(self):
948948
msgstr ""'''
949949

950950

951+
def test_wrap_with_enclosed_file_locations(self):
952+
# Ensure that file names containing white space are not wrapped regardless of the --width parameter
953+
catalog = Catalog()
954+
catalog.add('foo', locations=[('\u2068test utils.py\u2069', 1)])
955+
catalog.add('foo', locations=[('\u2068test utils.py\u2069', 3)])
956+
buf = BytesIO()
957+
pofile.write_po(buf, catalog, omit_header=True, include_lineno=True, width=1)
958+
assert buf.getvalue().strip() == b'''#: \xe2\x81\xa8test utils.py\xe2\x81\xa9:1
959+
#: \xe2\x81\xa8test utils.py\xe2\x81\xa9:3
960+
msgid "foo"
961+
msgstr ""'''
962+
963+
951964
class RoundtripPoTestCase(unittest.TestCase):
952965

953966
def test_enclosed_filenames_in_location_comment(self):

0 commit comments

Comments
 (0)