From acb20016c0567876e7fc8144ecbe77905ee8388a Mon Sep 17 00:00:00 2001 From: Markus Amalthea Magnuson Date: Fri, 16 May 2014 18:39:03 +0200 Subject: [PATCH] Fixed #6668 -- Optimized utils.text wrap function This fixes a failing test after applying an optimization of the utils.text.wrap function by user SmileyChris. --- django/utils/text.py | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/django/utils/text.py b/django/utils/text.py index df6e1d0c46..68eb713026 100644 --- a/django/utils/text.py +++ b/django/utils/text.py @@ -34,30 +34,33 @@ re_camel_case = re.compile(r'(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))') def wrap(text, width): """ - A word-wrap function that preserves existing line breaks and most spaces in - the text. Expects that existing line breaks are posix newlines. + A word-wrap function that preserves existing line breaks. Expects that + existing line breaks are posix newlines. + + All white space is preserved except added line breaks consume the space on + which they break the line. + + Long words are not wrapped, so the output text may have lines longer than + ``width``. """ text = force_text(text) def _generator(): - it = iter(text.split(' ')) - word = next(it) - yield word - pos = len(word) - word.rfind('\n') - 1 - for word in it: - if "\n" in word: - lines = word.split('\n') - else: - lines = (word,) - pos += len(lines[0]) + 1 - if pos > width: - yield '\n' - pos = len(lines[-1]) - else: - yield ' ' - if len(lines) > 1: - pos = len(lines[-1]) - yield word + for line in text.splitlines(True): # True keeps trailing linebreaks + max_width = min((line.endswith('\n') and width + 1 or width), width) + while len(line) > max_width: + space = line[:max_width + 1].rfind(' ') + 1 + if space == 0: + space = line.find(' ') + 1 + if space == 0: + yield line + line = '' + break + yield '%s\n' % line[:space - 1] + line = line[space:] + max_width = min((line.endswith('\n') and width + 1 or width), width) + if line: + yield line return ''.join(_generator()) wrap = allow_lazy(wrap, six.text_type)