1
0
mirror of https://github.com/django/django.git synced 2025-07-04 17:59:13 +00:00

Changed default template filters to always return unicode (and to handle unicode input better). Also changed all django.utils.* functions that are used (or likely to be used) by filters to return unicode strings.

Most of the filter porting was done by Ivan Sagalaev. Fixed #3977.


git-svn-id: http://code.djangoproject.com/svn/django/branches/unicode@5056 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2007-04-21 14:34:43 +00:00
parent dadbe3c737
commit b30e5b5434
11 changed files with 356 additions and 370 deletions

View File

@ -2,7 +2,8 @@
from django.template import resolve_variable, Library
from django.conf import settings
from django.utils.translation import gettext
from django.utils.translation import ugettext
from django.utils.encoding import smart_unicode, smart_str
import re
import random as random_module
@ -12,27 +13,15 @@ register = Library()
# STRING DECORATOR #
#######################
def smart_string(obj):
# FUTURE: Unicode strings should probably be normalized to a specific
# encoding and non-unicode strings should be converted to unicode too.
# if isinstance(obj, unicode):
# obj = obj.encode(settings.DEFAULT_CHARSET)
# else:
# obj = unicode(obj, settings.DEFAULT_CHARSET)
# FUTURE: Replace dumb string logic below with cool unicode logic above.
if not isinstance(obj, basestring):
obj = str(obj)
return obj
def stringfilter(func):
"""
Decorator for filters which should only receive strings. The object passed
as the first positional argument will be converted to a string.
Decorator for filters which should only receive unicode objects. The object passed
as the first positional argument will be converted to a unicode object.
"""
def _dec(*args, **kwargs):
if args:
args = list(args)
args[0] = smart_string(args[0])
args[0] = smart_unicode(args[0])
return func(*args, **kwargs)
# Include a reference to the real function (used to check original
@ -83,27 +72,27 @@ def floatformat(text, arg=-1):
try:
f = float(text)
except ValueError:
return ''
return u''
try:
d = int(arg)
except ValueError:
return smart_string(f)
return smart_unicode(f)
m = f - int(f)
if not m and d < 0:
return '%d' % int(f)
return u'%d' % int(f)
else:
formatstr = '%%.%df' % abs(d)
formatstr = u'%%.%df' % abs(d)
return formatstr % f
def linenumbers(value):
"Displays text with line numbers"
from django.utils.html import escape
lines = value.split('\n')
lines = value.split(u'\n')
# Find the maximum width of the line count, for use with zero padding string format command
width = str(len(str(len(lines))))
width = unicode(len(unicode(len(lines))))
for i, line in enumerate(lines):
lines[i] = ("%0" + width + "d. %s") % (i + 1, escape(line))
return '\n'.join(lines)
lines[i] = (u"%0" + width + u"d. %s") % (i + 1, escape(line))
return u'\n'.join(lines)
linenumbers = stringfilter(linenumbers)
def lower(value):
@ -121,6 +110,7 @@ make_list = stringfilter(make_list)
def slugify(value):
"Converts to lowercase, removes non-alpha chars and converts spaces to hyphens"
# Don't compile patterns as unicode because \w then would mean any letter. Slugify is effectively an asciiization.
value = re.sub('[^\w\s-]', '', value).strip().lower()
return re.sub('[-\s]+', '-', value)
slugify = stringfilter(slugify)
@ -135,9 +125,9 @@ def stringformat(value, arg):
of Python string formatting
"""
try:
return ("%" + str(arg)) % value
return (u"%" + unicode(arg)) % value
except (ValueError, TypeError):
return ""
return u""
def title(value):
"Converts a string into titlecase"
@ -155,8 +145,6 @@ def truncatewords(value, arg):
length = int(arg)
except ValueError: # invalid literal for int()
return value # Fail silently.
if not isinstance(value, basestring):
value = str(value)
return truncate_words(value, length)
truncatewords = stringfilter(truncatewords)
@ -171,8 +159,6 @@ def truncatewords_html(value, arg):
length = int(arg)
except ValueError: # invalid literal for int()
return value # Fail silently.
if not isinstance(value, basestring):
value = str(value)
return truncate_html_words(value, length)
truncatewords_html = stringfilter(truncatewords_html)
@ -184,9 +170,7 @@ upper = stringfilter(upper)
def urlencode(value):
"Escapes a value for use in a URL"
import urllib
if not isinstance(value, basestring):
value = str(value)
return urllib.quote(value)
return urllib.quote(value).decode('utf-8')
urlencode = stringfilter(urlencode)
def urlize(value):
@ -246,7 +230,7 @@ center = stringfilter(center)
def cut(value, arg):
"Removes all values of arg from the given string"
return value.replace(arg, '')
return value.replace(arg, u'')
cut = stringfilter(cut)
###################
@ -273,11 +257,11 @@ linebreaksbr = stringfilter(linebreaksbr)
def removetags(value, tags):
"Removes a space separated list of [X]HTML tags from the output"
tags = [re.escape(tag) for tag in tags.split()]
tags_re = '(%s)' % '|'.join(tags)
starttag_re = re.compile(r'<%s(/?>|(\s+[^>]*>))' % tags_re)
endtag_re = re.compile('</%s>' % tags_re)
value = starttag_re.sub('', value)
value = endtag_re.sub('', value)
tags_re = u'(%s)' % u'|'.join(tags)
starttag_re = re.compile(ur'<%s(/?>|(\s+[^>]*>))' % tags_re, re.U)
endtag_re = re.compile(u'</%s>' % tags_re)
value = starttag_re.sub(u'', value)
value = endtag_re.sub(u'', value)
return value
removetags = stringfilter(removetags)
@ -296,7 +280,7 @@ def dictsort(value, arg):
Takes a list of dicts, returns that list sorted by the property given in
the argument.
"""
decorated = [(resolve_variable('var.' + arg, {'var' : item}), item) for item in value]
decorated = [(resolve_variable(u'var.' + arg, {u'var' : item}), item) for item in value]
decorated.sort()
return [item[1] for item in decorated]
@ -305,7 +289,7 @@ def dictsortreversed(value, arg):
Takes a list of dicts, returns that list sorted in reverse order by the
property given in the argument.
"""
decorated = [(resolve_variable('var.' + arg, {'var' : item}), item) for item in value]
decorated = [(resolve_variable(u'var.' + arg, {u'var' : item}), item) for item in value]
decorated.sort()
decorated.reverse()
return [item[1] for item in decorated]
@ -315,12 +299,12 @@ def first(value):
try:
return value[0]
except IndexError:
return ''
return u''
def join(value, arg):
"Joins a list with a string, like Python's ``str.join(list)``"
try:
return arg.join(map(smart_string, value))
return arg.join(map(smart_unicode, value))
except AttributeError: # fail silently but nicely
return value
@ -346,7 +330,7 @@ def slice_(value, arg):
"""
try:
bits = []
for x in arg.split(':'):
for x in arg.split(u':'):
if len(x) == 0:
bits.append(None)
else:
@ -378,12 +362,12 @@ def unordered_list(value):
</li>
"""
def _helper(value, tabs):
indent = '\t' * tabs
indent = u'\t' * tabs
if value[1]:
return '%s<li>%s\n%s<ul>\n%s\n%s</ul>\n%s</li>' % (indent, value[0], indent,
'\n'.join([_helper(v, tabs+1) for v in value[1]]), indent, indent)
return u'%s<li>%s\n%s<ul>\n%s\n%s</ul>\n%s</li>' % (indent, value[0], indent,
u'\n'.join([_helper(v, tabs+1) for v in value[1]]), indent, indent)
else:
return '%s<li>%s</li>' % (indent, value[0])
return u'%s<li>%s</li>' % (indent, value[0])
return _helper(value, 1)
###################
@ -421,7 +405,7 @@ def date(value, arg=None):
"Formats a date according to the given format"
from django.utils.dateformat import format
if not value:
return ''
return u''
if arg is None:
arg = settings.DATE_FORMAT
return format(value, arg)
@ -429,8 +413,8 @@ def date(value, arg=None):
def time(value, arg=None):
"Formats a time according to the given format"
from django.utils.dateformat import time_format
if value in (None, ''):
return ''
if value in (None, u''):
return u''
if arg is None:
arg = settings.TIME_FORMAT
return time_format(value, arg)
@ -439,7 +423,7 @@ def timesince(value, arg=None):
'Formats a date as the time since that date (i.e. "4 days, 6 hours")'
from django.utils.timesince import timesince
if not value:
return ''
return u''
if arg:
return timesince(arg, value)
return timesince(value)
@ -449,7 +433,7 @@ def timeuntil(value, arg=None):
from django.utils.timesince import timesince
from datetime import datetime
if not value:
return ''
return u''
if arg:
return timesince(arg, value)
return timesince(datetime.now(), value)
@ -488,8 +472,8 @@ def yesno(value, arg=None):
========== ====================== ==================================
"""
if arg is None:
arg = gettext('yes,no,maybe')
bits = arg.split(',')
arg = ugettext('yes,no,maybe')
bits = arg.split(u',')
if len(bits) < 2:
return value # Invalid arg.
try:
@ -514,28 +498,28 @@ def filesizeformat(bytes):
try:
bytes = float(bytes)
except TypeError:
return "0 bytes"
return u"0 bytes"
if bytes < 1024:
return "%d byte%s" % (bytes, bytes != 1 and 's' or '')
return u"%d byte%s" % (bytes, bytes != 1 and u's' or u'')
if bytes < 1024 * 1024:
return "%.1f KB" % (bytes / 1024)
return u"%.1f KB" % (bytes / 1024)
if bytes < 1024 * 1024 * 1024:
return "%.1f MB" % (bytes / (1024 * 1024))
return "%.1f GB" % (bytes / (1024 * 1024 * 1024))
return u"%.1f MB" % (bytes / (1024 * 1024))
return u"%.1f GB" % (bytes / (1024 * 1024 * 1024))
def pluralize(value, arg='s'):
def pluralize(value, arg=u's'):
"""
Returns a plural suffix if the value is not 1, for '1 vote' vs. '2 votes'
By default, 's' is used as a suffix; if an argument is provided, that string
is used instead. If the provided argument contains a comma, the text before
the comma is used for the singular case.
"""
if not ',' in arg:
arg = ',' + arg
bits = arg.split(',')
if not u',' in arg:
arg = u',' + arg
bits = arg.split(u',')
if len(bits) > 2:
return ''
return u''
singular_suffix, plural_suffix = bits[:2]
try:
@ -562,7 +546,7 @@ def pprint(value):
try:
return pformat(value)
except Exception, e:
return "Error in formatting:%s" % e
return u"Error in formatting:%s" % e
# Syntax: register.filter(name of filter, callback)
register.filter(add)

