From 5efb9272e2490bd27d448447e8a750cbcfd3e7ae Mon Sep 17 00:00:00 2001 From: Jacob Kaplan-Moss Date: Fri, 15 Dec 2006 19:05:57 +0000 Subject: [PATCH] Vastly improved performance of django.utils.text.wrap. Thanks to GvR for the impetus and Micael Radziej for the patch. git-svn-id: http://code.djangoproject.com/svn/django/trunk@4213 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/utils/text.py | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/django/utils/text.py b/django/utils/text.py index 9e7bb3b6c4..217f42491b 100644 --- a/django/utils/text.py +++ b/django/utils/text.py @@ -8,17 +8,28 @@ capfirst = lambda x: x and x[0].upper() + x[1:] 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 (\n). - See http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/148061 + the text. Expects that existing line breaks are posix newlines. """ - return reduce(lambda line, word, width=width: '%s%s%s' % - (line, - ' \n'[(len(line[line.rfind('\n')+1:]) - + len(word.split('\n',1)[0] - ) >= width)], - word), - text.split(' ') - ) + def _generator(): + it = iter(text.split(' ')) + word = it.next() + yield word + pos = len(word) - word.rfind('\n') - 1 + for word in it: + if "\n" in word: + lines = word.splitlines() + 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 + return "".join(_generator()) def truncate_words(s, num): "Truncates a string after a certain number of words."