Ticket #3977: 3977.diff
File 3977.diff, 26.5 KB (added by , 18 years ago) |
---|
-
django/template/defaultfilters.py
3 3 from django.template import resolve_variable, Library 4 4 from django.conf import settings 5 5 from django.utils.translation import gettext 6 from django.utils.encoding import smart_unicode, smart_str 6 7 import re 7 8 import random as random_module 8 9 … … 12 13 # STRING DECORATOR # 13 14 ####################### 14 15 15 def smart_string(obj):16 # FUTURE: Unicode strings should probably be normalized to a specific17 # encoding and non-unicode strings should be converted to unicode too.18 # if isinstance(obj, unicode):19 # obj = obj.encode(settings.DEFAULT_CHARSET)20 # else:21 # obj = unicode(obj, settings.DEFAULT_CHARSET)22 # FUTURE: Replace dumb string logic below with cool unicode logic above.23 if not isinstance(obj, basestring):24 obj = str(obj)25 return obj26 27 16 def stringfilter(func): 28 17 """ 29 Decorator for filters which should only receive strings. The object passed30 as the first positional argument will be converted to a string.18 Decorator for filters which should only receive unicode objects. The object passed 19 as the first positional argument will be converted to a unicode object. 31 20 """ 32 21 def _dec(*args, **kwargs): 33 22 if args: 34 23 args = list(args) 35 args[0] = smart_ string(args[0])24 args[0] = smart_unicode(args[0]) 36 25 return func(*args, **kwargs) 37 26 38 27 # Include a reference to the real function (used to check original … … 83 72 try: 84 73 f = float(text) 85 74 except ValueError: 86 return ''75 return u'' 87 76 try: 88 77 d = int(arg) 89 78 except ValueError: 90 return smart_ string(f)79 return smart_unicode(f) 91 80 m = f - int(f) 92 81 if not m and d < 0: 93 return '%d' % int(f)82 return u'%d' % int(f) 94 83 else: 95 formatstr = '%%.%df' % abs(d)84 formatstr = u'%%.%df' % abs(d) 96 85 return formatstr % f 97 86 98 87 def linenumbers(value): 99 88 "Displays text with line numbers" 100 89 from django.utils.html import escape 101 lines = value.split( '\n')90 lines = value.split(u'\n') 102 91 # Find the maximum width of the line count, for use with zero padding string format command 103 width = str(len(str(len(lines))))92 width = unicode(len(unicode(len(lines)))) 104 93 for i, line in enumerate(lines): 105 lines[i] = ( "%0" + width +"d. %s") % (i + 1, escape(line))106 return '\n'.join(lines)94 lines[i] = (u"%0" + width + u"d. %s") % (i + 1, escape(line)) 95 return u'\n'.join(lines) 107 96 linenumbers = stringfilter(linenumbers) 108 97 109 98 def lower(value): … … 121 110 122 111 def slugify(value): 123 112 "Converts to lowercase, removes non-alpha chars and converts spaces to hyphens" 113 # Don't compile patterns as unicode because \w then would mean any letter. Slugify is effectively an asciiization. 124 114 value = re.sub('[^\w\s-]', '', value).strip().lower() 125 115 return re.sub('[-\s]+', '-', value) 126 116 slugify = stringfilter(slugify) … … 135 125 of Python string formatting 136 126 """ 137 127 try: 138 return ( "%" + str(arg)) % value128 return (u"%" + unicode(arg)) % value 139 129 except (ValueError, TypeError): 140 return ""130 return u"" 141 131 142 132 def title(value): 143 133 "Converts a string into titlecase" … … 155 145 length = int(arg) 156 146 except ValueError: # invalid literal for int() 157 147 return value # Fail silently. 158 if not isinstance(value, basestring):159 value = str(value)160 148 return truncate_words(value, length) 161 149 truncatewords = stringfilter(truncatewords) 162 150 … … 171 159 length = int(arg) 172 160 except ValueError: # invalid literal for int() 173 161 return value # Fail silently. 174 if not isinstance(value, basestring): 175 value = str(value) 176 return truncate_html_words(value, length) 162 result = truncate_html_words(value, length) 163 # isagalaev: Actually the better solution would be converting text utils to output unicode 164 if isinstance(result, str): 165 result = result.decode('utf-8') 166 return result 177 167 truncatewords_html = stringfilter(truncatewords_html) 178 168 179 169 def upper(value): … … 184 174 def urlencode(value): 185 175 "Escapes a value for use in a URL" 186 176 import urllib 187 if not isinstance(value, basestring): 188 value = str(value) 189 return urllib.quote(value) 177 return urllib.quote(value).decode('utf-8') 190 178 urlencode = stringfilter(urlencode) 191 179 192 180 def urlize(value): … … 246 234 247 235 def cut(value, arg): 248 236 "Removes all values of arg from the given string" 249 return value.replace(arg, '')237 return value.replace(arg, u'') 250 238 cut = stringfilter(cut) 251 239 252 240 ################### … … 273 261 def removetags(value, tags): 274 262 "Removes a space separated list of [X]HTML tags from the output" 275 263 tags = [re.escape(tag) for tag in tags.split()] 276 tags_re = '(%s)' %'|'.join(tags)277 starttag_re = re.compile( r'<%s(/?>|(\s+[^>]*>))' % tags_re)278 endtag_re = re.compile( '</%s>' % tags_re)279 value = starttag_re.sub( '', value)280 value = endtag_re.sub( '', value)264 tags_re = u'(%s)' % u'|'.join(tags) 265 starttag_re = re.compile(ur'<%s(/?>|(\s+[^>]*>))' % tags_re, re.U) 266 endtag_re = re.compile(u'</%s>' % tags_re, re.U) 267 value = starttag_re.sub(u'', value) 268 value = endtag_re.sub(u'', value) 281 269 return value 282 270 removetags = stringfilter(removetags) 283 271 … … 296 284 Takes a list of dicts, returns that list sorted by the property given in 297 285 the argument. 298 286 """ 299 decorated = [(resolve_variable( 'var.' + arg, {'var' : item}), item) for item in value]287 decorated = [(resolve_variable(u'var.' + arg, {u'var' : item}), item) for item in value] 300 288 decorated.sort() 301 289 return [item[1] for item in decorated] 302 290 … … 305 293 Takes a list of dicts, returns that list sorted in reverse order by the 306 294 property given in the argument. 307 295 """ 308 decorated = [(resolve_variable( 'var.' + arg, {'var' : item}), item) for item in value]296 decorated = [(resolve_variable(u'var.' + arg, {u'var' : item}), item) for item in value] 309 297 decorated.sort() 310 298 decorated.reverse() 311 299 return [item[1] for item in decorated] … … 315 303 try: 316 304 return value[0] 317 305 except IndexError: 318 return ''306 return u'' 319 307 320 308 def join(value, arg): 321 309 "Joins a list with a string, like Python's ``str.join(list)``" 322 310 try: 323 return arg.join(map(smart_ string, value))311 return arg.join(map(smart_unicode, value)) 324 312 except AttributeError: # fail silently but nicely 325 313 return value 326 314 … … 346 334 """ 347 335 try: 348 336 bits = [] 349 for x in arg.split( ':'):337 for x in arg.split(u':'): 350 338 if len(x) == 0: 351 339 bits.append(None) 352 340 else: … … 378 366 </li> 379 367 """ 380 368 def _helper(value, tabs): 381 indent = '\t' * tabs369 indent = u'\t' * tabs 382 370 if value[1]: 383 return '%s<li>%s\n%s<ul>\n%s\n%s</ul>\n%s</li>' % (indent, value[0], indent,384 '\n'.join([_helper(v, tabs+1) for v in value[1]]), indent, indent)371 return u'%s<li>%s\n%s<ul>\n%s\n%s</ul>\n%s</li>' % (indent, value[0], indent, 372 u'\n'.join([_helper(v, tabs+1) for v in value[1]]), indent, indent) 385 373 else: 386 return '%s<li>%s</li>' % (indent, value[0])374 return u'%s<li>%s</li>' % (indent, value[0]) 387 375 return _helper(value, 1) 388 376 389 377 ################### … … 409 397 if arg < 1: 410 398 return value 411 399 try: 412 return int(s tr(value)[-arg])400 return int(smart_unicode(value)[-arg]) 413 401 except IndexError: 414 402 return 0 415 403 … … 421 409 "Formats a date according to the given format" 422 410 from django.utils.dateformat import format 423 411 if not value: 424 return ''412 return u'' 425 413 if arg is None: 426 414 arg = settings.DATE_FORMAT 427 return format(value, arg) 415 else: 416 arg = smart_str(arg) 417 # isagalaev: Actually the better solution would be converting dateformat utils to deal with unicode 418 return format(value, arg).decode('utf-8') 428 419 429 420 def time(value, arg=None): 430 421 "Formats a time according to the given format" 431 422 from django.utils.dateformat import time_format 432 if value in (None, ''):433 return ''423 if value in (None, u''): 424 return u'' 434 425 if arg is None: 435 426 arg = settings.TIME_FORMAT 436 return time_format(value, arg) 427 else: 428 arg = smart_str(arg) 429 # isagalaev: Actually the better solution would be converting dateformat utils to deal with unicode 430 return time_format(value, arg).decode('utf-8') 437 431 438 432 def timesince(value, arg=None): 439 433 'Formats a date as the time since that date (i.e. "4 days, 6 hours")' 440 434 from django.utils.timesince import timesince 441 435 if not value: 442 return ''436 return u'' 443 437 if arg: 444 return timesince(arg, value) 445 return timesince(value) 438 return timesince(arg, value).decode('utf-8') 439 return timesince(value).decode('utf-8') 446 440 447 441 def timeuntil(value, arg=None): 448 442 'Formats a date as the time until that date (i.e. "4 days, 6 hours")' 449 443 from django.utils.timesince import timesince 450 444 from datetime import datetime 451 445 if not value: 452 return '' 446 return u'' 447 # isagalaev: Actually the better solution would be converting timesince utils to deal with unicode 453 448 if arg: 454 return timesince(arg, value) 455 return timesince(datetime.now(), value) 449 return timesince(arg, value).decode('utf-8') 450 return timesince(datetime.now(), value).decode('utf-8') 456 451 457 452 ################### 458 453 # LOGIC # … … 488 483 ========== ====================== ================================== 489 484 """ 490 485 if arg is None: 491 arg = gettext('yes,no,maybe') 492 bits = arg.split( ',')486 arg = gettext('yes,no,maybe').decode('utf-8') 487 bits = arg.split(u',') 493 488 if len(bits) < 2: 494 489 return value # Invalid arg. 495 490 try: … … 514 509 try: 515 510 bytes = float(bytes) 516 511 except TypeError: 517 return "0 bytes"512 return u"0 bytes" 518 513 519 514 if bytes < 1024: 520 return "%d byte%s" % (bytes, bytes != 1 and 's' or'')515 return u"%d byte%s" % (bytes, bytes != 1 and u's' or u'') 521 516 if bytes < 1024 * 1024: 522 return "%.1f KB" % (bytes / 1024)517 return u"%.1f KB" % (bytes / 1024) 523 518 if bytes < 1024 * 1024 * 1024: 524 return "%.1f MB" % (bytes / (1024 * 1024))525 return "%.1f GB" % (bytes / (1024 * 1024 * 1024))519 return u"%.1f MB" % (bytes / (1024 * 1024)) 520 return u"%.1f GB" % (bytes / (1024 * 1024 * 1024)) 526 521 527 def pluralize(value, arg= 's'):522 def pluralize(value, arg=u's'): 528 523 """ 529 524 Returns a plural suffix if the value is not 1, for '1 vote' vs. '2 votes' 530 525 By default, 's' is used as a suffix; if an argument is provided, that string 531 526 is used instead. If the provided argument contains a comma, the text before 532 527 the comma is used for the singular case. 533 528 """ 534 if not ',' in arg:535 arg = ',' + arg536 bits = arg.split( ',')529 if not u',' in arg: 530 arg = u',' + arg 531 bits = arg.split(u',') 537 532 if len(bits) > 2: 538 return ''533 return u'' 539 534 singular_suffix, plural_suffix = bits[:2] 540 535 541 536 try: … … 554 549 def phone2numeric(value): 555 550 "Takes a phone number and converts it in to its numerical equivalent" 556 551 from django.utils.text import phone2numeric 557 return phone2numeric(value) 552 # isagalaev: Actually the better solution would be converting text utils to return unicode 553 return phone2numeric(value).decode('utf-8') 558 554 559 555 def pprint(value): 560 556 "A wrapper around pprint.pprint -- for debugging, really" … … 562 558 try: 563 559 return pformat(value) 564 560 except Exception, e: 565 return "Error in formatting:%s" % e561 return u"Error in formatting:%s" % e 566 562 567 563 # Syntax: register.filter(name of filter, callback) 568 564 register.filter(add) -
tests/regressiontests/defaultfilters/tests.py
2 2 3 3 r""" 4 4 >>> floatformat(7.7) 5 '7.7'5 u'7.7' 6 6 >>> floatformat(7.0) 7 '7'7 u'7' 8 8 >>> floatformat(0.7) 9 '0.7'9 u'0.7' 10 10 >>> floatformat(0.07) 11 '0.1'11 u'0.1' 12 12 >>> floatformat(0.007) 13 '0.0'13 u'0.0' 14 14 >>> floatformat(0.0) 15 '0'15 u'0' 16 16 >>> floatformat(7.7,3) 17 '7.700'17 u'7.700' 18 18 >>> floatformat(6.000000,3) 19 '6.000'19 u'6.000' 20 20 >>> floatformat(13.1031,-3) 21 '13.103'21 u'13.103' 22 22 >>> floatformat(11.1197, -2) 23 '11.12'23 u'11.12' 24 24 >>> floatformat(11.0000, -2) 25 '11'25 u'11' 26 26 >>> floatformat(11.000001, -2) 27 '11.00'27 u'11.00' 28 28 >>> floatformat(8.2798, 3) 29 '8.280'30 >>> floatformat( 'foo')31 ''32 >>> floatformat(13.1031, 'bar')33 '13.1031'34 >>> floatformat( 'foo','bar')35 ''29 u'8.280' 30 >>> floatformat(u'foo') 31 u'' 32 >>> floatformat(13.1031, u'bar') 33 u'13.1031' 34 >>> floatformat(u'foo', u'bar') 35 u'' 36 36 37 >>> addslashes( '"double quotes" and \'single quotes\'')38 '\\"double quotes\\" and \\\'single quotes\\\''37 >>> addslashes(u'"double quotes" and \'single quotes\'') 38 u'\\"double quotes\\" and \\\'single quotes\\\'' 39 39 40 >>> addslashes( r'\ : backslashes, too')41 '\\\\ : backslashes, too'40 >>> addslashes(ur'\ : backslashes, too') 41 u'\\\\ : backslashes, too' 42 42 43 >>> capfirst( 'hello world')44 'Hello world'43 >>> capfirst(u'hello world') 44 u'Hello world' 45 45 46 >>> fix_ampersands( 'Jack & Jill & Jeroboam')47 'Jack & Jill & Jeroboam'46 >>> fix_ampersands(u'Jack & Jill & Jeroboam') 47 u'Jack & Jill & Jeroboam' 48 48 49 >>> linenumbers( 'line 1\nline 2')50 '1. line 1\n2. line 2'49 >>> linenumbers(u'line 1\nline 2') 50 u'1. line 1\n2. line 2' 51 51 52 >>> linenumbers( '\n'.join(['x'] * 10))53 '01. x\n02. x\n03. x\n04. x\n05. x\n06. x\n07. x\n08. x\n09. x\n10. x'52 >>> linenumbers(u'\n'.join([u'x'] * 10)) 53 u'01. x\n02. x\n03. x\n04. x\n05. x\n06. x\n07. x\n08. x\n09. x\n10. x' 54 54 55 55 >>> lower('TEST') 56 'test'56 u'test' 57 57 58 58 >>> lower(u'\xcb') # uppercase E umlaut 59 59 u'\xeb' 60 60 61 61 >>> make_list('abc') 62 [ 'a', 'b','c']62 [u'a', u'b', u'c'] 63 63 64 64 >>> make_list(1234) 65 [ '1', '2', '3','4']65 [u'1', u'2', u'3', u'4'] 66 66 67 67 >>> slugify(' Jack & Jill like numbers 1,2,3 and 4 and silly characters ?%.$!/') 68 'jack-jill-like-numbers-123-and-4-and-silly-characters'68 u'jack-jill-like-numbers-123-and-4-and-silly-characters' 69 69 70 >>> stringformat(1, '03d')71 '001'70 >>> stringformat(1, u'03d') 71 u'001' 72 72 73 >>> stringformat(1, 'z')74 ''73 >>> stringformat(1, u'z') 74 u'' 75 75 76 76 >>> title('a nice title, isn\'t it?') 77 "A Nice Title, Isn't It?"77 u"A Nice Title, Isn't It?" 78 78 79 79 80 >>> truncatewords( 'A sentence with a few words in it', 1)81 'A ...'80 >>> truncatewords(u'A sentence with a few words in it', 1) 81 u'A ...' 82 82 83 >>> truncatewords( 'A sentence with a few words in it', 5)84 'A sentence with a few ...'83 >>> truncatewords(u'A sentence with a few words in it', 5) 84 u'A sentence with a few ...' 85 85 86 >>> truncatewords( 'A sentence with a few words in it', 100)87 'A sentence with a few words in it'86 >>> truncatewords(u'A sentence with a few words in it', 100) 87 u'A sentence with a few words in it' 88 88 89 >>> truncatewords( 'A sentence with a few words in it', 'not a number')90 'A sentence with a few words in it'89 >>> truncatewords(u'A sentence with a few words in it', 'not a number') 90 u'A sentence with a few words in it' 91 91 92 >>> truncatewords_html( '<p>one <a href="#">two - three <br>four</a> five</p>', 0)93 ''92 >>> truncatewords_html(u'<p>one <a href="#">two - three <br>four</a> five</p>', 0) 93 u'' 94 94 95 >>> truncatewords_html( '<p>one <a href="#">two - three <br>four</a> five</p>', 2)96 '<p>one <a href="#">two ...</a></p>'95 >>> truncatewords_html(u'<p>one <a href="#">two - three <br>four</a> five</p>', 2) 96 u'<p>one <a href="#">two ...</a></p>' 97 97 98 >>> truncatewords_html( '<p>one <a href="#">two - three <br>four</a> five</p>', 4)99 '<p>one <a href="#">two - three <br>four ...</a></p>'98 >>> truncatewords_html(u'<p>one <a href="#">two - three <br>four</a> five</p>', 4) 99 u'<p>one <a href="#">two - three <br>four ...</a></p>' 100 100 101 >>> truncatewords_html( '<p>one <a href="#">two - three <br>four</a> five</p>', 5)102 '<p>one <a href="#">two - three <br>four</a> five</p>'101 >>> truncatewords_html(u'<p>one <a href="#">two - three <br>four</a> five</p>', 5) 102 u'<p>one <a href="#">two - three <br>four</a> five</p>' 103 103 104 >>> truncatewords_html( '<p>one <a href="#">two - three <br>four</a> five</p>', 100)105 '<p>one <a href="#">two - three <br>four</a> five</p>'104 >>> truncatewords_html(u'<p>one <a href="#">two - three <br>four</a> five</p>', 100) 105 u'<p>one <a href="#">two - three <br>four</a> five</p>' 106 106 107 >>> upper( 'Mixed case input')108 'MIXED CASE INPUT'107 >>> upper(u'Mixed case input') 108 u'MIXED CASE INPUT' 109 109 110 110 >>> upper(u'\xeb') # lowercase e umlaut 111 111 u'\xcb' 112 112 113 113 114 >>> urlencode( 'jack & jill')115 'jack%20%26%20jill'114 >>> urlencode(u'jack & jill') 115 u'jack%20%26%20jill' 116 116 >>> urlencode(1) 117 '1'117 u'1' 118 118 119 119 120 >>> urlizetrunc( 'http://short.com/', 20)121 '<a href="http://short.com/" rel="nofollow">http://short.com/</a>'120 >>> urlizetrunc(u'http://short.com/', 20) 121 u'<a href="http://short.com/" rel="nofollow">http://short.com/</a>' 122 122 123 >>> urlizetrunc( 'http://www.google.co.uk/search?hl=en&q=some+long+url&btnG=Search&meta=', 20)124 '<a href="http://www.google.co.uk/search?hl=en&q=some+long+url&btnG=Search&meta=" rel="nofollow">http://www.google.co...</a>'123 >>> urlizetrunc(u'http://www.google.co.uk/search?hl=en&q=some+long+url&btnG=Search&meta=', 20) 124 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>' 125 125 126 >>> wordcount( '')126 >>> wordcount(u'') 127 127 0 128 128 129 >>> wordcount( 'oneword')129 >>> wordcount(u'oneword') 130 130 1 131 131 132 >>> wordcount( 'lots of words')132 >>> wordcount(u'lots of words') 133 133 3 134 134 135 >>> wordwrap( 'this is a long paragraph of text that really needs to be wrapped I\'m afraid', 14)136 "this is a long\nparagraph of\ntext that\nreally needs\nto be wrapped\nI'm afraid"135 >>> wordwrap(u'this is a long paragraph of text that really needs to be wrapped I\'m afraid', 14) 136 u"this is a long\nparagraph of\ntext that\nreally needs\nto be wrapped\nI'm afraid" 137 137 138 >>> wordwrap( 'this is a short paragraph of text.\n But this line should be indented',14)139 'this is a\nshort\nparagraph of\ntext.\n But this\nline should be\nindented'138 >>> wordwrap(u'this is a short paragraph of text.\n But this line should be indented',14) 139 u'this is a\nshort\nparagraph of\ntext.\n But this\nline should be\nindented' 140 140 141 >>> wordwrap( 'this is a short paragraph of text.\n But this line should be indented',15)142 'this is a short\nparagraph of\ntext.\n But this line\nshould be\nindented'141 >>> wordwrap(u'this is a short paragraph of text.\n But this line should be indented',15) 142 u'this is a short\nparagraph of\ntext.\n But this line\nshould be\nindented' 143 143 144 >>> ljust( 'test', 10)145 'test '144 >>> ljust(u'test', 10) 145 u'test ' 146 146 147 >>> ljust( 'test', 3)148 'test'147 >>> ljust(u'test', 3) 148 u'test' 149 149 150 >>> rjust( 'test', 10)151 ' test'150 >>> rjust(u'test', 10) 151 u' test' 152 152 153 >>> rjust( 'test', 3)154 'test'153 >>> rjust(u'test', 3) 154 u'test' 155 155 156 >>> center( 'test', 6)157 ' test '156 >>> center(u'test', 6) 157 u' test ' 158 158 159 >>> cut( 'a string to be mangled', 'a')160 ' string to be mngled'159 >>> cut(u'a string to be mangled', 'a') 160 u' string to be mngled' 161 161 162 >>> cut( 'a string to be mangled', 'ng')163 'a stri to be maled'162 >>> cut(u'a string to be mangled', 'ng') 163 u'a stri to be maled' 164 164 165 >>> cut( 'a string to be mangled', 'strings')166 'a string to be mangled'165 >>> cut(u'a string to be mangled', 'strings') 166 u'a string to be mangled' 167 167 168 >>> escape( '<some html & special characters > here')169 '<some html & special characters > here'168 >>> escape(u'<some html & special characters > here') 169 u'<some html & special characters > here' 170 170 171 171 >>> escape(u'<some html & special characters > here ĐÅ€£') 172 172 u'<some html & special characters > here \xc4\x90\xc3\x85\xe2\x82\xac\xc2\xa3' 173 173 174 >>> linebreaks( 'line 1')175 '<p>line 1</p>'174 >>> linebreaks(u'line 1') 175 u'<p>line 1</p>' 176 176 177 >>> linebreaks( 'line 1\nline 2')178 '<p>line 1<br />line 2</p>'177 >>> linebreaks(u'line 1\nline 2') 178 u'<p>line 1<br />line 2</p>' 179 179 180 >>> removetags( 'some <b>html</b> with <script>alert("You smell")</script> disallowed <img /> tags', 'script img')181 'some <b>html</b> with alert("You smell") disallowed tags'180 >>> removetags(u'some <b>html</b> with <script>alert("You smell")</script> disallowed <img /> tags', 'script img') 181 u'some <b>html</b> with alert("You smell") disallowed tags' 182 182 183 >>> striptags( 'some <b>html</b> with <script>alert("You smell")</script> disallowed <img /> tags')184 'some html with alert("You smell") disallowed tags'183 >>> striptags(u'some <b>html</b> with <script>alert("You smell")</script> disallowed <img /> tags') 184 u'some html with alert("You smell") disallowed tags' 185 185 186 186 >>> dictsort([{'age': 23, 'name': 'Barbara-Ann'}, 187 187 ... {'age': 63, 'name': 'Ra Ra Rasputin'}, … … 196 196 >>> first([0,1,2]) 197 197 0 198 198 199 >>> first( '')200 ''199 >>> first(u'') 200 u'' 201 201 202 >>> first( 'test')203 't'202 >>> first(u'test') 203 u't' 204 204 205 >>> join([0,1,2], 'glue')206 '0glue1glue2'205 >>> join([0,1,2], u'glue') 206 u'0glue1glue2' 207 207 208 >>> length( '1234')208 >>> length(u'1234') 209 209 4 210 210 211 211 >>> length([1,2,3,4]) … … 220 220 >>> length_is('a', 1) 221 221 True 222 222 223 >>> length_is( 'a', 10)223 >>> length_is(u'a', 10) 224 224 False 225 225 226 >>> slice_( 'abcdefg','0')227 ''226 >>> slice_(u'abcdefg', u'0') 227 u'' 228 228 229 >>> slice_( 'abcdefg','1')230 'a'229 >>> slice_(u'abcdefg', u'1') 230 u'a' 231 231 232 >>> slice_( 'abcdefg','-1')233 'abcdef'232 >>> slice_(u'abcdefg', u'-1') 233 u'abcdef' 234 234 235 >>> slice_( 'abcdefg','1:2')236 'b'235 >>> slice_(u'abcdefg', u'1:2') 236 u'b' 237 237 238 >>> slice_( 'abcdefg','1:3')239 'bc'238 >>> slice_(u'abcdefg', u'1:3') 239 u'bc' 240 240 241 >>> slice_( 'abcdefg','0::2')242 'aceg'241 >>> slice_(u'abcdefg', u'0::2') 242 u'aceg' 243 243 244 >>> unordered_list([ 'item 1', []])245 '\t<li>item 1</li>'244 >>> unordered_list([u'item 1', []]) 245 u'\t<li>item 1</li>' 246 246 247 >>> unordered_list([ 'item 1', [['item 1.1', []]]])248 '\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1</li>\n\t</ul>\n\t</li>'247 >>> unordered_list([u'item 1', [[u'item 1.1', []]]]) 248 u'\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1</li>\n\t</ul>\n\t</li>' 249 249 250 >>> unordered_list([ 'item 1', [['item 1.1', []], ['item 1.2', []]]])251 '\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>'250 >>> unordered_list([u'item 1', [[u'item 1.1', []], [u'item 1.2', []]]]) 251 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>' 252 252 253 >>> add( '1','2')253 >>> add(u'1', u'2') 254 254 3 255 255 256 256 >>> get_digit(123, 1) … … 268 268 >>> get_digit(123, 0) 269 269 123 270 270 271 >>> get_digit( 'xyz', 0)272 'xyz'271 >>> get_digit(u'xyz', 0) 272 u'xyz' 273 273 274 274 # real testing of date() is in dateformat.py 275 >>> date(datetime.datetime(2005, 12, 29), "d F Y")276 '29 December 2005'277 >>> date(datetime.datetime(2005, 12, 29), r'jS o\f F')278 '29th of December'275 >>> date(datetime.datetime(2005, 12, 29), u"d F Y") 276 u'29 December 2005' 277 >>> date(datetime.datetime(2005, 12, 29), ur'jS o\f F') 278 u'29th of December' 279 279 280 280 # real testing of time() is done in dateformat.py 281 >>> time(datetime.time(13), "h")282 '01'281 >>> time(datetime.time(13), u"h") 282 u'01' 283 283 284 >>> time(datetime.time(0), "h")285 '12'284 >>> time(datetime.time(0), u"h") 285 u'12' 286 286 287 287 # real testing is done in timesince.py, where we can provide our own 'now' 288 288 >>> timesince(datetime.datetime.now() - datetime.timedelta(1)) 289 '1 day'289 u'1 day' 290 290 291 >>> default( "val","default")292 'val'291 >>> default(u"val", u"default") 292 u'val' 293 293 294 >>> default(None, "default")295 'default'294 >>> default(None, u"default") 295 u'default' 296 296 297 >>> default( '',"default")298 'default'297 >>> default(u'', u"default") 298 u'default' 299 299 300 >>> default_if_none( "val","default")301 'val'300 >>> default_if_none(u"val", u"default") 301 u'val' 302 302 303 >>> default_if_none(None, "default")304 'default'303 >>> default_if_none(None, u"default") 304 u'default' 305 305 306 >>> default_if_none( '',"default")307 ''306 >>> default_if_none(u'', u"default") 307 u'' 308 308 309 309 >>> divisibleby(4, 2) 310 310 True … … 313 313 False 314 314 315 315 >>> yesno(True) 316 'yes'316 u'yes' 317 317 318 318 >>> yesno(False) 319 'no'319 u'no' 320 320 321 321 >>> yesno(None) 322 'maybe'322 u'maybe' 323 323 324 >>> yesno(True, 'certainly,get out of town,perhaps')325 'certainly'324 >>> yesno(True, u'certainly,get out of town,perhaps') 325 u'certainly' 326 326 327 >>> yesno(False, 'certainly,get out of town,perhaps')328 'get out of town'327 >>> yesno(False, u'certainly,get out of town,perhaps') 328 u'get out of town' 329 329 330 >>> yesno(None, 'certainly,get out of town,perhaps')331 'perhaps'330 >>> yesno(None, u'certainly,get out of town,perhaps') 331 u'perhaps' 332 332 333 >>> yesno(None, 'certainly,get out of town')334 'get out of town'333 >>> yesno(None, u'certainly,get out of town') 334 u'get out of town' 335 335 336 336 >>> filesizeformat(1023) 337 '1023 bytes'337 u'1023 bytes' 338 338 339 339 >>> filesizeformat(1024) 340 '1.0 KB'340 u'1.0 KB' 341 341 342 342 >>> filesizeformat(10*1024) 343 '10.0 KB'343 u'10.0 KB' 344 344 345 345 >>> filesizeformat(1024*1024-1) 346 '1024.0 KB'346 u'1024.0 KB' 347 347 348 348 >>> filesizeformat(1024*1024) 349 '1.0 MB'349 u'1.0 MB' 350 350 351 351 >>> filesizeformat(1024*1024*50) 352 '50.0 MB'352 u'50.0 MB' 353 353 354 354 >>> filesizeformat(1024*1024*1024-1) 355 '1024.0 MB'355 u'1024.0 MB' 356 356 357 357 >>> filesizeformat(1024*1024*1024) 358 '1.0 GB'358 u'1.0 GB' 359 359 360 360 >>> pluralize(1) 361 ''361 u'' 362 362 363 363 >>> pluralize(0) 364 's'364 u's' 365 365 366 366 >>> pluralize(2) 367 's'367 u's' 368 368 369 369 >>> pluralize([1]) 370 ''370 u'' 371 371 372 372 >>> pluralize([]) 373 's'373 u's' 374 374 375 375 >>> pluralize([1,2,3]) 376 's'376 u's' 377 377 378 >>> pluralize(1, 'es')379 ''378 >>> pluralize(1,u'es') 379 u'' 380 380 381 >>> pluralize(0, 'es')382 'es'381 >>> pluralize(0,u'es') 382 u'es' 383 383 384 >>> pluralize(2, 'es')385 'es'384 >>> pluralize(2,u'es') 385 u'es' 386 386 387 >>> pluralize(1, 'y,ies')388 'y'387 >>> pluralize(1,u'y,ies') 388 u'y' 389 389 390 >>> pluralize(0, 'y,ies')391 'ies'390 >>> pluralize(0,u'y,ies') 391 u'ies' 392 392 393 >>> pluralize(2, 'y,ies')394 'ies'393 >>> pluralize(2,u'y,ies') 394 u'ies' 395 395 396 >>> pluralize(0, 'y,ies,error')397 ''396 >>> pluralize(0,u'y,ies,error') 397 u'' 398 398 399 >>> phone2numeric( '0800 flowers')400 '0800 3569377'399 >>> phone2numeric(u'0800 flowers') 400 u'0800 3569377' 401 401 402 402 # Filters shouldn't break if passed non-strings 403 403 >>> addslashes(123) 404 '123'404 u'123' 405 405 >>> linenumbers(123) 406 '1. 123'406 u'1. 123' 407 407 >>> lower(123) 408 '123'408 u'123' 409 409 >>> make_list(123) 410 [ '1', '2','3']410 [u'1', u'2', u'3'] 411 411 >>> slugify(123) 412 '123'412 u'123' 413 413 >>> title(123) 414 '123'414 u'123' 415 415 >>> truncatewords(123, 2) 416 '123'416 u'123' 417 417 >>> upper(123) 418 '123'418 u'123' 419 419 >>> urlencode(123) 420 '123'420 u'123' 421 421 >>> urlize(123) 422 '123'422 u'123' 423 423 >>> urlizetrunc(123, 1) 424 '123'424 u'123' 425 425 >>> wordcount(123) 426 426 1 427 427 >>> wordwrap(123, 2) 428 '123'428 u'123' 429 429 >>> ljust('123', 4) 430 '123 '430 u'123 ' 431 431 >>> rjust('123', 4) 432 ' 123'432 u' 123' 433 433 >>> center('123', 5) 434 ' 123 '434 u' 123 ' 435 435 >>> center('123', 6) 436 ' 123 '436 u' 123 ' 437 437 >>> cut(123, '2') 438 '13'438 u'13' 439 439 >>> escape(123) 440 '123'440 u'123' 441 441 >>> linebreaks(123) 442 '<p>123</p>'442 u'<p>123</p>' 443 443 >>> linebreaksbr(123) 444 '123'444 u'123' 445 445 >>> removetags(123, 'a') 446 '123'446 u'123' 447 447 >>> striptags(123) 448 '123'448 u'123' 449 449 450 450 """ 451 451