View File

@ -13,7 +13,7 @@ Usage:
from django.utils.dates import MONTHS, MONTHS_3, MONTHS_AP, WEEKDAYS
from django.utils.tzinfo import LocalTimezone
from django.utils.translation import gettext as _
from django.utils.translation import ugettext as _
from calendar import isleap, monthrange
import re, time
@ -28,7 +28,7 @@ class Formatter(object):
pieces.append(str(getattr(self, piece)()))
elif piece:
pieces.append(re_escaped.sub(r'\1', piece))
return ''.join(pieces)
return u''.join(pieces)
class TimeFormat(Formatter):
def __init__(self, t):
@ -52,13 +52,14 @@ class TimeFormat(Formatter):
def f(self):
"""
Time, in 12-hour hours and minutes, with minutes left off if they're zero.
Time, in 12-hour hours and minutes, with minutes left off if they're
zero.
Examples: '1', '1:30', '2:05', '2'
Proprietary extension.
"""
if self.data.minute == 0:
return self.g()
return '%s:%s' % (self.g(), self.i())
return u'%s:%s' % (self.g(), self.i())
def g(self):
"Hour, 12-hour format without leading zeros; i.e. '1' to '12'"
@ -74,15 +75,15 @@ class TimeFormat(Formatter):
def h(self):
"Hour, 12-hour format; i.e. '01' to '12'"
return '%02d' % self.g()
return u'%02d' % self.g()
def H(self):
"Hour, 24-hour format; i.e. '00' to '23'"
return '%02d' % self.G()
return u'%02d' % self.G()
def i(self):
"Minutes; i.e. '00' to '59'"
return '%02d' % self.data.minute
return u'%02d' % self.data.minute
def P(self):
"""
@ -95,11 +96,11 @@ class TimeFormat(Formatter):
return _('midnight')
if self.data.minute == 0 and self.data.hour == 12:
return _('noon')
return '%s %s' % (self.f(), self.a())
return u'%s %s' % (self.f(), self.a())
def s(self):
"Seconds; i.e. '00' to '59'"
return '%02d' % self.data.second
return u'%02d' % self.data.second
class DateFormat(TimeFormat):
year_days = [None, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]
@ -117,7 +118,7 @@ class DateFormat(TimeFormat):
def d(self):
"Day of the month, 2 digits with leading zeros; i.e. '01' to '31'"
return '%02d' % self.data.day
return u'%02d' % self.data.day
def D(self):
"Day of the week, textual, 3 letters; e.g. 'Fri'"
@ -130,9 +131,9 @@ class DateFormat(TimeFormat):
def I(self):
"'1' if Daylight Savings Time, '0' otherwise."
if self.timezone.dst(self.data):
return '1'
return u'1'
else:
return '0'
return u'0'
def j(self):
"Day of the month without leading zeros; i.e. '1' to '31'"
@ -148,7 +149,7 @@ class DateFormat(TimeFormat):
def m(self):
"Month; i.e. '01' to '12'"
return '%02d' % self.data.month
return u'%02d' % self.data.month
def M(self):
"Month, textual, 3 letters; e.g. 'Jan'"
@ -165,7 +166,7 @@ class DateFormat(TimeFormat):
def O(self):
"Difference to Greenwich time in hours; e.g. '+0200'"
tz = self.timezone.utcoffset(self.data)
return "%+03d%02d" % (tz.seconds // 3600, (tz.seconds // 60) % 60)
return u"%+03d%02d" % (tz.seconds // 3600, (tz.seconds // 60) % 60)
def r(self):
"RFC 822 formatted date; e.g. 'Thu, 21 Dec 2000 16:01:07 +0200'"
@ -174,26 +175,26 @@ class DateFormat(TimeFormat):
def S(self):
"English ordinal suffix for the day of the month, 2 characters; i.e. 'st', 'nd', 'rd' or 'th'"
if self.data.day in (11, 12, 13): # Special case
return 'th'
return u'th'
last = self.data.day % 10
if last == 1:
return 'st'
return u'st'
if last == 2:
return 'nd'
return u'nd'
if last == 3:
return 'rd'
return 'th'
return u'rd'
return u'th'
def t(self):
"Number of days in the given month; i.e. '28' to '31'"
return '%02d' % monthrange(self.data.year, self.data.month)[1]
return u'%02d' % monthrange(self.data.year, self.data.month)[1]
def T(self):
"Time zone of this machine; e.g. 'EST' or 'MDT'"
name = self.timezone.tzname(self.data)
if name is None:
name = self.format('O')
return name
return unicode(name)
def U(self):
"Seconds since the Unix epoch (January 1 1970 00:00:00 GMT)"
@ -232,7 +233,7 @@ class DateFormat(TimeFormat):
def y(self):
"Year, 2 digits; e.g. '99'"
return str(self.data.year)[2:]
return unicode(self.data.year)[2:]
def Y(self):
"Year, 4 digits; e.g. '1999'"

View File

@ -1,6 +1,6 @@
"Commonly-used date structures"
from django.utils.translation import gettext_lazy as _
from django.utils.translation import ugettext_lazy as _
WEEKDAYS = {
0:_('Monday'), 1:_('Tuesday'), 2:_('Wednesday'), 3:_('Thursday'), 4:_('Friday'),

View File

@ -25,7 +25,7 @@ del x # Temporary variable
def escape(html):
"Returns the given HTML with ampersands, quotes and carets encoded"
if not isinstance(html, basestring):
html = str(html)
html = smart_unicode(html)
return html.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;').replace('"', '&quot;').replace("'", '&#39;')
def linebreaks(value):
@ -33,7 +33,7 @@ def linebreaks(value):
value = re.sub(r'\r\n|\r|\n', '\n', value) # normalize newlines
paras = re.split('\n{2,}', value)
paras = ['<p>%s</p>' % p.strip().replace('\n', '<br />') for p in paras]
return '\n\n'.join(paras)
return u'\n\n'.join(paras)
def strip_tags(value):
"Returns the given HTML with all tags stripped"
@ -80,7 +80,7 @@ def urlize(text, trim_url_limit=None, nofollow=False):
middle = '<a href="mailto:%s">%s</a>' % (middle, middle)
if lead + middle + trail != word:
words[i] = lead + middle + trail
return ''.join(words)
return u''.join(words)
def clean_html(text):
"""
@ -108,7 +108,7 @@ def clean_html(text):
s = match.group().replace('</p>', '</li>')
for d in DOTS:
s = s.replace('<p>%s' % d, '<li>')
return '<ul>\n%s\n</ul>' % s
return u'<ul>\n%s\n</ul>' % s
text = hard_coded_bullets_re.sub(replace_p_tags, text)
# Remove stuff like "<p>&nbsp;&nbsp;</p>", but only if it's at the bottom of the text.
text = trailing_empty_content_re.sub('', text)

