Author: jacob
Date: 2010-02-14 12:36:48 -0600 (Sun, 14 Feb 2010)
New Revision: 12431
Modified:
django/trunk/django/utils/text.py
django/trunk/tests/regressiontests/utils/tests.py
Log:
Fixed #6799 - added an `end_text` argument to
`truncate_words`/`truncate_html_words`.
This allows customizing the standard "..." end text. Yes, this is technically a
feature sneaking in after the deadline, but I just couldn't bring myself to punt
it again: we already used that excuse for not getting it into 1.1.
Thanks to Adam Fast and Travis Cline for work on this patch.
Modified: django/trunk/django/utils/text.py
===================================================================
--- django/trunk/django/utils/text.py 2010-02-14 18:33:01 UTC (rev 12430)
+++ django/trunk/django/utils/text.py 2010-02-14 18:36:48 UTC (rev 12431)
@@ -1,5 +1,4 @@
import re
-from django.conf import settings
from django.utils.encoding import force_unicode
from django.utils.functional import allow_lazy
from django.utils.translation import ugettext_lazy
@@ -37,24 +36,25 @@
return u''.join(_generator())
wrap = allow_lazy(wrap, unicode)
-def truncate_words(s, num):
- "Truncates a string after a certain number of words."
+def truncate_words(s, num, end_text='...'):
+ """Truncates a string after a certain number of words. Takes an optional
+ argument of what should be used to notify that the string has been
+ truncated, defaults to ellipsis (...)"""
s = force_unicode(s)
length = int(num)
words = s.split()
if len(words) > length:
words = words[:length]
- if not words[-1].endswith('...'):
- words.append('...')
+ if not words[-1].endswith(end_text):
+ words.append(end_text)
return u' '.join(words)
truncate_words = allow_lazy(truncate_words, unicode)
-def truncate_html_words(s, num):
- """
- Truncates html to a certain number of words (not counting tags and
+def truncate_html_words(s, num, end_text='...'):
+ """Truncates html to a certain number of words (not counting tags and
comments). Closes opened tags if they were correctly closed in the given
- html.
- """
+ html. Takes an optional argument of what should be used to notify that the
+ string has been truncated, defaults to ellipsis (...)."""
s = force_unicode(s)
length = int(num)
if length <= 0:
@@ -65,7 +65,7 @@
re_tag = re.compile(r'<(/)?([^ ]+?)(?: (/)| .*?)?>')
# Count non-HTML words and keep note of open tags
pos = 0
- ellipsis_pos = 0
+ end_text_pos = 0
words = 0
open_tags = []
while words <= length:
@@ -78,11 +78,11 @@
# It's an actual non-HTML word
words += 1
if words == length:
- ellipsis_pos = pos
+ end_text_pos = pos
continue
# Check for tag
tag = re_tag.match(m.group(0))
- if not tag or ellipsis_pos:
+ if not tag or end_text_pos:
# Don't worry about non tags or tags after our truncate point
continue
closing_tag, tagname, self_closing = tag.groups()
@@ -104,7 +104,9 @@
if words <= length:
# Don't try to close tags if we don't need to truncate
return s
- out = s[:ellipsis_pos] + ' ...'
+ out = s[:end_text_pos]
+ if end_text:
+ out += ' ' + end_text
# Close any tags still open
for tag in open_tags:
out += '</%s>' % tag
Modified: django/trunk/tests/regressiontests/utils/tests.py
===================================================================
--- django/trunk/tests/regressiontests/utils/tests.py 2010-02-14 18:33:01 UTC
(rev 12430)
+++ django/trunk/tests/regressiontests/utils/tests.py 2010-02-14 18:36:48 UTC
(rev 12431)
@@ -4,7 +4,7 @@
from unittest import TestCase
-from django.utils import html, checksums
+from django.utils import html, checksums, text
from django.utils.functional import SimpleLazyObject
import timesince
@@ -244,6 +244,24 @@
s3 = copy.deepcopy(s)
self.assertEqual(s3, complex_object())
+class TestUtilsText(TestCase):
+
+ def test_truncate_words(self):
+ self.assertEqual(u'The quick brown fox jumped over the lazy dog.',
+ text.truncate_words(u'The quick brown fox jumped over the lazy
dog.', 10))
+ self.assertEqual(u'The quick brown fox ...',
+ text.truncate_words('The quick brown fox jumped over the lazy
dog.', 4))
+ self.assertEqual(u'The quick brown fox ....',
+ text.truncate_words('The quick brown fox jumped over the lazy
dog.', 4, '....'))
+ self.assertEqual(u'<p><strong><em>The quick brown fox jumped over the
lazy dog.</em></strong></p>',
+ text.truncate_html_words('<p><strong><em>The quick brown fox
jumped over the lazy dog.</em></strong></p>', 10))
+ self.assertEqual(u'<p><strong><em>The quick brown fox
...</em></strong></p>',
+ text.truncate_html_words('<p><strong><em>The quick brown fox
jumped over the lazy dog.</em></strong></p>', 4))
+ self.assertEqual(u'<p><strong><em>The quick brown fox
....</em></strong></p>',
+ text.truncate_html_words('<p><strong><em>The quick brown fox
jumped over the lazy dog.</em></strong></p>', 4, '....'))
+ self.assertEqual(u'<p><strong><em>The quick brown
fox</em></strong></p>',
+ text.truncate_html_words('<p><strong><em>The quick brown fox
jumped over the lazy dog.</em></strong></p>', 4, None))
+
if __name__ == "__main__":
import doctest
doctest.testmod()
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/django-updates?hl=en.