View File

@ -38,5 +38,5 @@ def strip_stopwords(sentence):
for word in words:
if word.lower() not in stopwords:
sentence.append(word)
return ' '.join(sentence)
return u' '.join(sentence)

View File

@ -1,6 +1,6 @@
import re
from django.conf import settings
from django.utils.encoding import smart_unicode
# Capitalizes the first letter of a string.
capfirst = lambda x: x and x[0].upper() + x[1:]
@ -10,6 +10,7 @@ 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.
"""
text = smart_unicode(text)
def _generator():
it = iter(text.split(' '))
word = it.next()
@ -29,26 +30,29 @@ def wrap(text, width):
if len(lines) > 1:
pos = len(lines[-1])
yield word
return "".join(_generator())
return u''.join(_generator())
def truncate_words(s, num):
"Truncates a string after a certain number of words."
s = smart_unicode(s)
length = int(num)
words = s.split()
if len(words) > length:
words = words[:length]
if not words[-1].endswith('...'):
words.append('...')
return ' '.join(words)
return u' '.join(words)
def truncate_html_words(s, num):
"""
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.
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.
"""
s = smart_unicode(s)
length = int(num)
if length <= 0:
return ''
return u''
html4_singlets = ('br', 'col', 'link', 'base', 'img', 'param', 'area', 'hr', 'input')
# Set up regular expressions
re_words = re.compile(r'&.*?;|<.*?>|([A-Za-z0-9][\w-]*)')
@ -110,10 +114,10 @@ def get_valid_filename(s):
>>> get_valid_filename("john's portrait in 2004.jpg")
'johns_portrait_in_2004.jpg'
"""
s = s.strip().replace(' ', '_')
s = smart_unicode(s).strip().replace(' ', '_')
return re.sub(r'[^-A-Za-z0-9_.]', '', s)
def get_text_list(list_, last_word='or'):
def get_text_list(list_, last_word=u'or'):
"""
>>> get_text_list(['a', 'b', 'c', 'd'])
'a, b, c or d'
@ -126,22 +130,18 @@ def get_text_list(list_, last_word='or'):
>>> get_text_list([])
''
"""
if len(list_) == 0: return ''
if len(list_) == 1: return list_[0]
return '%s %s %s' % (', '.join([str(i) for i in list_][:-1]), last_word, list_[-1])
if len(list_) == 0: return u''
if len(list_) == 1: return smart_unicode(list_[0])
return u'%s %s %s' % (', '.join([smart_unicode(i) for i in list_][:-1]), smart_unicode(last_word), smart_unicode(list_[-1]))
def normalize_newlines(text):
return re.sub(r'\r\n|\r|\n', '\n', text)
return smart_unicode(re.sub(r'\r\n|\r|\n', '\n', text))
def recapitalize(text):
"Recapitalizes text, placing caps after end-of-sentence punctuation."
# capwords = ()
text = text.lower()
text = smart_unicode(text).lower()
capsRE = re.compile(r'(?:^|(?<=[\.\?\!] ))([a-z])')
text = capsRE.sub(lambda x: x.group(1).upper(), text)
# for capword in capwords:
# capwordRE = re.compile(r'\b%s\b' % capword, re.I)
# text = capwordRE.sub(capword, text)
return text
def phone2numeric(phone):
@ -172,7 +172,7 @@ def javascript_quote(s, quote_double_quotes=False):
return r"\u%04x" % ord(match.group(1))
if type(s) == str:
s = s.decode(settings.DEFAULT_CHARSET)
s = s.decode('utf-8')
elif type(s) != unicode:
raise TypeError, s
s = s.replace('\\', '\\\\')
@ -195,6 +195,7 @@ def smart_split(text):
>>> list(smart_split('This is "a person\'s" test.'))
['This', 'is', '"a person\'s"', 'test.']
"""
text = smart_unicode(text)
for bit in smart_split_re.finditer(text):
bit = bit.group(0)
if bit[0] == '"' and bit[-1] == '"':

View File

@ -1,6 +1,6 @@
import datetime, math, time
from django.utils.tzinfo import LocalTimezone
from django.utils.translation import ngettext
from django.utils.translation import ungettext
def timesince(d, now=None):
"""
@ -9,12 +9,12 @@ def timesince(d, now=None):
Adapted from http://blog.natbat.co.uk/archive/2003/Jun/14/time_since
"""
chunks = (
(60 * 60 * 24 * 365, lambda n: ngettext('year', 'years', n)),
(60 * 60 * 24 * 30, lambda n: ngettext('month', 'months', n)),
(60 * 60 * 24 * 7, lambda n : ngettext('week', 'weeks', n)),
(60 * 60 * 24, lambda n : ngettext('day', 'days', n)),
(60 * 60, lambda n: ngettext('hour', 'hours', n)),
(60, lambda n: ngettext('minute', 'minutes', n))
(60 * 60 * 24 * 365, lambda n: ungettext('year', 'years', n)),
(60 * 60 * 24 * 30, lambda n: ungettext('month', 'months', n)),
(60 * 60 * 24 * 7, lambda n : ungettext('week', 'weeks', n)),
(60 * 60 * 24, lambda n : ungettext('day', 'days', n)),
(60 * 60, lambda n: ungettext('hour', 'hours', n)),
(60, lambda n: ungettext('minute', 'minutes', n))
)
# Convert datetime.date to datetime.datetime for comparison
if d.__class__ is not datetime.datetime:
@ -37,8 +37,8 @@ def timesince(d, now=None):
if count != 0:
break
if count < 0:
return '%d milliseconds' % math.floor((now - d).microseconds / 1000)
s = '%d %s' % (count, name(count))
return u'%d milliseconds' % math.floor((now - d).microseconds / 1000)
s = u'%d %s' % (count, name(count))
if i + 1 < len(chunks):
# Now get the second item
seconds2, name2 = chunks[i + 1]

View File

@ -7,7 +7,7 @@ class FixedOffset(tzinfo):
"Fixed offset in minutes east from UTC."
def __init__(self, offset):
self.__offset = timedelta(minutes=offset)
self.__name = "%+03d%02d" % (offset // 60, offset % 60)
self.__name = u"%+03d%02d" % (offset // 60, offset % 60)
def __repr__(self):
return self.__name
@ -25,7 +25,7 @@ class LocalTimezone(tzinfo):
"Proxy timezone information from time module."
def __init__(self, dt):
tzinfo.__init__(self, dt)
self._tzname = time.tzname[self._isdst(dt)]
self._tzname = unicode(time.tzname[self._isdst(dt)])
def __repr__(self):
return self._tzname
@ -43,7 +43,7 @@ class LocalTimezone(tzinfo):
return timedelta(0)
def tzname(self, dt):
return time.tzname[self._isdst(dt)]
return unicode(time.tzname[self._isdst(dt)])
def _isdst(self, dt):
tt = (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.weekday(), 0, -1)

View File

@ -1,54 +1,54 @@
r"""
>>> format(my_birthday, '')
''
u''
>>> format(my_birthday, 'a')
'p.m.'
u'p.m.'
>>> format(my_birthday, 'A')
'PM'
u'PM'
>>> format(my_birthday, 'd')
'08'
u'08'
>>> format(my_birthday, 'j')
'8'
u'8'
>>> format(my_birthday, 'l')
'Sunday'
u'Sunday'
>>> format(my_birthday, 'L')
'False'
u'False'
>>> format(my_birthday, 'm')
'07'
u'07'
>>> format(my_birthday, 'M')
'Jul'
u'Jul'
>>> format(my_birthday, 'b')
'jul'
u'jul'
>>> format(my_birthday, 'n')
'7'
u'7'
>>> format(my_birthday, 'N')
'July'
u'July'
>>> no_tz or format(my_birthday, 'O') == '+0100'
True
>>> format(my_birthday, 'P')
'10 p.m.'
u'10 p.m.'
>>> no_tz or format(my_birthday, 'r') == 'Sun, 8 Jul 1979 22:00:00 +0100'
True
>>> format(my_birthday, 's')
'00'
u'00'
>>> format(my_birthday, 'S')
'th'
u'th'
>>> format(my_birthday, 't')
'31'
u'31'
>>> no_tz or format(my_birthday, 'T') == 'CET'
True
>>> no_tz or format(my_birthday, 'U') == '300531600'
True
>>> format(my_birthday, 'w')
'0'
u'0'
>>> format(my_birthday, 'W')
'27'
u'27'
>>> format(my_birthday, 'y')
'79'
u'79'
>>> format(my_birthday, 'Y')
'1979'
u'1979'
>>> format(my_birthday, 'z')
'189'
u'189'
>>> no_tz or format(my_birthday, 'Z') == '3600'
True
@ -62,10 +62,10 @@ True
True
>>> format(my_birthday, r'Y z \C\E\T')
'1979 189 CET'
u'1979 189 CET'
>>> format(my_birthday, r'jS o\f F')
'8th of July'
u'8th of July'
"""
from django.utils import dateformat, translation

View File

@ -2,186 +2,186 @@
r"""
>>> floatformat(7.7)
'7.7'
u'7.7'
>>> floatformat(7.0)
'7'
u'7'
>>> floatformat(0.7)
'0.7'
u'0.7'
>>> floatformat(0.07)
'0.1'
u'0.1'
>>> floatformat(0.007)
'0.0'
u'0.0'
>>> floatformat(0.0)
'0'
u'0'
>>> floatformat(7.7,3)
'7.700'
u'7.700'
>>> floatformat(6.000000,3)
'6.000'
u'6.000'
>>> floatformat(13.1031,-3)
'13.103'
u'13.103'
>>> floatformat(11.1197, -2)
'11.12'
u'11.12'
>>> floatformat(11.0000, -2)
'11'
u'11'
>>> floatformat(11.000001, -2)
'11.00'
u'11.00'
>>> floatformat(8.2798, 3)
'8.280'
>>> floatformat('foo')
''
>>> floatformat(13.1031, 'bar')
'13.1031'
>>> floatformat('foo', 'bar')
''
u'8.280'
>>> floatformat(u'foo')
u''
>>> floatformat(13.1031, u'bar')
u'13.1031'
>>> floatformat(u'foo', u'bar')
u''
>>> addslashes('"double quotes" and \'single quotes\'')
'\\"double quotes\\" and \\\'single quotes\\\''
>>> addslashes(u'"double quotes" and \'single quotes\'')
u'\\"double quotes\\" and \\\'single quotes\\\''
>>> addslashes(r'\ : backslashes, too')
'\\\\ : backslashes, too'
>>> addslashes(ur'\ : backslashes, too')
u'\\\\ : backslashes, too'
>>> capfirst('hello world')
'Hello world'
>>> capfirst(u'hello world')
u'Hello world'
>>> fix_ampersands('Jack & Jill & Jeroboam')
'Jack &amp; Jill &amp; Jeroboam'
>>> fix_ampersands(u'Jack & Jill & Jeroboam')
u'Jack &amp; Jill &amp; Jeroboam'
>>> linenumbers('line 1\nline 2')
'1. line 1\n2. line 2'
>>> linenumbers(u'line 1\nline 2')
u'1. line 1\n2. line 2'
>>> linenumbers('\n'.join(['x'] * 10))
'01. x\n02. x\n03. x\n04. x\n05. x\n06. x\n07. x\n08. x\n09. x\n10. x'
>>> linenumbers(u'\n'.join([u'x'] * 10))
u'01. x\n02. x\n03. x\n04. x\n05. x\n06. x\n07. x\n08. x\n09. x\n10. x'
>>> lower('TEST')
'test'
u'test'
>>> lower(u'\xcb') # uppercase E umlaut
u'\xeb'
>>> make_list('abc')
['a', 'b', 'c']
[u'a', u'b', u'c']
>>> make_list(1234)
['1', '2', '3', '4']
[u'1', u'2', u'3', u'4']
>>> slugify(' Jack & Jill like numbers 1,2,3 and 4 and silly characters ?%.$!/')
'jack-jill-like-numbers-123-and-4-and-silly-characters'
u'jack-jill-like-numbers-123-and-4-and-silly-characters'
>>> stringformat(1, '03d')
'001'
>>> stringformat(1, u'03d')
u'001'
>>> stringformat(1, 'z')
''
>>> stringformat(1, u'z')
u''
>>> title('a nice title, isn\'t it?')
"A Nice Title, Isn't It?"
u"A Nice Title, Isn't It?"
>>> truncatewords('A sentence with a few words in it', 1)
'A ...'
>>> truncatewords(u'A sentence with a few words in it', 1)
u'A ...'
>>> truncatewords('A sentence with a few words in it', 5)
'A sentence with a few ...'
>>> truncatewords(u'A sentence with a few words in it', 5)
u'A sentence with a few ...'
>>> truncatewords('A sentence with a few words in it', 100)
'A sentence with a few words in it'
>>> truncatewords(u'A sentence with a few words in it', 100)
u'A sentence with a few words in it'
>>> truncatewords('A sentence with a few words in it', 'not a number')
'A sentence with a few words in it'
>>> truncatewords(u'A sentence with a few words in it', 'not a number')
u'A sentence with a few words in it'
>>> truncatewords_html('<p>one <a href="#">two - three <br>four</a> five</p>', 0)
''
>>> truncatewords_html(u'<p>one <a href="#">two - three <br>four</a> five</p>', 0)
u''
>>> truncatewords_html('<p>one <a href="#">two - three <br>four</a> five</p>', 2)
'<p>one <a href="#">two ...</a></p>'
>>> truncatewords_html(u'<p>one <a href="#">two - three <br>four</a> five</p>', 2)
u'<p>one <a href="#">two ...</a></p>'
>>> truncatewords_html('<p>one <a href="#">two - three <br>four</a> five</p>', 4)
'<p>one <a href="#">two - three <br>four ...</a></p>'
>>> truncatewords_html(u'<p>one <a href="#">two - three <br>four</a> five</p>', 4)
u'<p>one <a href="#">two - three <br>four ...</a></p>'
>>> truncatewords_html('<p>one <a href="#">two - three <br>four</a> five</p>', 5)
'<p>one <a href="#">two - three <br>four</a> five</p>'
>>> truncatewords_html(u'<p>one <a href="#">two - three <br>four</a> five</p>', 5)
u'<p>one <a href="#">two - three <br>four</a> five</p>'
>>> truncatewords_html('<p>one <a href="#">two - three <br>four</a> five</p>', 100)
'<p>one <a href="#">two - three <br>four</a> five</p>'
>>> truncatewords_html(u'<p>one <a href="#">two - three <br>four</a> five</p>', 100)
u'<p>one <a href="#">two - three <br>four</a> five</p>'
>>> upper('Mixed case input')
'MIXED CASE INPUT'
>>> upper(u'Mixed case input')
u'MIXED CASE INPUT'
>>> upper(u'\xeb') # lowercase e umlaut
u'\xcb'
>>> urlencode('jack & jill')
'jack%20%26%20jill'
>>> urlencode(u'jack & jill')
u'jack%20%26%20jill'
>>> urlencode(1)
'1'
u'1'
>>> urlizetrunc('http://short.com/', 20)
'<a href="http://short.com/" rel="nofollow">http://short.com/</a>'
>>> urlizetrunc(u'http://short.com/', 20)
u'<a href="http://short.com/" rel="nofollow">http://short.com/</a>'
>>> urlizetrunc('http://www.google.co.uk/search?hl=en&q=some+long+url&btnG=Search&meta=', 20)
'<a href="http://www.google.co.uk/search?hl=en&q=some+long+url&btnG=Search&meta=" rel="nofollow">http://www.google.co...</a>'
>>> urlizetrunc(u'http://www.google.co.uk/search?hl=en&q=some+long+url&btnG=Search&meta=', 20)
u'<a href="http://www.google.co.uk/search?hl=en&q=some+long+url&btnG=Search&meta=" rel="nofollow">http://www.google.co...</a>'
>>> wordcount('')
>>> wordcount(u'')
0
>>> wordcount('oneword')
>>> wordcount(u'oneword')
1
>>> wordcount('lots of words')
>>> wordcount(u'lots of words')
3
>>> wordwrap('this is a long paragraph of text that really needs to be wrapped I\'m afraid', 14)
"this is a long\nparagraph of\ntext that\nreally needs\nto be wrapped\nI'm afraid"
>>> wordwrap(u'this is a long paragraph of text that really needs to be wrapped I\'m afraid', 14)
u"this is a long\nparagraph of\ntext that\nreally needs\nto be wrapped\nI'm afraid"
>>> wordwrap('this is a short paragraph of text.\n But this line should be indented',14)
'this is a\nshort\nparagraph of\ntext.\n But this\nline should be\nindented'
>>> wordwrap(u'this is a short paragraph of text.\n But this line should be indented',14)
u'this is a\nshort\nparagraph of\ntext.\n But this\nline should be\nindented'
>>> wordwrap('this is a short paragraph of text.\n But this line should be indented',15)
'this is a short\nparagraph of\ntext.\n But this line\nshould be\nindented'
>>> wordwrap(u'this is a short paragraph of text.\n But this line should be indented',15)
u'this is a short\nparagraph of\ntext.\n But this line\nshould be\nindented'
>>> ljust('test', 10)
'test '
>>> ljust(u'test', 10)
u'test '
>>> ljust('test', 3)
'test'
>>> ljust(u'test', 3)
u'test'
>>> rjust('test', 10)
' test'
>>> rjust(u'test', 10)
u' test'
>>> rjust('test', 3)
'test'
>>> rjust(u'test', 3)
u'test'
>>> center('test', 6)
' test '
>>> center(u'test', 6)
u' test '
>>> cut('a string to be mangled', 'a')
' string to be mngled'
>>> cut(u'a string to be mangled', 'a')
u' string to be mngled'
>>> cut('a string to be mangled', 'ng')
'a stri to be maled'
>>> cut(u'a string to be mangled', 'ng')
u'a stri to be maled'
>>> cut('a string to be mangled', 'strings')
'a string to be mangled'
>>> cut(u'a string to be mangled', 'strings')
u'a string to be mangled'
>>> escape('<some html & special characters > here')
'&lt;some html &amp; special characters &gt; here'
>>> escape(u'<some html & special characters > here')
u'&lt;some html &amp; special characters &gt; here'
>>> escape(u'<some html & special characters > here ĐÅ€£')
u'&lt;some html &amp; special characters &gt; here \xc4\x90\xc3\x85\xe2\x82\xac\xc2\xa3'
>>> linebreaks('line 1')
'<p>line 1</p>'
>>> linebreaks(u'line 1')
u'<p>line 1</p>'
>>> linebreaks('line 1\nline 2')
'<p>line 1<br />line 2</p>'
>>> linebreaks(u'line 1\nline 2')
u'<p>line 1<br />line 2</p>'
>>> removetags('some <b>html</b> with <script>alert("You smell")</script> disallowed <img /> tags', 'script img')
'some <b>html</b> with alert("You smell") disallowed tags'
>>> removetags(u'some <b>html</b> with <script>alert("You smell")</script> disallowed <img /> tags', 'script img')
u'some <b>html</b> with alert("You smell") disallowed tags'
>>> striptags('some <b>html</b> with <script>alert("You smell")</script> disallowed <img /> tags')
'some html with alert("You smell") disallowed tags'
>>> striptags(u'some <b>html</b> with <script>alert("You smell")</script> disallowed <img /> tags')
u'some html with alert("You smell") disallowed tags'
>>> dictsort([{'age': 23, 'name': 'Barbara-Ann'},
... {'age': 63, 'name': 'Ra Ra Rasputin'},
@ -196,16 +196,16 @@ u'&lt;some html &amp; special characters &gt; here \xc4\x90\xc3\x85\xe2\x82\xac\
>>> first([0,1,2])
0
>>> first('')
''
>>> first(u'')
u''
>>> first('test')
't'
>>> first(u'test')
u't'
>>> join([0,1,2], 'glue')
'0glue1glue2'
>>> join([0,1,2], u'glue')
u'0glue1glue2'
>>> length('1234')
>>> length(u'1234')
4
>>> length([1,2,3,4])
@ -220,37 +220,37 @@ False
>>> length_is('a', 1)
True
>>> length_is('a', 10)
>>> length_is(u'a', 10)
False
>>> slice_('abcdefg', '0')
''
>>> slice_(u'abcdefg', u'0')
u''
>>> slice_('abcdefg', '1')
'a'
>>> slice_(u'abcdefg', u'1')
u'a'
>>> slice_('abcdefg', '-1')
'abcdef'
>>> slice_(u'abcdefg', u'-1')
u'abcdef'
>>> slice_('abcdefg', '1:2')
'b'
>>> slice_(u'abcdefg', u'1:2')
u'b'
>>> slice_('abcdefg', '1:3')
'bc'
>>> slice_(u'abcdefg', u'1:3')
u'bc'
>>> slice_('abcdefg', '0::2')
'aceg'
>>> slice_(u'abcdefg', u'0::2')
u'aceg'
>>> unordered_list(['item 1', []])
'\t<li>item 1</li>'
>>> unordered_list([u'item 1', []])
u'\t<li>item 1</li>'
>>> unordered_list(['item 1', [['item 1.1', []]]])
'\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1</li>\n\t</ul>\n\t</li>'
>>> unordered_list([u'item 1', [[u'item 1.1', []]]])
u'\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1</li>\n\t</ul>\n\t</li>'
>>> unordered_list(['item 1', [['item 1.1', []], ['item 1.2', []]]])
'\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1</li>\n\t\t<li>item 1.2</li>\n\t</ul>\n\t</li>'
>>> unordered_list([u'item 1', [[u'item 1.1', []], [u'item 1.2', []]]])
u'\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1</li>\n\t\t<li>item 1.2</li>\n\t</ul>\n\t</li>'
>>> add('1', '2')
>>> add(u'1', u'2')
3
>>> get_digit(123, 1)
@ -268,43 +268,43 @@ False
>>> get_digit(123, 0)
123
>>> get_digit('xyz', 0)
'xyz'
>>> get_digit(u'xyz', 0)
u'xyz'
# real testing of date() is in dateformat.py
>>> date(datetime.datetime(2005, 12, 29), "d F Y")
'29 December 2005'
>>> date(datetime.datetime(2005, 12, 29), r'jS o\f F')
'29th of December'
>>> date(datetime.datetime(2005, 12, 29), u"d F Y")
u'29 December 2005'
>>> date(datetime.datetime(2005, 12, 29), ur'jS o\f F')
u'29th of December'
# real testing of time() is done in dateformat.py
>>> time(datetime.time(13), "h")
'01'
>>> time(datetime.time(13), u"h")
u'01'
>>> time(datetime.time(0), "h")
'12'
>>> time(datetime.time(0), u"h")
u'12'
# real testing is done in timesince.py, where we can provide our own 'now'
>>> timesince(datetime.datetime.now() - datetime.timedelta(1))
'1 day'
u'1 day'
>>> default("val", "default")
'val'
>>> default(u"val", u"default")
u'val'
>>> default(None, "default")
'default'
>>> default(None, u"default")
u'default'
>>> default('', "default")
'default'
>>> default(u'', u"default")
u'default'
>>> default_if_none("val", "default")
'val'
>>> default_if_none(u"val", u"default")
u'val'
>>> default_if_none(None, "default")
'default'
>>> default_if_none(None, u"default")
u'default'
>>> default_if_none('', "default")
''
>>> default_if_none(u'', u"default")
u''
>>> divisibleby(4, 2)
True
@ -313,139 +313,139 @@ True
False
>>> yesno(True)
'yes'
u'yes'
>>> yesno(False)
'no'
u'no'
>>> yesno(None)
'maybe'
u'maybe'
>>> yesno(True, 'certainly,get out of town,perhaps')
'certainly'
>>> yesno(True, u'certainly,get out of town,perhaps')
u'certainly'
>>> yesno(False, 'certainly,get out of town,perhaps')
'get out of town'
>>> yesno(False, u'certainly,get out of town,perhaps')
u'get out of town'
>>> yesno(None, 'certainly,get out of town,perhaps')
'perhaps'
>>> yesno(None, u'certainly,get out of town,perhaps')
u'perhaps'
>>> yesno(None, 'certainly,get out of town')
'get out of town'
>>> yesno(None, u'certainly,get out of town')
u'get out of town'
>>> filesizeformat(1023)
'1023 bytes'
u'1023 bytes'
>>> filesizeformat(1024)
'1.0 KB'
u'1.0 KB'
>>> filesizeformat(10*1024)
'10.0 KB'
u'10.0 KB'
>>> filesizeformat(1024*1024-1)
'1024.0 KB'
u'1024.0 KB'
>>> filesizeformat(1024*1024)
'1.0 MB'
u'1.0 MB'
>>> filesizeformat(1024*1024*50)
'50.0 MB'
u'50.0 MB'
>>> filesizeformat(1024*1024*1024-1)
'1024.0 MB'
u'1024.0 MB'
>>> filesizeformat(1024*1024*1024)
'1.0 GB'
u'1.0 GB'
>>> pluralize(1)
''
u''
>>> pluralize(0)
's'
u's'
>>> pluralize(2)
's'
u's'
>>> pluralize([1])
''
u''
>>> pluralize([])
's'
u's'
>>> pluralize([1,2,3])
's'
u's'
>>> pluralize(1,'es')
''
>>> pluralize(1,u'es')
u''
>>> pluralize(0,'es')
'es'
>>> pluralize(0,u'es')
u'es'
>>> pluralize(2,'es')
'es'
>>> pluralize(2,u'es')
u'es'
>>> pluralize(1,'y,ies')
'y'
>>> pluralize(1,u'y,ies')
u'y'
>>> pluralize(0,'y,ies')
'ies'
>>> pluralize(0,u'y,ies')
u'ies'
>>> pluralize(2,'y,ies')
'ies'
>>> pluralize(2,u'y,ies')
u'ies'
>>> pluralize(0,'y,ies,error')
''
>>> pluralize(0,u'y,ies,error')
u''
>>> phone2numeric('0800 flowers')
'0800 3569377'
>>> phone2numeric(u'0800 flowers')
u'0800 3569377'
# Filters shouldn't break if passed non-strings
>>> addslashes(123)
'123'
u'123'
>>> linenumbers(123)
'1. 123'
u'1. 123'
>>> lower(123)
'123'
u'123'
>>> make_list(123)
['1', '2', '3']
[u'1', u'2', u'3']
>>> slugify(123)
'123'
u'123'
>>> title(123)
'123'
u'123'
>>> truncatewords(123, 2)
'123'
u'123'
>>> upper(123)
'123'
u'123'
>>> urlencode(123)
'123'
u'123'
>>> urlize(123)
'123'
u'123'
>>> urlizetrunc(123, 1)
'123'
u'123'
>>> wordcount(123)
1
>>> wordwrap(123, 2)
'123'
u'123'
>>> ljust('123', 4)
'123 '
u'123 '
>>> rjust('123', 4)
' 123'
u' 123'
>>> center('123', 5)
' 123 '
u' 123 '
>>> center('123', 6)
' 123 '
u' 123 '
>>> cut(123, '2')
'13'
u'13'
>>> escape(123)
'123'
u'123'
>>> linebreaks(123)
'<p>123</p>'
u'<p>123</p>'
>>> linebreaksbr(123)
'123'
u'123'
>>> removetags(123, 'a')
'123'
u'123'
>>> striptags(123)
'123'
u'123'
"""

View File

@ -5,13 +5,13 @@
### smart_split ###########################################################
>>> list(smart_split(r'''This is "a person" test.'''))
['This', 'is', '"a person"', 'test.']
[u'This', u'is', u'"a person"', u'test.']
>>> print list(smart_split(r'''This is "a person's" test.'''))[2]
"a person's"
>>> print list(smart_split(r'''This is "a person\\"s" test.'''))[2]
"a person"s"
>>> list(smart_split('''"a 'one'''))
['"a', "'one"]
[u'"a', u"'one"]
>>> print list(smart_split(r'''all friends' tests'''))[1]
friends'
"""