Ticket #14046: patch.2.diff
File patch.2.diff, 215.3 KB (added by , 14 years ago) |
---|
-
django/template/loader_tags.py
149 149 template_name = self.template_name.resolve(context) 150 150 t = get_template(template_name) 151 151 return t.render(context) 152 except TemplateSyntaxError, e:152 except: 153 153 if settings.TEMPLATE_DEBUG: 154 154 raise 155 return '' 156 except: 157 return '' # Fail silently for invalid included templates. 155 return '' # Fail silently for invalid included templates if settings,TEMPLATE_DEBUG is False 158 156 159 157 def do_block(parser, token): 160 158 """ -
tests/regressiontests/templates/utils.py
1 def testcase(template_name, context, evaluating_func, invalid_str="INVALID"): 2 """ 3 Wrapper for the template test cases, used in tests.py and filters.py 4 """ 5 return (template_name, context, evaluating_func, invalid_str) 6 No newline at end of file -
tests/regressiontests/templates/tests.py
11 11 import os 12 12 import sys 13 13 import traceback 14 import types 14 15 15 16 from django import template 16 17 from django.template import base as template_base … … 34 35 except ImportError: 35 36 pass # If setuptools isn't installed, that's fine. Just move on. 36 37 38 from utils import testcase 37 39 import filters 38 40 39 41 ################################# … … 354 356 tests.sort() 355 357 356 358 # Turn TEMPLATE_DEBUG off, because tests assume that. 357 old_td, settings.TEMPLATE_DEBUG = settings.TEMPLATE_DEBUG, False 358 359 # Set TEMPLATE_STRING_IF_INVALID to a known string. 359 # old_td, settings.TEMPLATE_DEBUG = settings.TEMPLATE_DEBUG, False 360 old_td = settings.TEMPLATE_DEBUG 360 361 old_invalid = settings.TEMPLATE_STRING_IF_INVALID 361 expected_invalid_str = 'INVALID'362 362 363 363 #Set ALLOWED_INCLUDE_ROOTS so that ssi works. 364 364 old_allowed_include_roots = settings.ALLOWED_INCLUDE_ROOTS … … 370 370 kwargs={'id':0,'action':"update"}) 371 371 372 372 for name, vals in tests: 373 if isinstance(vals[2], tuple):374 normal_string_result = vals[2][0]375 invalid_string_result = vals[2][1]376 if isinstance(invalid_string_result, basestring) and '%s' in invalid_string_result:377 expected_invalid_str = 'INVALID %s'378 invalid_string_result = invalid_string_result % vals[2][2]379 template_base.invalid_var_format_string = True380 else:381 normal_string_result = vals[2]382 invalid_string_result = vals[2]383 384 373 if 'LANGUAGE_CODE' in vals[1]: 385 374 activate(vals[1]['LANGUAGE_CODE']) 386 375 else: 387 376 activate('en-us') 388 377 389 for invalid_str, result in [('', normal_string_result), 390 (expected_invalid_str, invalid_string_result)]: 378 for invalid_str_on in (True, False): 379 if invalid_str_on: 380 invalid_str = vals[3] 381 template_base.invalid_var_format_string = True 382 else: 383 invalid_str = "" 384 template_base.invalid_var_format_string = False 385 391 386 settings.TEMPLATE_STRING_IF_INVALID = invalid_str 392 for is_cached in (False, True):393 try:394 start = datetime.now()395 test_template = loader.get_template(name)396 end = datetime.now()397 if end-start > timedelta(seconds=0.2):398 failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Took too long to parse test" % (is_cached, invalid_str, name))399 387 400 start = datetime.now() 401 output = self.render(test_template, vals) 402 end = datetime.now() 403 if end-start > timedelta(seconds=0.2): 404 failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Took too long to render test" % (is_cached, invalid_str, name)) 405 except ContextStackException: 406 failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Context stack was left imbalanced" % (is_cached, invalid_str, name)) 407 continue 408 except Exception: 409 exc_type, exc_value, exc_tb = sys.exc_info() 410 if exc_type != result: 411 tb = '\n'.join(traceback.format_exception(exc_type, exc_value, exc_tb)) 412 failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Got %s, exception: %s\n%s" % (is_cached, invalid_str, name, exc_type, exc_value, tb)) 413 continue 414 if output != result: 415 failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Expected %r, got %r" % (is_cached, invalid_str, name, result, output)) 416 cache_loader.reset() 388 for TEMPLATE_DEBUG in (False, True): 389 settings.TEMPLATE_DEBUG = TEMPLATE_DEBUG 390 for is_cached in (False, True): 391 result = vals[2] 392 if not isinstance(result, types.FunctionType): 393 assert isinstance(result, (str, unicode, type)), "Expected result should either be callable, exception or string-like" 394 else: 395 result = result(TEMPLATE_DEBUG, invalid_str) 417 396 397 try: 398 start = datetime.now() 399 test_template = loader.get_template(name) 400 end = datetime.now() 401 if end-start > timedelta(seconds=0.2): 402 failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Took too long to parse test" % (is_cached, invalid_str, name)) 403 404 start = datetime.now() 405 output = self.render(test_template, vals) 406 end = datetime.now() 407 if end-start > timedelta(seconds=0.2): 408 failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Took too long to render test" % (is_cached, invalid_str, name)) 409 except ContextStackException: 410 failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Context stack was left imbalanced" % (is_cached, invalid_str, name)) 411 continue 412 except Exception: 413 exc_type, exc_value, exc_tb = sys.exc_info() 414 if exc_type != result: 415 tb = '\n'.join(traceback.format_exception(exc_type, exc_value, exc_tb)) 416 failures.append("""Template test (Cached='%(is_cached)s', TEMPLATE_STRING_IF_INVALID='%(invalid_str)s', TEMPLATE_DEBUG=%(TEMPLATE_DEBUG)s): 417 %(name)s -- FAILED. Got %(exc_type)s, expected: %(result)s, exception: %(exc_value)s\n%(tb)s""" 418 % locals()) 419 continue 420 if output != result: 421 failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s', TEMPLATE_DEBUG=%s): %s -- FAILED. Expected %r, got %r" % 422 (is_cached, invalid_str, TEMPLATE_DEBUG, name, result, output)) 423 cache_loader.reset() 424 418 425 if 'LANGUAGE_CODE' in vals[1]: 419 426 deactivate() 420 427 … … 441 448 442 449 def get_template_tests(self): 443 450 # SYNTAX -- 444 # 'template_name': ('template contents', 'context dict', 'expected string output' or Exception class) 451 # 'template_name': testcase('template contents', 'context dict', 'expected string output' or Exception class or 452 # callable which accepts two parameters: TEMPLATE_DEBUG and TEMPLATE_STRING_IF_INVALID and returns 453 # expected string output or Exception class depending on those two state parameters, [optional] value of TEMPLATE_STRING_IF_INVALID) 454 445 455 return { 446 456 ### BASIC SYNTAX ################################################ 447 457 448 458 # Plain text should go through the template parser untouched 449 'basic-syntax01': ("something cool", {}, "something cool"),459 'basic-syntax01': testcase("something cool", {}, "something cool"), 450 460 451 461 # Variables should be replaced with their value in the current 452 462 # context 453 'basic-syntax02': ("{{ headline }}", {'headline':'Success'}, "Success"),463 'basic-syntax02': testcase("{{ headline }}", {'headline':'Success'}, "Success"), 454 464 455 465 # More than one replacement variable is allowed in a template 456 'basic-syntax03': ("{{ first }} --- {{ second }}", {"first" : 1, "second" : 2}, "1 --- 2"),466 'basic-syntax03': testcase("{{ first }} --- {{ second }}", {"first" : 1, "second" : 2}, "1 --- 2"), 457 467 458 468 # Fail silently when a variable is not found in the current context 459 'basic-syntax04': ("as{{ missing }}df", {}, ("asdf","asINVALIDdf")), 469 'basic-syntax04': testcase("as{{ missing }}df", {}, 470 lambda tdebug, invalid_str: invalid_str and "asINVALIDdf" or "asdf"), 460 471 461 472 # A variable may not contain more than one word 462 'basic-syntax06': ("{{ multi word variable }}", {}, template.TemplateSyntaxError),473 'basic-syntax06': testcase("{{ multi word variable }}", {}, template.TemplateSyntaxError), 463 474 464 475 # Raise TemplateSyntaxError for empty variable tags 465 'basic-syntax07': ("{{ }}", {}, template.TemplateSyntaxError),466 'basic-syntax08': ("{{ }}", {}, template.TemplateSyntaxError),476 'basic-syntax07': testcase("{{ }}", {}, template.TemplateSyntaxError), 477 'basic-syntax08': testcase("{{ }}", {}, template.TemplateSyntaxError), 467 478 468 479 # Attribute syntax allows a template to call an object's attribute 469 'basic-syntax09': ("{{ var.method }}", {"var": SomeClass()}, "SomeClass.method"),480 'basic-syntax09': testcase("{{ var.method }}", {"var": SomeClass()}, "SomeClass.method"), 470 481 471 482 # Multiple levels of attribute access are allowed 472 'basic-syntax10': ("{{ var.otherclass.method }}", {"var": SomeClass()}, "OtherClass.method"),483 'basic-syntax10': testcase("{{ var.otherclass.method }}", {"var": SomeClass()}, "OtherClass.method"), 473 484 474 485 # Fail silently when a variable's attribute isn't found 475 'basic-syntax11': ("{{ var.blech }}", {"var": SomeClass()}, ("","INVALID")), 486 'basic-syntax11': testcase("{{ var.blech }}", {"var": SomeClass()}, 487 lambda tdebug, invalid_str: invalid_str and "INVALID" or ""), 476 488 477 489 # Raise TemplateSyntaxError when trying to access a variable beginning with an underscore 478 'basic-syntax12': ("{{ var.__dict__ }}", {"var": SomeClass()}, template.TemplateSyntaxError),490 'basic-syntax12': testcase("{{ var.__dict__ }}", {"var": SomeClass()}, template.TemplateSyntaxError), 479 491 480 492 # Raise TemplateSyntaxError when trying to access a variable containing an illegal character 481 'basic-syntax13': ("{{ va>r }}", {}, template.TemplateSyntaxError),482 'basic-syntax14': ("{{ (var.r) }}", {}, template.TemplateSyntaxError),483 'basic-syntax15': ("{{ sp%am }}", {}, template.TemplateSyntaxError),484 'basic-syntax16': ("{{ eggs! }}", {}, template.TemplateSyntaxError),485 'basic-syntax17': ("{{ moo? }}", {}, template.TemplateSyntaxError),493 'basic-syntax13': testcase("{{ va>r }}", {}, template.TemplateSyntaxError), 494 'basic-syntax14': testcase("{{ (var.r) }}", {}, template.TemplateSyntaxError), 495 'basic-syntax15': testcase("{{ sp%am }}", {}, template.TemplateSyntaxError), 496 'basic-syntax16': testcase("{{ eggs! }}", {}, template.TemplateSyntaxError), 497 'basic-syntax17': testcase("{{ moo? }}", {}, template.TemplateSyntaxError), 486 498 487 499 # Attribute syntax allows a template to call a dictionary key's value 488 'basic-syntax18': ("{{ foo.bar }}", {"foo" : {"bar" : "baz"}}, "baz"),500 'basic-syntax18': testcase("{{ foo.bar }}", {"foo" : {"bar" : "baz"}}, "baz"), 489 501 490 502 # Fail silently when a variable's dictionary key isn't found 491 'basic-syntax19': ("{{ foo.spam }}", {"foo" : {"bar" : "baz"}}, ("","INVALID")), 503 'basic-syntax19': testcase("{{ foo.spam }}", {"foo" : {"bar" : "baz"}}, 504 lambda tdebug, invalid_str: invalid_str and "INVALID" or ""), 492 505 493 506 # Fail silently when accessing a non-simple method 494 'basic-syntax20': ("{{ var.method2 }}", {"var": SomeClass()}, ("","INVALID")), 507 'basic-syntax20': testcase("{{ var.method2 }}", {"var": SomeClass()}, 508 lambda tdebug, invalid_str: invalid_str and "INVALID" or ""), 495 509 496 510 # Don't get confused when parsing something that is almost, but not 497 511 # quite, a template tag. 498 'basic-syntax21': ("a {{ moo %} b", {}, "a {{ moo %} b"),499 'basic-syntax22': ("{{ moo #}", {}, "{{ moo #}"),512 'basic-syntax21': testcase("a {{ moo %} b", {}, "a {{ moo %} b"), 513 'basic-syntax22': testcase("{{ moo #}", {}, "{{ moo #}"), 500 514 501 515 # Will try to treat "moo #} {{ cow" as the variable. Not ideal, but 502 516 # costly to work around, so this triggers an error. 503 'basic-syntax23': ("{{ moo #} {{ cow }}", {"cow": "cow"}, template.TemplateSyntaxError),517 'basic-syntax23': testcase("{{ moo #} {{ cow }}", {"cow": "cow"}, template.TemplateSyntaxError), 504 518 505 519 # Embedded newlines make it not-a-tag. 506 'basic-syntax24': ("{{ moo\n }}", {}, "{{ moo\n }}"),520 'basic-syntax24': testcase("{{ moo\n }}", {}, "{{ moo\n }}"), 507 521 508 522 # Literal strings are permitted inside variables, mostly for i18n 509 523 # purposes. 510 'basic-syntax25': ('{{ "fred" }}', {}, "fred"),511 'basic-syntax26': (r'{{ "\"fred\"" }}', {}, "\"fred\""),512 'basic-syntax27': (r'{{ _("\"fred\"") }}', {}, "\"fred\""),524 'basic-syntax25': testcase('{{ "fred" }}', {}, "fred"), 525 'basic-syntax26': testcase(r'{{ "\"fred\"" }}', {}, "\"fred\""), 526 'basic-syntax27': testcase(r'{{ _("\"fred\"") }}', {}, "\"fred\""), 513 527 514 528 # regression test for ticket #12554 515 529 # make sure a silent_variable_failure Exception is supressed 516 530 # on dictionary and attribute lookup 517 'basic-syntax28': ("{{ a.b }}", {'a': SilentGetItemClass()}, ('', 'INVALID')), 518 'basic-syntax29': ("{{ a.b }}", {'a': SilentAttrClass()}, ('', 'INVALID')), 531 'basic-syntax28': testcase("{{ a.b }}", {'a': SilentGetItemClass()}, 532 lambda tdebug, invalid_str: invalid_str and "INVALID" or ""), 533 'basic-syntax29': testcase("{{ a.b }}", {'a': SilentAttrClass()}, 534 lambda tdebug, invalid_str: invalid_str and "INVALID" or ""), 519 535 520 536 # Something that starts like a number but has an extra lookup works as a lookup. 521 'basic-syntax30': ("{{ 1.2.3 }}", {"1": {"2": {"3": "d"}}}, "d"),522 'basic-syntax31': ("{{ 1.2.3 }}", {"1": {"2": ("a", "b", "c", "d")}}, "d"),523 'basic-syntax32': ("{{ 1.2.3 }}", {"1": (("x", "x", "x", "x"), ("y", "y", "y", "y"), ("a", "b", "c", "d"))}, "d"),524 'basic-syntax33': ("{{ 1.2.3 }}", {"1": ("xxxx", "yyyy", "abcd")}, "d"),525 'basic-syntax34': ("{{ 1.2.3 }}", {"1": ({"x": "x"}, {"y": "y"}, {"z": "z", "3": "d"})}, "d"),537 'basic-syntax30': testcase("{{ 1.2.3 }}", {"1": {"2": {"3": "d"}}}, "d"), 538 'basic-syntax31': testcase("{{ 1.2.3 }}", {"1": {"2": ("a", "b", "c", "d")}}, "d"), 539 'basic-syntax32': testcase("{{ 1.2.3 }}", {"1": (("x", "x", "x", "x"), ("y", "y", "y", "y"), ("a", "b", "c", "d"))}, "d"), 540 'basic-syntax33': testcase("{{ 1.2.3 }}", {"1": ("xxxx", "yyyy", "abcd")}, "d"), 541 'basic-syntax34': testcase("{{ 1.2.3 }}", {"1": ({"x": "x"}, {"y": "y"}, {"z": "z", "3": "d"})}, "d"), 526 542 527 543 # Numbers are numbers even if their digits are in the context. 528 'basic-syntax35': ("{{ 1 }}", {"1": "abc"}, "1"),529 'basic-syntax36': ("{{ 1.2 }}", {"1": "abc"}, "1.2"),544 'basic-syntax35': testcase("{{ 1 }}", {"1": "abc"}, "1"), 545 'basic-syntax36': testcase("{{ 1.2 }}", {"1": "abc"}, "1.2"), 530 546 531 547 # List-index syntax allows a template to access a certain item of a subscriptable object. 532 'list-index01': ("{{ var.1 }}", {"var": ["first item", "second item"]}, "second item"),548 'list-index01': testcase("{{ var.1 }}", {"var": ["first item", "second item"]}, "second item"), 533 549 534 550 # Fail silently when the list index is out of range. 535 'list-index02': ("{{ var.5 }}", {"var": ["first item", "second item"]}, ("", "INVALID")), 551 'list-index02': testcase("{{ var.5 }}", {"var": ["first item", "second item"]}, 552 lambda tdebug, invalid_str: invalid_str and "INVALID" or ""), 536 553 537 554 # Fail silently when the variable is not a subscriptable object. 538 'list-index03': ("{{ var.1 }}", {"var": None}, ("", "INVALID")), 555 'list-index03': testcase("{{ var.1 }}", {"var": None}, 556 lambda tdebug, invalid_str: invalid_str and "INVALID" or ""), 539 557 540 558 # Fail silently when variable is a dict without the specified key. 541 'list-index04': ("{{ var.1 }}", {"var": {}}, ("", "INVALID")), 559 'list-index04': testcase("{{ var.1 }}", {"var": {}}, 560 lambda tdebug, invalid_str: invalid_str and "INVALID" or ""), 542 561 543 562 # Dictionary lookup wins out when dict's key is a string. 544 'list-index05': ("{{ var.1 }}", {"var": {'1': "hello"}}, "hello"),563 'list-index05': testcase("{{ var.1 }}", {"var": {'1': "hello"}}, "hello"), 545 564 546 565 # But list-index lookup wins out when dict's key is an int, which 547 566 # behind the scenes is really a dictionary lookup (for a dict) 548 567 # after converting the key to an int. 549 'list-index06': ("{{ var.1 }}", {"var": {1: "hello"}}, "hello"),568 'list-index06': testcase("{{ var.1 }}", {"var": {1: "hello"}}, "hello"), 550 569 551 570 # Dictionary lookup wins out when there is a string and int version of the key. 552 'list-index07': ("{{ var.1 }}", {"var": {'1': "hello", 1: "world"}}, "hello"),571 'list-index07': testcase("{{ var.1 }}", {"var": {'1': "hello", 1: "world"}}, "hello"), 553 572 554 573 # Basic filter usage 555 'filter-syntax01': ("{{ var|upper }}", {"var": "Django is the greatest!"}, "DJANGO IS THE GREATEST!"),574 'filter-syntax01': testcase("{{ var|upper }}", {"var": "Django is the greatest!"}, "DJANGO IS THE GREATEST!"), 556 575 557 576 # Chained filters 558 'filter-syntax02': ("{{ var|upper|lower }}", {"var": "Django is the greatest!"}, "django is the greatest!"),577 'filter-syntax02': testcase("{{ var|upper|lower }}", {"var": "Django is the greatest!"}, "django is the greatest!"), 559 578 560 579 # Raise TemplateSyntaxError for space between a variable and filter pipe 561 'filter-syntax03': ("{{ var |upper }}", {}, template.TemplateSyntaxError),580 'filter-syntax03': testcase("{{ var |upper }}", {}, template.TemplateSyntaxError), 562 581 563 582 # Raise TemplateSyntaxError for space after a filter pipe 564 'filter-syntax04': ("{{ var| upper }}", {}, template.TemplateSyntaxError),583 'filter-syntax04': testcase("{{ var| upper }}", {}, template.TemplateSyntaxError), 565 584 566 585 # Raise TemplateSyntaxError for a nonexistent filter 567 'filter-syntax05': ("{{ var|does_not_exist }}", {}, template.TemplateSyntaxError),586 'filter-syntax05': testcase("{{ var|does_not_exist }}", {}, template.TemplateSyntaxError), 568 587 569 588 # Raise TemplateSyntaxError when trying to access a filter containing an illegal character 570 'filter-syntax06': ("{{ var|fil(ter) }}", {}, template.TemplateSyntaxError),589 'filter-syntax06': testcase("{{ var|fil(ter) }}", {}, template.TemplateSyntaxError), 571 590 572 591 # Raise TemplateSyntaxError for invalid block tags 573 'filter-syntax07': ("{% nothing_to_see_here %}", {}, template.TemplateSyntaxError),592 'filter-syntax07': testcase("{% nothing_to_see_here %}", {}, template.TemplateSyntaxError), 574 593 575 594 # Raise TemplateSyntaxError for empty block tags 576 'filter-syntax08': ("{% %}", {}, template.TemplateSyntaxError),595 'filter-syntax08': testcase("{% %}", {}, template.TemplateSyntaxError), 577 596 578 597 # Chained filters, with an argument to the first one 579 'filter-syntax09': ('{{ var|removetags:"b i"|upper|lower }}', {"var": "<b><i>Yes</i></b>"}, "yes"),598 'filter-syntax09': testcase('{{ var|removetags:"b i"|upper|lower }}', {"var": "<b><i>Yes</i></b>"}, "yes"), 580 599 581 600 # Literal string as argument is always "safe" from auto-escaping.. 582 'filter-syntax10': (r'{{ var|default_if_none:" endquote\" hah" }}',601 'filter-syntax10': testcase(r'{{ var|default_if_none:" endquote\" hah" }}', 583 602 {"var": None}, ' endquote" hah'), 584 603 585 604 # Variable as argument 586 'filter-syntax11': (r'{{ var|default_if_none:var2 }}', {"var": None, "var2": "happy"}, 'happy'),605 'filter-syntax11': testcase(r'{{ var|default_if_none:var2 }}', {"var": None, "var2": "happy"}, 'happy'), 587 606 588 607 # Default argument testing 589 'filter-syntax12': (r'{{ var|yesno:"yup,nup,mup" }} {{ var|yesno }}', {"var": True}, 'yup yes'),608 'filter-syntax12': testcase(r'{{ var|yesno:"yup,nup,mup" }} {{ var|yesno }}', {"var": True}, 'yup yes'), 590 609 591 610 # Fail silently for methods that raise an exception with a 592 611 # "silent_variable_failure" attribute 593 'filter-syntax13': (r'1{{ var.method3 }}2', {"var": SomeClass()}, ("12", "1INVALID2")), 612 'filter-syntax13': testcase(r'1{{ var.method3 }}2', {"var": SomeClass()}, 613 lambda tdebug, invalid_str: invalid_str and "1INVALID2" or "12"), 594 614 595 615 # In methods that raise an exception without a 596 616 # "silent_variable_attribute" set to True, the exception propagates 597 'filter-syntax14': (r'1{{ var.method4 }}2', {"var": SomeClass()}, SomeOtherException), 617 'filter-syntax14': testcase(r'1{{ var.method4 }}2', {"var": SomeClass()}, 618 lambda tdebug, invalid_str: tdebug and template.TemplateSyntaxError or SomeOtherException), 598 619 599 620 # Escaped backslash in argument 600 'filter-syntax15': (r'{{ var|default_if_none:"foo\bar" }}', {"var": None}, r'foo\bar'),621 'filter-syntax15': testcase(r'{{ var|default_if_none:"foo\bar" }}', {"var": None}, r'foo\bar'), 601 622 602 623 # Escaped backslash using known escape char 603 'filter-syntax16': (r'{{ var|default_if_none:"foo\now" }}', {"var": None}, r'foo\now'),624 'filter-syntax16': testcase(r'{{ var|default_if_none:"foo\now" }}', {"var": None}, r'foo\now'), 604 625 605 626 # Empty strings can be passed as arguments to filters 606 'filter-syntax17': (r'{{ var|join:"" }}', {'var': ['a', 'b', 'c']}, 'abc'),627 'filter-syntax17': testcase(r'{{ var|join:"" }}', {'var': ['a', 'b', 'c']}, 'abc'), 607 628 608 629 # Make sure that any unicode strings are converted to bytestrings 609 630 # in the final output. 610 'filter-syntax18': (r'{{ var }}', {'var': UTF8Class()}, u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111'),631 'filter-syntax18': testcase(r'{{ var }}', {'var': UTF8Class()}, u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111'), 611 632 612 633 # Numbers as filter arguments should work 613 'filter-syntax19': ('{{ var|truncatewords:1 }}', {"var": "hello world"}, "hello ..."),634 'filter-syntax19': testcase('{{ var|truncatewords:1 }}', {"var": "hello world"}, "hello ..."), 614 635 615 636 #filters should accept empty string constants 616 'filter-syntax20': ('{{ ""|default_if_none:"was none" }}', {}, ""),637 'filter-syntax20': testcase('{{ ""|default_if_none:"was none" }}', {}, ""), 617 638 618 639 ### COMMENT SYNTAX ######################################################## 619 'comment-syntax01': ("{# this is hidden #}hello", {}, "hello"),620 'comment-syntax02': ("{# this is hidden #}hello{# foo #}", {}, "hello"),640 'comment-syntax01': testcase("{# this is hidden #}hello", {}, "hello"), 641 'comment-syntax02': testcase("{# this is hidden #}hello{# foo #}", {}, "hello"), 621 642 622 643 # Comments can contain invalid stuff. 623 'comment-syntax03': ("foo{# {% if %} #}", {}, "foo"),624 'comment-syntax04': ("foo{# {% endblock %} #}", {}, "foo"),625 'comment-syntax05': ("foo{# {% somerandomtag %} #}", {}, "foo"),626 'comment-syntax06': ("foo{# {% #}", {}, "foo"),627 'comment-syntax07': ("foo{# %} #}", {}, "foo"),628 'comment-syntax08': ("foo{# %} #}bar", {}, "foobar"),629 'comment-syntax09': ("foo{# {{ #}", {}, "foo"),630 'comment-syntax10': ("foo{# }} #}", {}, "foo"),631 'comment-syntax11': ("foo{# { #}", {}, "foo"),632 'comment-syntax12': ("foo{# } #}", {}, "foo"),644 'comment-syntax03': testcase("foo{# {% if %} #}", {}, "foo"), 645 'comment-syntax04': testcase("foo{# {% endblock %} #}", {}, "foo"), 646 'comment-syntax05': testcase("foo{# {% somerandomtag %} #}", {}, "foo"), 647 'comment-syntax06': testcase("foo{# {% #}", {}, "foo"), 648 'comment-syntax07': testcase("foo{# %} #}", {}, "foo"), 649 'comment-syntax08': testcase("foo{# %} #}bar", {}, "foobar"), 650 'comment-syntax09': testcase("foo{# {{ #}", {}, "foo"), 651 'comment-syntax10': testcase("foo{# }} #}", {}, "foo"), 652 'comment-syntax11': testcase("foo{# { #}", {}, "foo"), 653 'comment-syntax12': testcase("foo{# } #}", {}, "foo"), 633 654 634 655 ### COMMENT TAG ########################################################### 635 'comment-tag01': ("{% comment %}this is hidden{% endcomment %}hello", {}, "hello"),636 'comment-tag02': ("{% comment %}this is hidden{% endcomment %}hello{% comment %}foo{% endcomment %}", {}, "hello"),656 'comment-tag01': testcase("{% comment %}this is hidden{% endcomment %}hello", {}, "hello"), 657 'comment-tag02': testcase("{% comment %}this is hidden{% endcomment %}hello{% comment %}foo{% endcomment %}", {}, "hello"), 637 658 638 659 # Comment tag can contain invalid stuff. 639 'comment-tag03': ("foo{% comment %} {% if %} {% endcomment %}", {}, "foo"),640 'comment-tag04': ("foo{% comment %} {% endblock %} {% endcomment %}", {}, "foo"),641 'comment-tag05': ("foo{% comment %} {% somerandomtag %} {% endcomment %}", {}, "foo"),660 'comment-tag03': testcase("foo{% comment %} {% if %} {% endcomment %}", {}, "foo"), 661 'comment-tag04': testcase("foo{% comment %} {% endblock %} {% endcomment %}", {}, "foo"), 662 'comment-tag05': testcase("foo{% comment %} {% somerandomtag %} {% endcomment %}", {}, "foo"), 642 663 643 664 ### CYCLE TAG ############################################################# 644 'cycle01': ('{% cycle a %}', {}, template.TemplateSyntaxError),645 'cycle02': ('{% cycle a,b,c as abc %}{% cycle abc %}', {}, 'ab'),646 'cycle03': ('{% cycle a,b,c as abc %}{% cycle abc %}{% cycle abc %}', {}, 'abc'),647 'cycle04': ('{% cycle a,b,c as abc %}{% cycle abc %}{% cycle abc %}{% cycle abc %}', {}, 'abca'),648 'cycle05': ('{% cycle %}', {}, template.TemplateSyntaxError),649 'cycle06': ('{% cycle a %}', {}, template.TemplateSyntaxError),650 'cycle07': ('{% cycle a,b,c as foo %}{% cycle bar %}', {}, template.TemplateSyntaxError),651 'cycle08': ('{% cycle a,b,c as foo %}{% cycle foo %}{{ foo }}{{ foo }}{% cycle foo %}{{ foo }}', {}, 'abbbcc'),652 'cycle09': ("{% for i in test %}{% cycle a,b %}{{ i }},{% endfor %}", {'test': range(5)}, 'a0,b1,a2,b3,a4,'),653 'cycle10': ("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}", {}, 'ab'),654 'cycle11': ("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}{% cycle abc %}", {}, 'abc'),655 'cycle12': ("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}{% cycle abc %}{% cycle abc %}", {}, 'abca'),656 'cycle13': ("{% for i in test %}{% cycle 'a' 'b' %}{{ i }},{% endfor %}", {'test': range(5)}, 'a0,b1,a2,b3,a4,'),657 'cycle14': ("{% cycle one two as foo %}{% cycle foo %}", {'one': '1','two': '2'}, '12'),658 'cycle15': ("{% for i in test %}{% cycle aye bee %}{{ i }},{% endfor %}", {'test': range(5), 'aye': 'a', 'bee': 'b'}, 'a0,b1,a2,b3,a4,'),659 'cycle16': ("{% cycle one|lower two as foo %}{% cycle foo %}", {'one': 'A','two': '2'}, 'a2'),660 'cycle17': ("{% cycle 'a' 'b' 'c' as abc silent %}{% cycle abc %}{% cycle abc %}{% cycle abc %}{% cycle abc %}", {}, "abca"),661 'cycle18': ("{% cycle 'a' 'b' 'c' as foo invalid_flag %}", {}, template.TemplateSyntaxError),662 'cycle19': ("{% cycle 'a' 'b' as silent %}{% cycle silent %}", {}, "ab"),665 'cycle01': testcase('{% cycle a %}', {}, template.TemplateSyntaxError), 666 'cycle02': testcase('{% cycle a,b,c as abc %}{% cycle abc %}', {}, 'ab'), 667 'cycle03': testcase('{% cycle a,b,c as abc %}{% cycle abc %}{% cycle abc %}', {}, 'abc'), 668 'cycle04': testcase('{% cycle a,b,c as abc %}{% cycle abc %}{% cycle abc %}{% cycle abc %}', {}, 'abca'), 669 'cycle05': testcase('{% cycle %}', {}, template.TemplateSyntaxError), 670 'cycle06': testcase('{% cycle a %}', {}, template.TemplateSyntaxError), 671 'cycle07': testcase('{% cycle a,b,c as foo %}{% cycle bar %}', {}, template.TemplateSyntaxError), 672 'cycle08': testcase('{% cycle a,b,c as foo %}{% cycle foo %}{{ foo }}{{ foo }}{% cycle foo %}{{ foo }}', {}, 'abbbcc'), 673 'cycle09': testcase("{% for i in test %}{% cycle a,b %}{{ i }},{% endfor %}", {'test': range(5)}, 'a0,b1,a2,b3,a4,'), 674 'cycle10': testcase("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}", {}, 'ab'), 675 'cycle11': testcase("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}{% cycle abc %}", {}, 'abc'), 676 'cycle12': testcase("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}{% cycle abc %}{% cycle abc %}", {}, 'abca'), 677 'cycle13': testcase("{% for i in test %}{% cycle 'a' 'b' %}{{ i }},{% endfor %}", {'test': range(5)}, 'a0,b1,a2,b3,a4,'), 678 'cycle14': testcase("{% cycle one two as foo %}{% cycle foo %}", {'one': '1','two': '2'}, '12'), 679 'cycle15': testcase("{% for i in test %}{% cycle aye bee %}{{ i }},{% endfor %}", {'test': range(5), 'aye': 'a', 'bee': 'b'}, 'a0,b1,a2,b3,a4,'), 680 'cycle16': testcase("{% cycle one|lower two as foo %}{% cycle foo %}", {'one': 'A','two': '2'}, 'a2'), 681 'cycle17': testcase("{% cycle 'a' 'b' 'c' as abc silent %}{% cycle abc %}{% cycle abc %}{% cycle abc %}{% cycle abc %}", {}, "abca"), 682 'cycle18': testcase("{% cycle 'a' 'b' 'c' as foo invalid_flag %}", {}, template.TemplateSyntaxError), 683 'cycle19': testcase("{% cycle 'a' 'b' as silent %}{% cycle silent %}", {}, "ab"), 663 684 664 685 ### EXCEPTIONS ############################################################ 665 686 666 687 # Raise exception for invalid template name 667 'exception01': ("{% extends 'nonexistent' %}", {}, template.TemplateDoesNotExist), 688 'exception01': testcase("{% extends 'nonexistent' %}", {}, 689 lambda tdebug, invalid_str: tdebug and template.TemplateSyntaxError or template.TemplateDoesNotExist), 668 690 669 691 # Raise exception for invalid template name (in variable) 670 'exception02': ("{% extends nonexistent %}", {}, (template.TemplateSyntaxError, template.TemplateDoesNotExist)), 692 'exception02': testcase("{% extends nonexistent %}", {}, 693 lambda tdebug, invalid_str: (invalid_str and not tdebug) and template.TemplateDoesNotExist or template.TemplateSyntaxError), 671 694 672 695 # Raise exception for extra {% extends %} tags 673 'exception03': ("{% extends 'inheritance01' %}{% block first %}2{% endblock %}{% extends 'inheritance16' %}", {}, template.TemplateSyntaxError), 696 'exception03': testcase("{% extends 'inheritance01' %}{% block first %}2{% endblock %}{% extends 'inheritance16' %}", 697 {}, template.TemplateSyntaxError), 674 698 675 699 # Raise exception for custom tags used in child with {% load %} tag in parent, not in child 676 'exception04': ("{% extends 'inheritance17' %}{% block first %}{% echo 400 %}5678{% endblock %}", {}, template.TemplateSyntaxError), 700 'exception04': testcase("{% extends 'inheritance17' %}{% block first %}{% echo 400 %}5678{% endblock %}", 701 {}, template.TemplateSyntaxError), 677 702 678 703 ### FILTER TAG ############################################################ 679 'filter01': ('{% filter upper %}{% endfilter %}', {}, ''),680 'filter02': ('{% filter upper %}django{% endfilter %}', {}, 'DJANGO'),681 'filter03': ('{% filter upper|lower %}django{% endfilter %}', {}, 'django'),682 'filter04': ('{% filter cut:remove %}djangospam{% endfilter %}', {'remove': 'spam'}, 'django'),704 'filter01': testcase('{% filter upper %}{% endfilter %}', {}, ''), 705 'filter02': testcase('{% filter upper %}django{% endfilter %}', {}, 'DJANGO'), 706 'filter03': testcase('{% filter upper|lower %}django{% endfilter %}', {}, 'django'), 707 'filter04': testcase('{% filter cut:remove %}djangospam{% endfilter %}', {'remove': 'spam'}, 'django'), 683 708 684 709 ### FIRSTOF TAG ########################################################### 685 'firstof01': ('{% firstof a b c %}', {'a':0,'b':0,'c':0}, ''),686 'firstof02': ('{% firstof a b c %}', {'a':1,'b':0,'c':0}, '1'),687 'firstof03': ('{% firstof a b c %}', {'a':0,'b':2,'c':0}, '2'),688 'firstof04': ('{% firstof a b c %}', {'a':0,'b':0,'c':3}, '3'),689 'firstof05': ('{% firstof a b c %}', {'a':1,'b':2,'c':3}, '1'),690 'firstof06': ('{% firstof a b c %}', {'b':0,'c':3}, '3'),691 'firstof07': ('{% firstof a b "c" %}', {'a':0}, 'c'),692 'firstof08': ('{% firstof a b "c and d" %}', {'a':0,'b':0}, 'c and d'),693 'firstof09': ('{% firstof %}', {}, template.TemplateSyntaxError),710 'firstof01': testcase('{% firstof a b c %}', {'a':0,'b':0,'c':0}, ''), 711 'firstof02': testcase('{% firstof a b c %}', {'a':1,'b':0,'c':0}, '1'), 712 'firstof03': testcase('{% firstof a b c %}', {'a':0,'b':2,'c':0}, '2'), 713 'firstof04': testcase('{% firstof a b c %}', {'a':0,'b':0,'c':3}, '3'), 714 'firstof05': testcase('{% firstof a b c %}', {'a':1,'b':2,'c':3}, '1'), 715 'firstof06': testcase('{% firstof a b c %}', {'b':0,'c':3}, '3'), 716 'firstof07': testcase('{% firstof a b "c" %}', {'a':0}, 'c'), 717 'firstof08': testcase('{% firstof a b "c and d" %}', {'a':0,'b':0}, 'c and d'), 718 'firstof09': testcase('{% firstof %}', {}, template.TemplateSyntaxError), 694 719 695 720 ### FOR TAG ############################################################### 696 'for-tag01': ("{% for val in values %}{{ val }}{% endfor %}", {"values": [1, 2, 3]}, "123"),697 'for-tag02': ("{% for val in values reversed %}{{ val }}{% endfor %}", {"values": [1, 2, 3]}, "321"),698 'for-tag-vars01': ("{% for val in values %}{{ forloop.counter }}{% endfor %}", {"values": [6, 6, 6]}, "123"),699 'for-tag-vars02': ("{% for val in values %}{{ forloop.counter0 }}{% endfor %}", {"values": [6, 6, 6]}, "012"),700 'for-tag-vars03': ("{% for val in values %}{{ forloop.revcounter }}{% endfor %}", {"values": [6, 6, 6]}, "321"),701 'for-tag-vars04': ("{% for val in values %}{{ forloop.revcounter0 }}{% endfor %}", {"values": [6, 6, 6]}, "210"),702 'for-tag-vars05': ("{% for val in values %}{% if forloop.first %}f{% else %}x{% endif %}{% endfor %}", {"values": [6, 6, 6]}, "fxx"),703 'for-tag-vars06': ("{% for val in values %}{% if forloop.last %}l{% else %}x{% endif %}{% endfor %}", {"values": [6, 6, 6]}, "xxl"),704 'for-tag-unpack01': ("{% for key,value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"),705 'for-tag-unpack03': ("{% for key, value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"),706 'for-tag-unpack04': ("{% for key , value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"),707 'for-tag-unpack05': ("{% for key ,value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"),708 'for-tag-unpack06': ("{% for key value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, template.TemplateSyntaxError),709 'for-tag-unpack07': ("{% for key,,value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, template.TemplateSyntaxError),710 'for-tag-unpack08': ("{% for key,value, in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, template.TemplateSyntaxError),721 'for-tag01': testcase("{% for val in values %}{{ val }}{% endfor %}", {"values": [1, 2, 3]}, "123"), 722 'for-tag02': testcase("{% for val in values reversed %}{{ val }}{% endfor %}", {"values": [1, 2, 3]}, "321"), 723 'for-tag-vars01': testcase("{% for val in values %}{{ forloop.counter }}{% endfor %}", {"values": [6, 6, 6]}, "123"), 724 'for-tag-vars02': testcase("{% for val in values %}{{ forloop.counter0 }}{% endfor %}", {"values": [6, 6, 6]}, "012"), 725 'for-tag-vars03': testcase("{% for val in values %}{{ forloop.revcounter }}{% endfor %}", {"values": [6, 6, 6]}, "321"), 726 'for-tag-vars04': testcase("{% for val in values %}{{ forloop.revcounter0 }}{% endfor %}", {"values": [6, 6, 6]}, "210"), 727 'for-tag-vars05': testcase("{% for val in values %}{% if forloop.first %}f{% else %}x{% endif %}{% endfor %}", {"values": [6, 6, 6]}, "fxx"), 728 'for-tag-vars06': testcase("{% for val in values %}{% if forloop.last %}l{% else %}x{% endif %}{% endfor %}", {"values": [6, 6, 6]}, "xxl"), 729 'for-tag-unpack01': testcase("{% for key,value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"), 730 'for-tag-unpack03': testcase("{% for key, value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"), 731 'for-tag-unpack04': testcase("{% for key , value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"), 732 'for-tag-unpack05': testcase("{% for key ,value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"), 733 'for-tag-unpack06': testcase("{% for key value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, template.TemplateSyntaxError), 734 'for-tag-unpack07': testcase("{% for key,,value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, template.TemplateSyntaxError), 735 'for-tag-unpack08': testcase("{% for key,value, in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, template.TemplateSyntaxError), 711 736 # Ensure that a single loopvar doesn't truncate the list in val. 712 'for-tag-unpack09': ("{% for val in items %}{{ val.0 }}:{{ val.1 }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"),737 'for-tag-unpack09': testcase("{% for val in items %}{{ val.0 }}:{{ val.1 }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"), 713 738 # Otherwise, silently truncate if the length of loopvars differs to the length of each set of items. 714 'for-tag-unpack10': ("{% for x,y in items %}{{ x }}:{{ y }}/{% endfor %}", {"items": (('one', 1, 'carrot'), ('two', 2, 'orange'))}, "one:1/two:2/"), 715 'for-tag-unpack11': ("{% for x,y,z in items %}{{ x }}:{{ y }},{{ z }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, ("one:1,/two:2,/", "one:1,INVALID/two:2,INVALID/")), 716 'for-tag-unpack12': ("{% for x,y,z in items %}{{ x }}:{{ y }},{{ z }}/{% endfor %}", {"items": (('one', 1, 'carrot'), ('two', 2))}, ("one:1,carrot/two:2,/", "one:1,carrot/two:2,INVALID/")), 717 'for-tag-unpack13': ("{% for x,y,z in items %}{{ x }}:{{ y }},{{ z }}/{% endfor %}", {"items": (('one', 1, 'carrot'), ('two', 2, 'cheese'))}, ("one:1,carrot/two:2,cheese/", "one:1,carrot/two:2,cheese/")), 718 'for-tag-unpack14': ("{% for x,y in items %}{{ x }}:{{ y }}/{% endfor %}", {"items": (1, 2)}, (":/:/", "INVALID:INVALID/INVALID:INVALID/")), 719 'for-tag-empty01': ("{% for val in values %}{{ val }}{% empty %}empty text{% endfor %}", {"values": [1, 2, 3]}, "123"), 720 'for-tag-empty02': ("{% for val in values %}{{ val }}{% empty %}values array empty{% endfor %}", {"values": []}, "values array empty"), 721 'for-tag-empty03': ("{% for val in values %}{{ val }}{% empty %}values array not found{% endfor %}", {}, "values array not found"), 739 'for-tag-unpack10': testcase("{% for x,y in items %}{{ x }}:{{ y }}/{% endfor %}", {"items": (('one', 1, 'carrot'), ('two', 2, 'orange'))}, "one:1/two:2/"), 740 'for-tag-unpack11': testcase("{% for x,y,z in items %}{{ x }}:{{ y }},{{ z }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, 741 lambda tdebug, invalid_str: invalid_str and "one:1,INVALID/two:2,INVALID/" or "one:1,/two:2,/"), 742 'for-tag-unpack12': testcase("{% for x,y,z in items %}{{ x }}:{{ y }},{{ z }}/{% endfor %}", {"items": (('one', 1, 'carrot'), ('two', 2))}, 743 lambda tdebug, invalid_str: invalid_str and "one:1,carrot/two:2,INVALID/" or "one:1,carrot/two:2,/"), 744 'for-tag-unpack13': testcase("{% for x,y,z in items %}{{ x }}:{{ y }},{{ z }}/{% endfor %}", {"items": (('one', 1, 'carrot'), ('two', 2, 'cheese'))}, 745 "one:1,carrot/two:2,cheese/"), 722 746 747 'for-tag-unpack14': testcase("{% for x,y in items %}{{ x }}:{{ y }}/{% endfor %}", {"items": (1, 2)}, 748 lambda tdebug, invalid_str: invalid_str and "INVALID:INVALID/INVALID:INVALID/" or ":/:/"), 749 'for-tag-empty01': testcase("{% for val in values %}{{ val }}{% empty %}empty text{% endfor %}", {"values": [1, 2, 3]}, "123"), 750 'for-tag-empty02': testcase("{% for val in values %}{{ val }}{% empty %}values array empty{% endfor %}", {"values": []}, "values array empty"), 751 'for-tag-empty03': testcase("{% for val in values %}{{ val }}{% empty %}values array not found{% endfor %}", {}, "values array not found"), 752 723 753 ### IF TAG ################################################################ 724 'if-tag01': ("{% if foo %}yes{% else %}no{% endif %}", {"foo": True}, "yes"),725 'if-tag02': ("{% if foo %}yes{% else %}no{% endif %}", {"foo": False}, "no"),726 'if-tag03': ("{% if foo %}yes{% else %}no{% endif %}", {}, "no"),754 'if-tag01': testcase("{% if foo %}yes{% else %}no{% endif %}", {"foo": True}, "yes"), 755 'if-tag02': testcase("{% if foo %}yes{% else %}no{% endif %}", {"foo": False}, "no"), 756 'if-tag03': testcase("{% if foo %}yes{% else %}no{% endif %}", {}, "no"), 727 757 728 758 # Filters 729 'if-tag-filter01': ("{% if foo|length == 5 %}yes{% else %}no{% endif %}", {'foo': 'abcde'}, "yes"),730 'if-tag-filter02': ("{% if foo|upper == 'ABC' %}yes{% else %}no{% endif %}", {}, "no"),759 'if-tag-filter01': testcase("{% if foo|length == 5 %}yes{% else %}no{% endif %}", {'foo': 'abcde'}, "yes"), 760 'if-tag-filter02': testcase("{% if foo|upper == 'ABC' %}yes{% else %}no{% endif %}", {}, "no"), 731 761 732 762 # Equality 733 'if-tag-eq01': ("{% if foo == bar %}yes{% else %}no{% endif %}", {}, "yes"),734 'if-tag-eq02': ("{% if foo == bar %}yes{% else %}no{% endif %}", {'foo': 1}, "no"),735 'if-tag-eq03': ("{% if foo == bar %}yes{% else %}no{% endif %}", {'foo': 1, 'bar': 1}, "yes"),736 'if-tag-eq04': ("{% if foo == bar %}yes{% else %}no{% endif %}", {'foo': 1, 'bar': 2}, "no"),737 'if-tag-eq05': ("{% if foo == '' %}yes{% else %}no{% endif %}", {}, "no"),763 'if-tag-eq01': testcase("{% if foo == bar %}yes{% else %}no{% endif %}", {}, "yes"), 764 'if-tag-eq02': testcase("{% if foo == bar %}yes{% else %}no{% endif %}", {'foo': 1}, "no"), 765 'if-tag-eq03': testcase("{% if foo == bar %}yes{% else %}no{% endif %}", {'foo': 1, 'bar': 1}, "yes"), 766 'if-tag-eq04': testcase("{% if foo == bar %}yes{% else %}no{% endif %}", {'foo': 1, 'bar': 2}, "no"), 767 'if-tag-eq05': testcase("{% if foo == '' %}yes{% else %}no{% endif %}", {}, "no"), 738 768 739 769 # Comparison 740 'if-tag-gt-01': ("{% if 2 > 1 %}yes{% else %}no{% endif %}", {}, "yes"),741 'if-tag-gt-02': ("{% if 1 > 1 %}yes{% else %}no{% endif %}", {}, "no"),742 'if-tag-gte-01': ("{% if 1 >= 1 %}yes{% else %}no{% endif %}", {}, "yes"),743 'if-tag-gte-02': ("{% if 1 >= 2 %}yes{% else %}no{% endif %}", {}, "no"),744 'if-tag-lt-01': ("{% if 1 < 2 %}yes{% else %}no{% endif %}", {}, "yes"),745 'if-tag-lt-02': ("{% if 1 < 1 %}yes{% else %}no{% endif %}", {}, "no"),746 'if-tag-lte-01': ("{% if 1 <= 1 %}yes{% else %}no{% endif %}", {}, "yes"),747 'if-tag-lte-02': ("{% if 2 <= 1 %}yes{% else %}no{% endif %}", {}, "no"),770 'if-tag-gt-01': testcase("{% if 2 > 1 %}yes{% else %}no{% endif %}", {}, "yes"), 771 'if-tag-gt-02': testcase("{% if 1 > 1 %}yes{% else %}no{% endif %}", {}, "no"), 772 'if-tag-gte-01': testcase("{% if 1 >= 1 %}yes{% else %}no{% endif %}", {}, "yes"), 773 'if-tag-gte-02': testcase("{% if 1 >= 2 %}yes{% else %}no{% endif %}", {}, "no"), 774 'if-tag-lt-01': testcase("{% if 1 < 2 %}yes{% else %}no{% endif %}", {}, "yes"), 775 'if-tag-lt-02': testcase("{% if 1 < 1 %}yes{% else %}no{% endif %}", {}, "no"), 776 'if-tag-lte-01': testcase("{% if 1 <= 1 %}yes{% else %}no{% endif %}", {}, "yes"), 777 'if-tag-lte-02': testcase("{% if 2 <= 1 %}yes{% else %}no{% endif %}", {}, "no"), 748 778 749 779 # Contains 750 'if-tag-in-01': ("{% if 1 in x %}yes{% else %}no{% endif %}", {'x':[1]}, "yes"),751 'if-tag-in-02': ("{% if 2 in x %}yes{% else %}no{% endif %}", {'x':[1]}, "no"),752 'if-tag-not-in-01': ("{% if 1 not in x %}yes{% else %}no{% endif %}", {'x':[1]}, "no"),753 'if-tag-not-in-02': ("{% if 2 not in x %}yes{% else %}no{% endif %}", {'x':[1]}, "yes"),780 'if-tag-in-01': testcase("{% if 1 in x %}yes{% else %}no{% endif %}", {'x':[1]}, "yes"), 781 'if-tag-in-02': testcase("{% if 2 in x %}yes{% else %}no{% endif %}", {'x':[1]}, "no"), 782 'if-tag-not-in-01': testcase("{% if 1 not in x %}yes{% else %}no{% endif %}", {'x':[1]}, "no"), 783 'if-tag-not-in-02': testcase("{% if 2 not in x %}yes{% else %}no{% endif %}", {'x':[1]}, "yes"), 754 784 755 785 # AND 756 'if-tag-and01': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'yes'),757 'if-tag-and02': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'no'),758 'if-tag-and03': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'no'),759 'if-tag-and04': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'no'),760 'if-tag-and05': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': False}, 'no'),761 'if-tag-and06': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'bar': False}, 'no'),762 'if-tag-and07': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': True}, 'no'),763 'if-tag-and08': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'bar': True}, 'no'),786 'if-tag-and01': testcase("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'yes'), 787 'if-tag-and02': testcase("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'no'), 788 'if-tag-and03': testcase("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'no'), 789 'if-tag-and04': testcase("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'no'), 790 'if-tag-and05': testcase("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': False}, 'no'), 791 'if-tag-and06': testcase("{% if foo and bar %}yes{% else %}no{% endif %}", {'bar': False}, 'no'), 792 'if-tag-and07': testcase("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': True}, 'no'), 793 'if-tag-and08': testcase("{% if foo and bar %}yes{% else %}no{% endif %}", {'bar': True}, 'no'), 764 794 765 795 # OR 766 'if-tag-or01': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'yes'),767 'if-tag-or02': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'yes'),768 'if-tag-or03': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'yes'),769 'if-tag-or04': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'no'),770 'if-tag-or05': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': False}, 'no'),771 'if-tag-or06': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'bar': False}, 'no'),772 'if-tag-or07': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': True}, 'yes'),773 'if-tag-or08': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'bar': True}, 'yes'),796 'if-tag-or01': testcase("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'yes'), 797 'if-tag-or02': testcase("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'yes'), 798 'if-tag-or03': testcase("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'yes'), 799 'if-tag-or04': testcase("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'no'), 800 'if-tag-or05': testcase("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': False}, 'no'), 801 'if-tag-or06': testcase("{% if foo or bar %}yes{% else %}no{% endif %}", {'bar': False}, 'no'), 802 'if-tag-or07': testcase("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': True}, 'yes'), 803 'if-tag-or08': testcase("{% if foo or bar %}yes{% else %}no{% endif %}", {'bar': True}, 'yes'), 774 804 775 805 # multiple ORs 776 'if-tag-or09': ("{% if foo or bar or baz %}yes{% else %}no{% endif %}", {'baz': True}, 'yes'),806 'if-tag-or09': testcase("{% if foo or bar or baz %}yes{% else %}no{% endif %}", {'baz': True}, 'yes'), 777 807 778 808 # NOT 779 'if-tag-not01': ("{% if not foo %}no{% else %}yes{% endif %}", {'foo': True}, 'yes'),780 'if-tag-not02': ("{% if not not foo %}no{% else %}yes{% endif %}", {'foo': True}, 'no'),809 'if-tag-not01': testcase("{% if not foo %}no{% else %}yes{% endif %}", {'foo': True}, 'yes'), 810 'if-tag-not02': testcase("{% if not not foo %}no{% else %}yes{% endif %}", {'foo': True}, 'no'), 781 811 # not03 to not05 removed, now TemplateSyntaxErrors 782 812 783 'if-tag-not06': ("{% if foo and not bar %}yes{% else %}no{% endif %}", {}, 'no'),784 'if-tag-not07': ("{% if foo and not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'no'),785 'if-tag-not08': ("{% if foo and not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'yes'),786 'if-tag-not09': ("{% if foo and not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'no'),787 'if-tag-not10': ("{% if foo and not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'no'),813 'if-tag-not06': testcase("{% if foo and not bar %}yes{% else %}no{% endif %}", {}, 'no'), 814 'if-tag-not07': testcase("{% if foo and not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'no'), 815 'if-tag-not08': testcase("{% if foo and not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'yes'), 816 'if-tag-not09': testcase("{% if foo and not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'no'), 817 'if-tag-not10': testcase("{% if foo and not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'no'), 788 818 789 'if-tag-not11': ("{% if not foo and bar %}yes{% else %}no{% endif %}", {}, 'no'),790 'if-tag-not12': ("{% if not foo and bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'no'),791 'if-tag-not13': ("{% if not foo and bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'no'),792 'if-tag-not14': ("{% if not foo and bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'yes'),793 'if-tag-not15': ("{% if not foo and bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'no'),819 'if-tag-not11': testcase("{% if not foo and bar %}yes{% else %}no{% endif %}", {}, 'no'), 820 'if-tag-not12': testcase("{% if not foo and bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'no'), 821 'if-tag-not13': testcase("{% if not foo and bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'no'), 822 'if-tag-not14': testcase("{% if not foo and bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'yes'), 823 'if-tag-not15': testcase("{% if not foo and bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'no'), 794 824 795 'if-tag-not16': ("{% if foo or not bar %}yes{% else %}no{% endif %}", {}, 'yes'),796 'if-tag-not17': ("{% if foo or not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'yes'),797 'if-tag-not18': ("{% if foo or not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'yes'),798 'if-tag-not19': ("{% if foo or not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'no'),799 'if-tag-not20': ("{% if foo or not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'yes'),825 'if-tag-not16': testcase("{% if foo or not bar %}yes{% else %}no{% endif %}", {}, 'yes'), 826 'if-tag-not17': testcase("{% if foo or not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'yes'), 827 'if-tag-not18': testcase("{% if foo or not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'yes'), 828 'if-tag-not19': testcase("{% if foo or not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'no'), 829 'if-tag-not20': testcase("{% if foo or not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'yes'), 800 830 801 'if-tag-not21': ("{% if not foo or bar %}yes{% else %}no{% endif %}", {}, 'yes'),802 'if-tag-not22': ("{% if not foo or bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'yes'),803 'if-tag-not23': ("{% if not foo or bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'no'),804 'if-tag-not24': ("{% if not foo or bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'yes'),805 'if-tag-not25': ("{% if not foo or bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'yes'),831 'if-tag-not21': testcase("{% if not foo or bar %}yes{% else %}no{% endif %}", {}, 'yes'), 832 'if-tag-not22': testcase("{% if not foo or bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'yes'), 833 'if-tag-not23': testcase("{% if not foo or bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'no'), 834 'if-tag-not24': testcase("{% if not foo or bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'yes'), 835 'if-tag-not25': testcase("{% if not foo or bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'yes'), 806 836 807 'if-tag-not26': ("{% if not foo and not bar %}yes{% else %}no{% endif %}", {}, 'yes'),808 'if-tag-not27': ("{% if not foo and not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'no'),809 'if-tag-not28': ("{% if not foo and not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'no'),810 'if-tag-not29': ("{% if not foo and not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'no'),811 'if-tag-not30': ("{% if not foo and not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'yes'),837 'if-tag-not26': testcase("{% if not foo and not bar %}yes{% else %}no{% endif %}", {}, 'yes'), 838 'if-tag-not27': testcase("{% if not foo and not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'no'), 839 'if-tag-not28': testcase("{% if not foo and not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'no'), 840 'if-tag-not29': testcase("{% if not foo and not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'no'), 841 'if-tag-not30': testcase("{% if not foo and not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'yes'), 812 842 813 'if-tag-not31': ("{% if not foo or not bar %}yes{% else %}no{% endif %}", {}, 'yes'),814 'if-tag-not32': ("{% if not foo or not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'no'),815 'if-tag-not33': ("{% if not foo or not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'yes'),816 'if-tag-not34': ("{% if not foo or not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'yes'),817 'if-tag-not35': ("{% if not foo or not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'yes'),843 'if-tag-not31': testcase("{% if not foo or not bar %}yes{% else %}no{% endif %}", {}, 'yes'), 844 'if-tag-not32': testcase("{% if not foo or not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'no'), 845 'if-tag-not33': testcase("{% if not foo or not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'yes'), 846 'if-tag-not34': testcase("{% if not foo or not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'yes'), 847 'if-tag-not35': testcase("{% if not foo or not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'yes'), 818 848 819 849 # Various syntax errors 820 'if-tag-error01': ("{% if %}yes{% endif %}", {}, template.TemplateSyntaxError),821 'if-tag-error02': ("{% if foo and %}yes{% else %}no{% endif %}", {'foo': True}, template.TemplateSyntaxError),822 'if-tag-error03': ("{% if foo or %}yes{% else %}no{% endif %}", {'foo': True}, template.TemplateSyntaxError),823 'if-tag-error04': ("{% if not foo and %}yes{% else %}no{% endif %}", {'foo': True}, template.TemplateSyntaxError),824 'if-tag-error05': ("{% if not foo or %}yes{% else %}no{% endif %}", {'foo': True}, template.TemplateSyntaxError),825 'if-tag-error06': ("{% if abc def %}yes{% endif %}", {}, template.TemplateSyntaxError),826 'if-tag-error07': ("{% if not %}yes{% endif %}", {}, template.TemplateSyntaxError),827 'if-tag-error08': ("{% if and %}yes{% endif %}", {}, template.TemplateSyntaxError),828 'if-tag-error09': ("{% if or %}yes{% endif %}", {}, template.TemplateSyntaxError),829 'if-tag-error10': ("{% if == %}yes{% endif %}", {}, template.TemplateSyntaxError),830 'if-tag-error11': ("{% if 1 == %}yes{% endif %}", {}, template.TemplateSyntaxError),831 'if-tag-error12': ("{% if a not b %}yes{% endif %}", {}, template.TemplateSyntaxError),850 'if-tag-error01': testcase("{% if %}yes{% endif %}", {}, template.TemplateSyntaxError), 851 'if-tag-error02': testcase("{% if foo and %}yes{% else %}no{% endif %}", {'foo': True}, template.TemplateSyntaxError), 852 'if-tag-error03': testcase("{% if foo or %}yes{% else %}no{% endif %}", {'foo': True}, template.TemplateSyntaxError), 853 'if-tag-error04': testcase("{% if not foo and %}yes{% else %}no{% endif %}", {'foo': True}, template.TemplateSyntaxError), 854 'if-tag-error05': testcase("{% if not foo or %}yes{% else %}no{% endif %}", {'foo': True}, template.TemplateSyntaxError), 855 'if-tag-error06': testcase("{% if abc def %}yes{% endif %}", {}, template.TemplateSyntaxError), 856 'if-tag-error07': testcase("{% if not %}yes{% endif %}", {}, template.TemplateSyntaxError), 857 'if-tag-error08': testcase("{% if and %}yes{% endif %}", {}, template.TemplateSyntaxError), 858 'if-tag-error09': testcase("{% if or %}yes{% endif %}", {}, template.TemplateSyntaxError), 859 'if-tag-error10': testcase("{% if == %}yes{% endif %}", {}, template.TemplateSyntaxError), 860 'if-tag-error11': testcase("{% if 1 == %}yes{% endif %}", {}, template.TemplateSyntaxError), 861 'if-tag-error12': testcase("{% if a not b %}yes{% endif %}", {}, template.TemplateSyntaxError), 832 862 833 863 # If evaluations are shortcircuited where possible 834 864 # These tests will fail by taking too long to run. When the if clause 835 865 # is shortcircuiting correctly, the is_bad() function shouldn't be 836 866 # evaluated, and the deliberate sleep won't happen. 837 'if-tag-shortcircuit01': ('{% if x.is_true or x.is_bad %}yes{% else %}no{% endif %}', {'x': TestObj()}, "yes"),838 'if-tag-shortcircuit02': ('{% if x.is_false and x.is_bad %}yes{% else %}no{% endif %}', {'x': TestObj()}, "no"),867 'if-tag-shortcircuit01': testcase('{% if x.is_true or x.is_bad %}yes{% else %}no{% endif %}', {'x': TestObj()}, "yes"), 868 'if-tag-shortcircuit02': testcase('{% if x.is_false and x.is_bad %}yes{% else %}no{% endif %}', {'x': TestObj()}, "no"), 839 869 840 870 # Non-existent args 841 'if-tag-badarg01': ("{% if x|default_if_none:y %}yes{% endif %}", {}, ''),842 'if-tag-badarg02': ("{% if x|default_if_none:y %}yes{% endif %}", {'y': 0}, ''),843 'if-tag-badarg03': ("{% if x|default_if_none:y %}yes{% endif %}", {'y': 1}, 'yes'),844 'if-tag-badarg04': ("{% if x|default_if_none:y %}yes{% else %}no{% endif %}", {}, 'no'),871 'if-tag-badarg01': testcase("{% if x|default_if_none:y %}yes{% endif %}", {}, ''), 872 'if-tag-badarg02': testcase("{% if x|default_if_none:y %}yes{% endif %}", {'y': 0}, ''), 873 'if-tag-badarg03': testcase("{% if x|default_if_none:y %}yes{% endif %}", {'y': 1}, 'yes'), 874 'if-tag-badarg04': testcase("{% if x|default_if_none:y %}yes{% else %}no{% endif %}", {}, 'no'), 845 875 846 876 # Additional, more precise parsing tests are in SmartIfTests 847 877 848 878 ### IFCHANGED TAG ######################################################### 849 'ifchanged01': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', {'num': (1,2,3)}, '123'),850 'ifchanged02': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', {'num': (1,1,3)}, '13'),851 'ifchanged03': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', {'num': (1,1,1)}, '1'),852 'ifchanged04': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', {'num': (1, 2, 3), 'numx': (2, 2, 2)}, '122232'),853 'ifchanged05': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', {'num': (1, 1, 1), 'numx': (1, 2, 3)}, '1123123123'),854 'ifchanged06': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', {'num': (1, 1, 1), 'numx': (2, 2, 2)}, '1222'),855 'ifchanged07': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% for y in numy %}{% ifchanged %}{{ y }}{% endifchanged %}{% endfor %}{% endfor %}{% endfor %}', {'num': (1, 1, 1), 'numx': (2, 2, 2), 'numy': (3, 3, 3)}, '1233323332333'),856 'ifchanged08': ('{% for data in datalist %}{% for c,d in data %}{% if c %}{% ifchanged %}{{ d }}{% endifchanged %}{% endif %}{% endfor %}{% endfor %}', {'datalist': [[(1, 'a'), (1, 'a'), (0, 'b'), (1, 'c')], [(0, 'a'), (1, 'c'), (1, 'd'), (1, 'd'), (0, 'e')]]}, 'accd'),879 'ifchanged01': testcase('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', {'num': (1,2,3)}, '123'), 880 'ifchanged02': testcase('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', {'num': (1,1,3)}, '13'), 881 'ifchanged03': testcase('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', {'num': (1,1,1)}, '1'), 882 'ifchanged04': testcase('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', {'num': (1, 2, 3), 'numx': (2, 2, 2)}, '122232'), 883 'ifchanged05': testcase('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', {'num': (1, 1, 1), 'numx': (1, 2, 3)}, '1123123123'), 884 'ifchanged06': testcase('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', {'num': (1, 1, 1), 'numx': (2, 2, 2)}, '1222'), 885 'ifchanged07': testcase('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% for y in numy %}{% ifchanged %}{{ y }}{% endifchanged %}{% endfor %}{% endfor %}{% endfor %}', {'num': (1, 1, 1), 'numx': (2, 2, 2), 'numy': (3, 3, 3)}, '1233323332333'), 886 'ifchanged08': testcase('{% for data in datalist %}{% for c,d in data %}{% if c %}{% ifchanged %}{{ d }}{% endifchanged %}{% endif %}{% endfor %}{% endfor %}', {'datalist': [[(1, 'a'), (1, 'a'), (0, 'b'), (1, 'c')], [(0, 'a'), (1, 'c'), (1, 'd'), (1, 'd'), (0, 'e')]]}, 'accd'), 857 887 858 888 # Test one parameter given to ifchanged. 859 'ifchanged-param01': ('{% for n in num %}{% ifchanged n %}..{% endifchanged %}{{ n }}{% endfor %}', { 'num': (1,2,3) }, '..1..2..3'),860 'ifchanged-param02': ('{% for n in num %}{% for x in numx %}{% ifchanged n %}..{% endifchanged %}{{ x }}{% endfor %}{% endfor %}', { 'num': (1,2,3), 'numx': (5,6,7) }, '..567..567..567'),889 'ifchanged-param01': testcase('{% for n in num %}{% ifchanged n %}..{% endifchanged %}{{ n }}{% endfor %}', { 'num': (1,2,3) }, '..1..2..3'), 890 'ifchanged-param02': testcase('{% for n in num %}{% for x in numx %}{% ifchanged n %}..{% endifchanged %}{{ x }}{% endfor %}{% endfor %}', { 'num': (1,2,3), 'numx': (5,6,7) }, '..567..567..567'), 861 891 862 892 # Test multiple parameters to ifchanged. 863 'ifchanged-param03': ('{% for n in num %}{{ n }}{% for x in numx %}{% ifchanged x n %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', { 'num': (1,1,2), 'numx': (5,6,6) }, '156156256'),893 'ifchanged-param03': testcase('{% for n in num %}{{ n }}{% for x in numx %}{% ifchanged x n %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', { 'num': (1,1,2), 'numx': (5,6,6) }, '156156256'), 864 894 865 895 # Test a date+hour like construct, where the hour of the last day 866 896 # is the same but the date had changed, so print the hour anyway. 867 'ifchanged-param04': ('{% for d in days %}{% ifchanged %}{{ d.day }}{% endifchanged %}{% for h in d.hours %}{% ifchanged d h %}{{ h }}{% endifchanged %}{% endfor %}{% endfor %}', {'days':[{'day':1, 'hours':[1,2,3]},{'day':2, 'hours':[3]},] }, '112323'),897 'ifchanged-param04': testcase('{% for d in days %}{% ifchanged %}{{ d.day }}{% endifchanged %}{% for h in d.hours %}{% ifchanged d h %}{{ h }}{% endifchanged %}{% endfor %}{% endfor %}', {'days':[{'day':1, 'hours':[1,2,3]},{'day':2, 'hours':[3]},] }, '112323'), 868 898 869 899 # Logically the same as above, just written with explicit 870 900 # ifchanged for the day. 871 'ifchanged-param05': ('{% for d in days %}{% ifchanged d.day %}{{ d.day }}{% endifchanged %}{% for h in d.hours %}{% ifchanged d.day h %}{{ h }}{% endifchanged %}{% endfor %}{% endfor %}', {'days':[{'day':1, 'hours':[1,2,3]},{'day':2, 'hours':[3]},] }, '112323'),901 'ifchanged-param05': testcase('{% for d in days %}{% ifchanged d.day %}{{ d.day }}{% endifchanged %}{% for h in d.hours %}{% ifchanged d.day h %}{{ h }}{% endifchanged %}{% endfor %}{% endfor %}', {'days':[{'day':1, 'hours':[1,2,3]},{'day':2, 'hours':[3]},] }, '112323'), 872 902 873 903 # Test the else clause of ifchanged. 874 'ifchanged-else01': ('{% for id in ids %}{{ id }}{% ifchanged id %}-first{% else %}-other{% endifchanged %},{% endfor %}', {'ids': [1,1,2,2,2,3]}, '1-first,1-other,2-first,2-other,2-other,3-first,'),904 'ifchanged-else01': testcase('{% for id in ids %}{{ id }}{% ifchanged id %}-first{% else %}-other{% endifchanged %},{% endfor %}', {'ids': [1,1,2,2,2,3]}, '1-first,1-other,2-first,2-other,2-other,3-first,'), 875 905 876 'ifchanged-else02': ('{% for id in ids %}{{ id }}-{% ifchanged id %}{% cycle red,blue %}{% else %}grey{% endifchanged %},{% endfor %}', {'ids': [1,1,2,2,2,3]}, '1-red,1-grey,2-blue,2-grey,2-grey,3-red,'),877 'ifchanged-else03': ('{% for id in ids %}{{ id }}{% ifchanged id %}-{% cycle red,blue %}{% else %}{% endifchanged %},{% endfor %}', {'ids': [1,1,2,2,2,3]}, '1-red,1,2-blue,2,2,3-red,'),906 'ifchanged-else02': testcase('{% for id in ids %}{{ id }}-{% ifchanged id %}{% cycle red,blue %}{% else %}grey{% endifchanged %},{% endfor %}', {'ids': [1,1,2,2,2,3]}, '1-red,1-grey,2-blue,2-grey,2-grey,3-red,'), 907 'ifchanged-else03': testcase('{% for id in ids %}{{ id }}{% ifchanged id %}-{% cycle red,blue %}{% else %}{% endifchanged %},{% endfor %}', {'ids': [1,1,2,2,2,3]}, '1-red,1,2-blue,2,2,3-red,'), 878 908 879 'ifchanged-else04': ('{% for id in ids %}{% ifchanged %}***{{ id }}*{% else %}...{% endifchanged %}{{ forloop.counter }}{% endfor %}', {'ids': [1,1,2,2,2,3,4]}, '***1*1...2***2*3...4...5***3*6***4*7'),909 'ifchanged-else04': testcase('{% for id in ids %}{% ifchanged %}***{{ id }}*{% else %}...{% endifchanged %}{{ forloop.counter }}{% endfor %}', {'ids': [1,1,2,2,2,3,4]}, '***1*1...2***2*3...4...5***3*6***4*7'), 880 910 881 911 ### IFEQUAL TAG ########################################################### 882 'ifequal01': ("{% ifequal a b %}yes{% endifequal %}", {"a": 1, "b": 2}, ""),883 'ifequal02': ("{% ifequal a b %}yes{% endifequal %}", {"a": 1, "b": 1}, "yes"),884 'ifequal03': ("{% ifequal a b %}yes{% else %}no{% endifequal %}", {"a": 1, "b": 2}, "no"),885 'ifequal04': ("{% ifequal a b %}yes{% else %}no{% endifequal %}", {"a": 1, "b": 1}, "yes"),886 'ifequal05': ("{% ifequal a 'test' %}yes{% else %}no{% endifequal %}", {"a": "test"}, "yes"),887 'ifequal06': ("{% ifequal a 'test' %}yes{% else %}no{% endifequal %}", {"a": "no"}, "no"),888 'ifequal07': ('{% ifequal a "test" %}yes{% else %}no{% endifequal %}', {"a": "test"}, "yes"),889 'ifequal08': ('{% ifequal a "test" %}yes{% else %}no{% endifequal %}', {"a": "no"}, "no"),890 'ifequal09': ('{% ifequal a "test" %}yes{% else %}no{% endifequal %}', {}, "no"),891 'ifequal10': ('{% ifequal a b %}yes{% else %}no{% endifequal %}', {}, "yes"),912 'ifequal01': testcase("{% ifequal a b %}yes{% endifequal %}", {"a": 1, "b": 2}, ""), 913 'ifequal02': testcase("{% ifequal a b %}yes{% endifequal %}", {"a": 1, "b": 1}, "yes"), 914 'ifequal03': testcase("{% ifequal a b %}yes{% else %}no{% endifequal %}", {"a": 1, "b": 2}, "no"), 915 'ifequal04': testcase("{% ifequal a b %}yes{% else %}no{% endifequal %}", {"a": 1, "b": 1}, "yes"), 916 'ifequal05': testcase("{% ifequal a 'test' %}yes{% else %}no{% endifequal %}", {"a": "test"}, "yes"), 917 'ifequal06': testcase("{% ifequal a 'test' %}yes{% else %}no{% endifequal %}", {"a": "no"}, "no"), 918 'ifequal07': testcase('{% ifequal a "test" %}yes{% else %}no{% endifequal %}', {"a": "test"}, "yes"), 919 'ifequal08': testcase('{% ifequal a "test" %}yes{% else %}no{% endifequal %}', {"a": "no"}, "no"), 920 'ifequal09': testcase('{% ifequal a "test" %}yes{% else %}no{% endifequal %}', {}, "no"), 921 'ifequal10': testcase('{% ifequal a b %}yes{% else %}no{% endifequal %}', {}, "yes"), 892 922 893 923 # SMART SPLITTING 894 'ifequal-split01': ('{% ifequal a "test man" %}yes{% else %}no{% endifequal %}', {}, "no"),895 'ifequal-split02': ('{% ifequal a "test man" %}yes{% else %}no{% endifequal %}', {'a': 'foo'}, "no"),896 'ifequal-split03': ('{% ifequal a "test man" %}yes{% else %}no{% endifequal %}', {'a': 'test man'}, "yes"),897 'ifequal-split04': ("{% ifequal a 'test man' %}yes{% else %}no{% endifequal %}", {'a': 'test man'}, "yes"),898 'ifequal-split05': ("{% ifequal a 'i \"love\" you' %}yes{% else %}no{% endifequal %}", {'a': ''}, "no"),899 'ifequal-split06': ("{% ifequal a 'i \"love\" you' %}yes{% else %}no{% endifequal %}", {'a': 'i "love" you'}, "yes"),900 'ifequal-split07': ("{% ifequal a 'i \"love\" you' %}yes{% else %}no{% endifequal %}", {'a': 'i love you'}, "no"),901 'ifequal-split08': (r"{% ifequal a 'I\'m happy' %}yes{% else %}no{% endifequal %}", {'a': "I'm happy"}, "yes"),902 'ifequal-split09': (r"{% ifequal a 'slash\man' %}yes{% else %}no{% endifequal %}", {'a': r"slash\man"}, "yes"),903 'ifequal-split10': (r"{% ifequal a 'slash\man' %}yes{% else %}no{% endifequal %}", {'a': r"slashman"}, "no"),924 'ifequal-split01': testcase('{% ifequal a "test man" %}yes{% else %}no{% endifequal %}', {}, "no"), 925 'ifequal-split02': testcase('{% ifequal a "test man" %}yes{% else %}no{% endifequal %}', {'a': 'foo'}, "no"), 926 'ifequal-split03': testcase('{% ifequal a "test man" %}yes{% else %}no{% endifequal %}', {'a': 'test man'}, "yes"), 927 'ifequal-split04': testcase("{% ifequal a 'test man' %}yes{% else %}no{% endifequal %}", {'a': 'test man'}, "yes"), 928 'ifequal-split05': testcase("{% ifequal a 'i \"love\" you' %}yes{% else %}no{% endifequal %}", {'a': ''}, "no"), 929 'ifequal-split06': testcase("{% ifequal a 'i \"love\" you' %}yes{% else %}no{% endifequal %}", {'a': 'i "love" you'}, "yes"), 930 'ifequal-split07': testcase("{% ifequal a 'i \"love\" you' %}yes{% else %}no{% endifequal %}", {'a': 'i love you'}, "no"), 931 'ifequal-split08': testcase(r"{% ifequal a 'I\'m happy' %}yes{% else %}no{% endifequal %}", {'a': "I'm happy"}, "yes"), 932 'ifequal-split09': testcase(r"{% ifequal a 'slash\man' %}yes{% else %}no{% endifequal %}", {'a': r"slash\man"}, "yes"), 933 'ifequal-split10': testcase(r"{% ifequal a 'slash\man' %}yes{% else %}no{% endifequal %}", {'a': r"slashman"}, "no"), 904 934 905 935 # NUMERIC RESOLUTION 906 'ifequal-numeric01': ('{% ifequal x 5 %}yes{% endifequal %}', {'x': '5'}, ''),907 'ifequal-numeric02': ('{% ifequal x 5 %}yes{% endifequal %}', {'x': 5}, 'yes'),908 'ifequal-numeric03': ('{% ifequal x 5.2 %}yes{% endifequal %}', {'x': 5}, ''),909 'ifequal-numeric04': ('{% ifequal x 5.2 %}yes{% endifequal %}', {'x': 5.2}, 'yes'),910 'ifequal-numeric05': ('{% ifequal x 0.2 %}yes{% endifequal %}', {'x': .2}, 'yes'),911 'ifequal-numeric06': ('{% ifequal x .2 %}yes{% endifequal %}', {'x': .2}, 'yes'),912 'ifequal-numeric07': ('{% ifequal x 2. %}yes{% endifequal %}', {'x': 2}, ''),913 'ifequal-numeric08': ('{% ifequal x "5" %}yes{% endifequal %}', {'x': 5}, ''),914 'ifequal-numeric09': ('{% ifequal x "5" %}yes{% endifequal %}', {'x': '5'}, 'yes'),915 'ifequal-numeric10': ('{% ifequal x -5 %}yes{% endifequal %}', {'x': -5}, 'yes'),916 'ifequal-numeric11': ('{% ifequal x -5.2 %}yes{% endifequal %}', {'x': -5.2}, 'yes'),917 'ifequal-numeric12': ('{% ifequal x +5 %}yes{% endifequal %}', {'x': 5}, 'yes'),936 'ifequal-numeric01': testcase('{% ifequal x 5 %}yes{% endifequal %}', {'x': '5'}, ''), 937 'ifequal-numeric02': testcase('{% ifequal x 5 %}yes{% endifequal %}', {'x': 5}, 'yes'), 938 'ifequal-numeric03': testcase('{% ifequal x 5.2 %}yes{% endifequal %}', {'x': 5}, ''), 939 'ifequal-numeric04': testcase('{% ifequal x 5.2 %}yes{% endifequal %}', {'x': 5.2}, 'yes'), 940 'ifequal-numeric05': testcase('{% ifequal x 0.2 %}yes{% endifequal %}', {'x': .2}, 'yes'), 941 'ifequal-numeric06': testcase('{% ifequal x .2 %}yes{% endifequal %}', {'x': .2}, 'yes'), 942 'ifequal-numeric07': testcase('{% ifequal x 2. %}yes{% endifequal %}', {'x': 2}, ''), 943 'ifequal-numeric08': testcase('{% ifequal x "5" %}yes{% endifequal %}', {'x': 5}, ''), 944 'ifequal-numeric09': testcase('{% ifequal x "5" %}yes{% endifequal %}', {'x': '5'}, 'yes'), 945 'ifequal-numeric10': testcase('{% ifequal x -5 %}yes{% endifequal %}', {'x': -5}, 'yes'), 946 'ifequal-numeric11': testcase('{% ifequal x -5.2 %}yes{% endifequal %}', {'x': -5.2}, 'yes'), 947 'ifequal-numeric12': testcase('{% ifequal x +5 %}yes{% endifequal %}', {'x': 5}, 'yes'), 918 948 919 949 # FILTER EXPRESSIONS AS ARGUMENTS 920 'ifequal-filter01': ('{% ifequal a|upper "A" %}x{% endifequal %}', {'a': 'a'}, 'x'),921 'ifequal-filter02': ('{% ifequal "A" a|upper %}x{% endifequal %}', {'a': 'a'}, 'x'),922 'ifequal-filter03': ('{% ifequal a|upper b|upper %}x{% endifequal %}', {'a': 'x', 'b': 'X'}, 'x'),923 'ifequal-filter04': ('{% ifequal x|slice:"1" "a" %}x{% endifequal %}', {'x': 'aaa'}, 'x'),924 'ifequal-filter05': ('{% ifequal x|slice:"1"|upper "A" %}x{% endifequal %}', {'x': 'aaa'}, 'x'),950 'ifequal-filter01': testcase('{% ifequal a|upper "A" %}x{% endifequal %}', {'a': 'a'}, 'x'), 951 'ifequal-filter02': testcase('{% ifequal "A" a|upper %}x{% endifequal %}', {'a': 'a'}, 'x'), 952 'ifequal-filter03': testcase('{% ifequal a|upper b|upper %}x{% endifequal %}', {'a': 'x', 'b': 'X'}, 'x'), 953 'ifequal-filter04': testcase('{% ifequal x|slice:"1" "a" %}x{% endifequal %}', {'x': 'aaa'}, 'x'), 954 'ifequal-filter05': testcase('{% ifequal x|slice:"1"|upper "A" %}x{% endifequal %}', {'x': 'aaa'}, 'x'), 925 955 926 956 ### IFNOTEQUAL TAG ######################################################## 927 'ifnotequal01': ("{% ifnotequal a b %}yes{% endifnotequal %}", {"a": 1, "b": 2}, "yes"),928 'ifnotequal02': ("{% ifnotequal a b %}yes{% endifnotequal %}", {"a": 1, "b": 1}, ""),929 'ifnotequal03': ("{% ifnotequal a b %}yes{% else %}no{% endifnotequal %}", {"a": 1, "b": 2}, "yes"),930 'ifnotequal04': ("{% ifnotequal a b %}yes{% else %}no{% endifnotequal %}", {"a": 1, "b": 1}, "no"),957 'ifnotequal01': testcase("{% ifnotequal a b %}yes{% endifnotequal %}", {"a": 1, "b": 2}, "yes"), 958 'ifnotequal02': testcase("{% ifnotequal a b %}yes{% endifnotequal %}", {"a": 1, "b": 1}, ""), 959 'ifnotequal03': testcase("{% ifnotequal a b %}yes{% else %}no{% endifnotequal %}", {"a": 1, "b": 2}, "yes"), 960 'ifnotequal04': testcase("{% ifnotequal a b %}yes{% else %}no{% endifnotequal %}", {"a": 1, "b": 1}, "no"), 931 961 932 962 ### INCLUDE TAG ########################################################### 933 'include01': ('{% include "basic-syntax01" %}', {}, "something cool"), 934 'include02': ('{% include "basic-syntax02" %}', {'headline': 'Included'}, "Included"), 935 'include03': ('{% include template_name %}', {'template_name': 'basic-syntax02', 'headline': 'Included'}, "Included"), 936 'include04': ('a{% include "nonexistent" %}b', {}, "ab"), 937 'include 05': ('template with a space', {}, 'template with a space'), 938 'include06': ('{% include "include 05"%}', {}, 'template with a space'), 963 'include01': testcase('{% include "basic-syntax01" %}', {}, "something cool"), 964 'include02': testcase('{% include "basic-syntax02" %}', {'headline': 'Included'}, "Included"), 965 'include03': testcase('{% include template_name %}', {'template_name': 'basic-syntax02', 'headline': 'Included'}, "Included"), 966 'include04': testcase('a{% include "nonexistent" %}b', {}, 967 lambda tdebug, invalid_str: tdebug and template.TemplateDoesNotExist or 'ab'), 968 'include 05': testcase('template with a space', {}, 'template with a space'), 969 'include06': testcase('{% include "include 05"%}', {}, 'template with a space'), 939 970 971 ### INCLUSION ERROR REPORTING ############################################# 972 'include-fail': testcase('{% load broken_tag %}', {}, template.TemplateSyntaxError), 973 'include-error': testcase('{% include failed_include %}', {'failed_include': 'include-fail'}, 974 lambda tdebug, invalid_str: tdebug and template.TemplateSyntaxError or ''), 940 975 ### NAMED ENDBLOCKS ####################################################### 941 976 942 977 # Basic test 943 'namedendblocks01': ("1{% block first %}_{% block second %}2{% endblock second %}_{% endblock first %}3", {}, '1_2_3'),978 'namedendblocks01': testcase("1{% block first %}_{% block second %}2{% endblock second %}_{% endblock first %}3", {}, '1_2_3'), 944 979 945 980 # Unbalanced blocks 946 'namedendblocks02': ("1{% block first %}_{% block second %}2{% endblock first %}_{% endblock second %}3", {}, template.TemplateSyntaxError),947 'namedendblocks03': ("1{% block first %}_{% block second %}2{% endblock %}_{% endblock second %}3", {}, template.TemplateSyntaxError),948 'namedendblocks04': ("1{% block first %}_{% block second %}2{% endblock second %}_{% endblock third %}3", {}, template.TemplateSyntaxError),949 'namedendblocks05': ("1{% block first %}_{% block second %}2{% endblock first %}", {}, template.TemplateSyntaxError),981 'namedendblocks02': testcase("1{% block first %}_{% block second %}2{% endblock first %}_{% endblock second %}3", {}, template.TemplateSyntaxError), 982 'namedendblocks03': testcase("1{% block first %}_{% block second %}2{% endblock %}_{% endblock second %}3", {}, template.TemplateSyntaxError), 983 'namedendblocks04': testcase("1{% block first %}_{% block second %}2{% endblock second %}_{% endblock third %}3", {}, template.TemplateSyntaxError), 984 'namedendblocks05': testcase("1{% block first %}_{% block second %}2{% endblock first %}", {}, template.TemplateSyntaxError), 950 985 951 986 # Mixed named and unnamed endblocks 952 'namedendblocks06': ("1{% block first %}_{% block second %}2{% endblock %}_{% endblock first %}3", {}, '1_2_3'),953 'namedendblocks07': ("1{% block first %}_{% block second %}2{% endblock second %}_{% endblock %}3", {}, '1_2_3'),987 'namedendblocks06': testcase("1{% block first %}_{% block second %}2{% endblock %}_{% endblock first %}3", {}, '1_2_3'), 988 'namedendblocks07': testcase("1{% block first %}_{% block second %}2{% endblock second %}_{% endblock %}3", {}, '1_2_3'), 954 989 955 990 ### INHERITANCE ########################################################### 956 991 957 992 # Standard template with no inheritance 958 'inheritance01': ("1{% block first %}&{% endblock %}3{% block second %}_{% endblock %}", {}, '1&3_'),993 'inheritance01': testcase("1{% block first %}&{% endblock %}3{% block second %}_{% endblock %}", {}, '1&3_'), 959 994 960 995 # Standard two-level inheritance 961 'inheritance02': ("{% extends 'inheritance01' %}{% block first %}2{% endblock %}{% block second %}4{% endblock %}", {}, '1234'),996 'inheritance02': testcase("{% extends 'inheritance01' %}{% block first %}2{% endblock %}{% block second %}4{% endblock %}", {}, '1234'), 962 997 963 998 # Three-level with no redefinitions on third level 964 'inheritance03': ("{% extends 'inheritance02' %}", {}, '1234'),999 'inheritance03': testcase("{% extends 'inheritance02' %}", {}, '1234'), 965 1000 966 1001 # Two-level with no redefinitions on second level 967 'inheritance04': ("{% extends 'inheritance01' %}", {}, '1&3_'),1002 'inheritance04': testcase("{% extends 'inheritance01' %}", {}, '1&3_'), 968 1003 969 1004 # Two-level with double quotes instead of single quotes 970 'inheritance05': ('{% extends "inheritance02" %}', {}, '1234'),1005 'inheritance05': testcase('{% extends "inheritance02" %}', {}, '1234'), 971 1006 972 1007 # Three-level with variable parent-template name 973 'inheritance06': ("{% extends foo %}", {'foo': 'inheritance02'}, '1234'),1008 'inheritance06': testcase("{% extends foo %}", {'foo': 'inheritance02'}, '1234'), 974 1009 975 1010 # Two-level with one block defined, one block not defined 976 'inheritance07': ("{% extends 'inheritance01' %}{% block second %}5{% endblock %}", {}, '1&35'),1011 'inheritance07': testcase("{% extends 'inheritance01' %}{% block second %}5{% endblock %}", {}, '1&35'), 977 1012 978 1013 # Three-level with one block defined on this level, two blocks defined next level 979 'inheritance08': ("{% extends 'inheritance02' %}{% block second %}5{% endblock %}", {}, '1235'),1014 'inheritance08': testcase("{% extends 'inheritance02' %}{% block second %}5{% endblock %}", {}, '1235'), 980 1015 981 1016 # Three-level with second and third levels blank 982 'inheritance09': ("{% extends 'inheritance04' %}", {}, '1&3_'),1017 'inheritance09': testcase("{% extends 'inheritance04' %}", {}, '1&3_'), 983 1018 984 1019 # Three-level with space NOT in a block -- should be ignored 985 'inheritance10': ("{% extends 'inheritance04' %} ", {}, '1&3_'),1020 'inheritance10': testcase("{% extends 'inheritance04' %} ", {}, '1&3_'), 986 1021 987 1022 # Three-level with both blocks defined on this level, but none on second level 988 'inheritance11': ("{% extends 'inheritance04' %}{% block first %}2{% endblock %}{% block second %}4{% endblock %}", {}, '1234'),1023 'inheritance11': testcase("{% extends 'inheritance04' %}{% block first %}2{% endblock %}{% block second %}4{% endblock %}", {}, '1234'), 989 1024 990 1025 # Three-level with this level providing one and second level providing the other 991 'inheritance12': ("{% extends 'inheritance07' %}{% block first %}2{% endblock %}", {}, '1235'),1026 'inheritance12': testcase("{% extends 'inheritance07' %}{% block first %}2{% endblock %}", {}, '1235'), 992 1027 993 1028 # Three-level with this level overriding second level 994 'inheritance13': ("{% extends 'inheritance02' %}{% block first %}a{% endblock %}{% block second %}b{% endblock %}", {}, '1a3b'),1029 'inheritance13': testcase("{% extends 'inheritance02' %}{% block first %}a{% endblock %}{% block second %}b{% endblock %}", {}, '1a3b'), 995 1030 996 1031 # A block defined only in a child template shouldn't be displayed 997 'inheritance14': ("{% extends 'inheritance01' %}{% block newblock %}NO DISPLAY{% endblock %}", {}, '1&3_'),1032 'inheritance14': testcase("{% extends 'inheritance01' %}{% block newblock %}NO DISPLAY{% endblock %}", {}, '1&3_'), 998 1033 999 1034 # A block within another block 1000 'inheritance15': ("{% extends 'inheritance01' %}{% block first %}2{% block inner %}inner{% endblock %}{% endblock %}", {}, '12inner3_'),1035 'inheritance15': testcase("{% extends 'inheritance01' %}{% block first %}2{% block inner %}inner{% endblock %}{% endblock %}", {}, '12inner3_'), 1001 1036 1002 1037 # A block within another block (level 2) 1003 'inheritance16': ("{% extends 'inheritance15' %}{% block inner %}out{% endblock %}", {}, '12out3_'),1038 'inheritance16': testcase("{% extends 'inheritance15' %}{% block inner %}out{% endblock %}", {}, '12out3_'), 1004 1039 1005 1040 # {% load %} tag (parent -- setup for exception04) 1006 'inheritance17': ("{% load testtags %}{% block first %}1234{% endblock %}", {}, '1234'),1041 'inheritance17': testcase("{% load testtags %}{% block first %}1234{% endblock %}", {}, '1234'), 1007 1042 1008 1043 # {% load %} tag (standard usage, without inheritance) 1009 'inheritance18': ("{% load testtags %}{% echo this that theother %}5678", {}, 'this that theother5678'),1044 'inheritance18': testcase("{% load testtags %}{% echo this that theother %}5678", {}, 'this that theother5678'), 1010 1045 1011 1046 # {% load %} tag (within a child template) 1012 'inheritance19': ("{% extends 'inheritance01' %}{% block first %}{% load testtags %}{% echo 400 %}5678{% endblock %}", {}, '140056783_'),1047 'inheritance19': testcase("{% extends 'inheritance01' %}{% block first %}{% load testtags %}{% echo 400 %}5678{% endblock %}", {}, '140056783_'), 1013 1048 1014 1049 # Two-level inheritance with {{ block.super }} 1015 'inheritance20': ("{% extends 'inheritance01' %}{% block first %}{{ block.super }}a{% endblock %}", {}, '1&a3_'),1050 'inheritance20': testcase("{% extends 'inheritance01' %}{% block first %}{{ block.super }}a{% endblock %}", {}, '1&a3_'), 1016 1051 1017 1052 # Three-level inheritance with {{ block.super }} from parent 1018 'inheritance21': ("{% extends 'inheritance02' %}{% block first %}{{ block.super }}a{% endblock %}", {}, '12a34'),1053 'inheritance21': testcase("{% extends 'inheritance02' %}{% block first %}{{ block.super }}a{% endblock %}", {}, '12a34'), 1019 1054 1020 1055 # Three-level inheritance with {{ block.super }} from grandparent 1021 'inheritance22': ("{% extends 'inheritance04' %}{% block first %}{{ block.super }}a{% endblock %}", {}, '1&a3_'),1056 'inheritance22': testcase("{% extends 'inheritance04' %}{% block first %}{{ block.super }}a{% endblock %}", {}, '1&a3_'), 1022 1057 1023 1058 # Three-level inheritance with {{ block.super }} from parent and grandparent 1024 'inheritance23': ("{% extends 'inheritance20' %}{% block first %}{{ block.super }}b{% endblock %}", {}, '1&ab3_'),1059 'inheritance23': testcase("{% extends 'inheritance20' %}{% block first %}{{ block.super }}b{% endblock %}", {}, '1&ab3_'), 1025 1060 1026 1061 # Inheritance from local context without use of template loader 1027 'inheritance24': ("{% extends context_template %}{% block first %}2{% endblock %}{% block second %}4{% endblock %}", {'context_template': template.Template("1{% block first %}_{% endblock %}3{% block second %}_{% endblock %}")}, '1234'),1062 'inheritance24': testcase("{% extends context_template %}{% block first %}2{% endblock %}{% block second %}4{% endblock %}", {'context_template': template.Template("1{% block first %}_{% endblock %}3{% block second %}_{% endblock %}")}, '1234'), 1028 1063 1029 1064 # Inheritance from local context with variable parent template 1030 'inheritance25': ("{% extends context_template.1 %}{% block first %}2{% endblock %}{% block second %}4{% endblock %}", {'context_template': [template.Template("Wrong"), template.Template("1{% block first %}_{% endblock %}3{% block second %}_{% endblock %}")]}, '1234'),1065 'inheritance25': testcase("{% extends context_template.1 %}{% block first %}2{% endblock %}{% block second %}4{% endblock %}", {'context_template': [template.Template("Wrong"), template.Template("1{% block first %}_{% endblock %}3{% block second %}_{% endblock %}")]}, '1234'), 1031 1066 1032 1067 # Set up a base template to extend 1033 'inheritance26': ("no tags", {}, 'no tags'),1068 'inheritance26': testcase("no tags", {}, 'no tags'), 1034 1069 1035 1070 # Inheritance from a template that doesn't have any blocks 1036 'inheritance27': ("{% extends 'inheritance26' %}", {}, 'no tags'),1071 'inheritance27': testcase("{% extends 'inheritance26' %}", {}, 'no tags'), 1037 1072 1038 1073 # Set up a base template with a space in it. 1039 'inheritance 28': ("{% block first %}!{% endblock %}", {}, '!'),1074 'inheritance 28': testcase("{% block first %}!{% endblock %}", {}, '!'), 1040 1075 1041 1076 # Inheritance from a template with a space in its name should work. 1042 'inheritance29': ("{% extends 'inheritance 28' %}", {}, '!'),1077 'inheritance29': testcase("{% extends 'inheritance 28' %}", {}, '!'), 1043 1078 1044 1079 # Base template, putting block in a conditional {% if %} tag 1045 'inheritance30': ("1{% if optional %}{% block opt %}2{% endblock %}{% endif %}3", {'optional': True}, '123'),1080 'inheritance30': testcase("1{% if optional %}{% block opt %}2{% endblock %}{% endif %}3", {'optional': True}, '123'), 1046 1081 1047 1082 # Inherit from a template with block wrapped in an {% if %} tag (in parent), still gets overridden 1048 'inheritance31': ("{% extends 'inheritance30' %}{% block opt %}two{% endblock %}", {'optional': True}, '1two3'),1049 'inheritance32': ("{% extends 'inheritance30' %}{% block opt %}two{% endblock %}", {}, '13'),1083 'inheritance31': testcase("{% extends 'inheritance30' %}{% block opt %}two{% endblock %}", {'optional': True}, '1two3'), 1084 'inheritance32': testcase("{% extends 'inheritance30' %}{% block opt %}two{% endblock %}", {}, '13'), 1050 1085 1051 1086 # Base template, putting block in a conditional {% ifequal %} tag 1052 'inheritance33': ("1{% ifequal optional 1 %}{% block opt %}2{% endblock %}{% endifequal %}3", {'optional': 1}, '123'),1087 'inheritance33': testcase("1{% ifequal optional 1 %}{% block opt %}2{% endblock %}{% endifequal %}3", {'optional': 1}, '123'), 1053 1088 1054 1089 # Inherit from a template with block wrapped in an {% ifequal %} tag (in parent), still gets overridden 1055 'inheritance34': ("{% extends 'inheritance33' %}{% block opt %}two{% endblock %}", {'optional': 1}, '1two3'),1056 'inheritance35': ("{% extends 'inheritance33' %}{% block opt %}two{% endblock %}", {'optional': 2}, '13'),1090 'inheritance34': testcase("{% extends 'inheritance33' %}{% block opt %}two{% endblock %}", {'optional': 1}, '1two3'), 1091 'inheritance35': testcase("{% extends 'inheritance33' %}{% block opt %}two{% endblock %}", {'optional': 2}, '13'), 1057 1092 1058 1093 # Base template, putting block in a {% for %} tag 1059 'inheritance36': ("{% for n in numbers %}_{% block opt %}{{ n }}{% endblock %}{% endfor %}_", {'numbers': '123'}, '_1_2_3_'),1094 'inheritance36': testcase("{% for n in numbers %}_{% block opt %}{{ n }}{% endblock %}{% endfor %}_", {'numbers': '123'}, '_1_2_3_'), 1060 1095 1061 1096 # Inherit from a template with block wrapped in an {% for %} tag (in parent), still gets overridden 1062 'inheritance37': ("{% extends 'inheritance36' %}{% block opt %}X{% endblock %}", {'numbers': '123'}, '_X_X_X_'),1063 'inheritance38': ("{% extends 'inheritance36' %}{% block opt %}X{% endblock %}", {}, '_'),1097 'inheritance37': testcase("{% extends 'inheritance36' %}{% block opt %}X{% endblock %}", {'numbers': '123'}, '_X_X_X_'), 1098 'inheritance38': testcase("{% extends 'inheritance36' %}{% block opt %}X{% endblock %}", {}, '_'), 1064 1099 1065 1100 # The super block will still be found. 1066 'inheritance39': ("{% extends 'inheritance30' %}{% block opt %}new{{ block.super }}{% endblock %}", {'optional': True}, '1new23'),1067 'inheritance40': ("{% extends 'inheritance33' %}{% block opt %}new{{ block.super }}{% endblock %}", {'optional': 1}, '1new23'),1068 'inheritance41': ("{% extends 'inheritance36' %}{% block opt %}new{{ block.super }}{% endblock %}", {'numbers': '123'}, '_new1_new2_new3_'),1101 'inheritance39': testcase("{% extends 'inheritance30' %}{% block opt %}new{{ block.super }}{% endblock %}", {'optional': True}, '1new23'), 1102 'inheritance40': testcase("{% extends 'inheritance33' %}{% block opt %}new{{ block.super }}{% endblock %}", {'optional': 1}, '1new23'), 1103 'inheritance41': testcase("{% extends 'inheritance36' %}{% block opt %}new{{ block.super }}{% endblock %}", {'numbers': '123'}, '_new1_new2_new3_'), 1069 1104 1070 1105 ### LOADING TAG LIBRARIES ################################################# 1071 1106 1072 1107 # {% load %} tag, importing individual tags 1073 'load1': ("{% load echo from testtags %}{% echo this that theother %}", {}, 'this that theother'),1074 'load2': ("{% load echo other_echo from testtags %}{% echo this that theother %} {% other_echo and another thing %}", {}, 'this that theother and another thing'),1075 'load3': ("{% load echo upper from testtags %}{% echo this that theother %} {{ statement|upper }}", {'statement': 'not shouting'}, 'this that theother NOT SHOUTING'),1108 'load1': testcase("{% load echo from testtags %}{% echo this that theother %}", {}, 'this that theother'), 1109 'load2': testcase("{% load echo other_echo from testtags %}{% echo this that theother %} {% other_echo and another thing %}", {}, 'this that theother and another thing'), 1110 'load3': testcase("{% load echo upper from testtags %}{% echo this that theother %} {{ statement|upper }}", {'statement': 'not shouting'}, 'this that theother NOT SHOUTING'), 1076 1111 1077 1112 # {% load %} tag errors 1078 'load4': ("{% load echo other_echo bad_tag from testtags %}", {}, template.TemplateSyntaxError),1079 'load5': ("{% load echo other_echo bad_tag from %}", {}, template.TemplateSyntaxError),1080 'load6': ("{% load from testtags %}", {}, template.TemplateSyntaxError),1081 'load7': ("{% load echo from bad_library %}", {}, template.TemplateSyntaxError),1113 'load4': testcase("{% load echo other_echo bad_tag from testtags %}", {}, template.TemplateSyntaxError), 1114 'load5': testcase("{% load echo other_echo bad_tag from %}", {}, template.TemplateSyntaxError), 1115 'load6': testcase("{% load from testtags %}", {}, template.TemplateSyntaxError), 1116 'load7': testcase("{% load echo from bad_library %}", {}, template.TemplateSyntaxError), 1082 1117 1083 1118 ### I18N ################################################################## 1084 1119 1085 1120 # {% spaceless %} tag 1086 'spaceless01': ("{% spaceless %} <b> <i> text </i> </b> {% endspaceless %}", {}, "<b><i> text </i></b>"),1087 'spaceless02': ("{% spaceless %} <b> \n <i> text </i> \n </b> {% endspaceless %}", {}, "<b><i> text </i></b>"),1088 'spaceless03': ("{% spaceless %}<b><i>text</i></b>{% endspaceless %}", {}, "<b><i>text</i></b>"),1121 'spaceless01': testcase("{% spaceless %} <b> <i> text </i> </b> {% endspaceless %}", {}, "<b><i> text </i></b>"), 1122 'spaceless02': testcase("{% spaceless %} <b> \n <i> text </i> \n </b> {% endspaceless %}", {}, "<b><i> text </i></b>"), 1123 'spaceless03': testcase("{% spaceless %}<b><i>text</i></b>{% endspaceless %}", {}, "<b><i>text</i></b>"), 1089 1124 1090 1125 # simple translation of a string delimited by ' 1091 'i18n01': ("{% load i18n %}{% trans 'xxxyyyxxx' %}", {}, "xxxyyyxxx"),1126 'i18n01': testcase("{% load i18n %}{% trans 'xxxyyyxxx' %}", {}, "xxxyyyxxx"), 1092 1127 1093 1128 # simple translation of a string delimited by " 1094 'i18n02': ('{% load i18n %}{% trans "xxxyyyxxx" %}', {}, "xxxyyyxxx"),1129 'i18n02': testcase('{% load i18n %}{% trans "xxxyyyxxx" %}', {}, "xxxyyyxxx"), 1095 1130 1096 1131 # simple translation of a variable 1097 'i18n03': ('{% load i18n %}{% blocktrans %}{{ anton }}{% endblocktrans %}', {'anton': '\xc3\x85'}, u"Å"),1132 'i18n03': testcase('{% load i18n %}{% blocktrans %}{{ anton }}{% endblocktrans %}', {'anton': '\xc3\x85'}, u"Å"), 1098 1133 1099 1134 # simple translation of a variable and filter 1100 'i18n04': ('{% load i18n %}{% blocktrans with anton|lower as berta %}{{ berta }}{% endblocktrans %}', {'anton': '\xc3\x85'}, u'å'),1135 'i18n04': testcase('{% load i18n %}{% blocktrans with anton|lower as berta %}{{ berta }}{% endblocktrans %}', {'anton': '\xc3\x85'}, u'å'), 1101 1136 1102 1137 # simple translation of a string with interpolation 1103 'i18n05': ('{% load i18n %}{% blocktrans %}xxx{{ anton }}xxx{% endblocktrans %}', {'anton': 'yyy'}, "xxxyyyxxx"),1138 'i18n05': testcase('{% load i18n %}{% blocktrans %}xxx{{ anton }}xxx{% endblocktrans %}', {'anton': 'yyy'}, "xxxyyyxxx"), 1104 1139 1105 1140 # simple translation of a string to german 1106 'i18n06': ('{% load i18n %}{% trans "Page not found" %}', {'LANGUAGE_CODE': 'de'}, "Seite nicht gefunden"),1141 'i18n06': testcase('{% load i18n %}{% trans "Page not found" %}', {'LANGUAGE_CODE': 'de'}, "Seite nicht gefunden"), 1107 1142 1108 1143 # translation of singular form 1109 'i18n07': ('{% load i18n %}{% blocktrans count number as counter %}singular{% plural %}{{ counter }} plural{% endblocktrans %}', {'number': 1}, "singular"),1144 'i18n07': testcase('{% load i18n %}{% blocktrans count number as counter %}singular{% plural %}{{ counter }} plural{% endblocktrans %}', {'number': 1}, "singular"), 1110 1145 1111 1146 # translation of plural form 1112 'i18n08': ('{% load i18n %}{% blocktrans count number as counter %}singular{% plural %}{{ counter }} plural{% endblocktrans %}', {'number': 2}, "2 plural"),1147 'i18n08': testcase('{% load i18n %}{% blocktrans count number as counter %}singular{% plural %}{{ counter }} plural{% endblocktrans %}', {'number': 2}, "2 plural"), 1113 1148 1114 1149 # simple non-translation (only marking) of a string to german 1115 'i18n09': ('{% load i18n %}{% trans "Page not found" noop %}', {'LANGUAGE_CODE': 'de'}, "Page not found"),1150 'i18n09': testcase('{% load i18n %}{% trans "Page not found" noop %}', {'LANGUAGE_CODE': 'de'}, "Page not found"), 1116 1151 1117 1152 # translation of a variable with a translated filter 1118 'i18n10': ('{{ bool|yesno:_("yes,no,maybe") }}', {'bool': True, 'LANGUAGE_CODE': 'de'}, 'Ja'),1153 'i18n10': testcase('{{ bool|yesno:_("yes,no,maybe") }}', {'bool': True, 'LANGUAGE_CODE': 'de'}, 'Ja'), 1119 1154 1120 1155 # translation of a variable with a non-translated filter 1121 'i18n11': ('{{ bool|yesno:"ja,nein" }}', {'bool': True}, 'ja'),1156 'i18n11': testcase('{{ bool|yesno:"ja,nein" }}', {'bool': True}, 'ja'), 1122 1157 1123 1158 # usage of the get_available_languages tag 1124 'i18n12': ('{% load i18n %}{% get_available_languages as langs %}{% for lang in langs %}{% ifequal lang.0 "de" %}{{ lang.0 }}{% endifequal %}{% endfor %}', {}, 'de'),1159 'i18n12': testcase('{% load i18n %}{% get_available_languages as langs %}{% for lang in langs %}{% ifequal lang.0 "de" %}{{ lang.0 }}{% endifequal %}{% endfor %}', {}, 'de'), 1125 1160 1126 1161 # translation of constant strings 1127 'i18n13': ('{{ _("Password") }}', {'LANGUAGE_CODE': 'de'}, 'Passwort'),1128 'i18n14': ('{% cycle "foo" _("Password") _(\'Password\') as c %} {% cycle c %} {% cycle c %}', {'LANGUAGE_CODE': 'de'}, 'foo Passwort Passwort'),1129 'i18n15': ('{{ absent|default:_("Password") }}', {'LANGUAGE_CODE': 'de', 'absent': ""}, 'Passwort'),1130 'i18n16': ('{{ _("<") }}', {'LANGUAGE_CODE': 'de'}, '<'),1162 'i18n13': testcase('{{ _("Password") }}', {'LANGUAGE_CODE': 'de'}, 'Passwort'), 1163 'i18n14': testcase('{% cycle "foo" _("Password") _(\'Password\') as c %} {% cycle c %} {% cycle c %}', {'LANGUAGE_CODE': 'de'}, 'foo Passwort Passwort'), 1164 'i18n15': testcase('{{ absent|default:_("Password") }}', {'LANGUAGE_CODE': 'de', 'absent': ""}, 'Passwort'), 1165 'i18n16': testcase('{{ _("<") }}', {'LANGUAGE_CODE': 'de'}, '<'), 1131 1166 1132 1167 # Escaping inside blocktrans and trans works as if it was directly in the 1133 1168 # template. 1134 'i18n17': ('{% load i18n %}{% blocktrans with anton|escape as berta %}{{ berta }}{% endblocktrans %}', {'anton': 'α & β'}, u'α & β'),1135 'i18n18': ('{% load i18n %}{% blocktrans with anton|force_escape as berta %}{{ berta }}{% endblocktrans %}', {'anton': 'α & β'}, u'α & β'),1136 'i18n19': ('{% load i18n %}{% blocktrans %}{{ andrew }}{% endblocktrans %}', {'andrew': 'a & b'}, u'a & b'),1137 'i18n20': ('{% load i18n %}{% trans andrew %}', {'andrew': 'a & b'}, u'a & b'),1138 'i18n21': ('{% load i18n %}{% blocktrans %}{{ andrew }}{% endblocktrans %}', {'andrew': mark_safe('a & b')}, u'a & b'),1139 'i18n22': ('{% load i18n %}{% trans andrew %}', {'andrew': mark_safe('a & b')}, u'a & b'),1169 'i18n17': testcase('{% load i18n %}{% blocktrans with anton|escape as berta %}{{ berta }}{% endblocktrans %}', {'anton': 'α & β'}, u'α & β'), 1170 'i18n18': testcase('{% load i18n %}{% blocktrans with anton|force_escape as berta %}{{ berta }}{% endblocktrans %}', {'anton': 'α & β'}, u'α & β'), 1171 'i18n19': testcase('{% load i18n %}{% blocktrans %}{{ andrew }}{% endblocktrans %}', {'andrew': 'a & b'}, u'a & b'), 1172 'i18n20': testcase('{% load i18n %}{% trans andrew %}', {'andrew': 'a & b'}, u'a & b'), 1173 'i18n21': testcase('{% load i18n %}{% blocktrans %}{{ andrew }}{% endblocktrans %}', {'andrew': mark_safe('a & b')}, u'a & b'), 1174 'i18n22': testcase('{% load i18n %}{% trans andrew %}', {'andrew': mark_safe('a & b')}, u'a & b'), 1140 1175 1141 1176 # Use filters with the {% trans %} tag, #5972 1142 'i18n23': ('{% load i18n %}{% trans "Page not found"|capfirst|slice:"6:" %}', {'LANGUAGE_CODE': 'de'}, u'nicht gefunden'),1143 'i18n24': ("{% load i18n %}{% trans 'Page not found'|upper %}", {'LANGUAGE_CODE': 'de'}, u'SEITE NICHT GEFUNDEN'),1144 'i18n25': ('{% load i18n %}{% trans somevar|upper %}', {'somevar': 'Page not found', 'LANGUAGE_CODE': 'de'}, u'SEITE NICHT GEFUNDEN'),1177 'i18n23': testcase('{% load i18n %}{% trans "Page not found"|capfirst|slice:"6:" %}', {'LANGUAGE_CODE': 'de'}, u'nicht gefunden'), 1178 'i18n24': testcase("{% load i18n %}{% trans 'Page not found'|upper %}", {'LANGUAGE_CODE': 'de'}, u'SEITE NICHT GEFUNDEN'), 1179 'i18n25': testcase('{% load i18n %}{% trans somevar|upper %}', {'somevar': 'Page not found', 'LANGUAGE_CODE': 'de'}, u'SEITE NICHT GEFUNDEN'), 1145 1180 1146 1181 # translation of plural form with extra field in singular form (#13568) 1147 'i18n26': ('{% load i18n %}{% blocktrans with myextra_field as extra_field count number as counter %}singular {{ extra_field }}{% plural %}plural{% endblocktrans %}', {'number': 1, 'myextra_field': 'test'}, "singular test"),1182 'i18n26': testcase('{% load i18n %}{% blocktrans with myextra_field as extra_field count number as counter %}singular {{ extra_field }}{% plural %}plural{% endblocktrans %}', {'number': 1, 'myextra_field': 'test'}, "singular test"), 1148 1183 1149 1184 # translation of singular form in russian (#14126) 1150 'i18n27': ('{% load i18n %}{% blocktrans count number as counter %}1 result{% plural %}{{ counter }} results{% endblocktrans %}', {'number': 1, 'LANGUAGE_CODE': 'ru'}, u'1 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442'),1185 'i18n27': testcase('{% load i18n %}{% blocktrans count number as counter %}1 result{% plural %}{{ counter }} results{% endblocktrans %}', {'number': 1, 'LANGUAGE_CODE': 'ru'}, u'1 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442'), 1151 1186 1152 1187 ### HANDLING OF TEMPLATE_STRING_IF_INVALID ################################### 1153 1188 1154 'invalidstr01': ('{{ var|default:"Foo" }}', {}, ('Foo','INVALID')), 1155 'invalidstr02': ('{{ var|default_if_none:"Foo" }}', {}, ('','INVALID')), 1156 'invalidstr03': ('{% for v in var %}({{ v }}){% endfor %}', {}, ''), 1157 'invalidstr04': ('{% if var %}Yes{% else %}No{% endif %}', {}, 'No'), 1158 'invalidstr04': ('{% if var|default:"Foo" %}Yes{% else %}No{% endif %}', {}, 'Yes'), 1159 'invalidstr05': ('{{ var }}', {}, ('', 'INVALID %s', 'var')), 1160 'invalidstr06': ('{{ var.prop }}', {'var': {}}, ('', 'INVALID %s', 'var.prop')), 1189 'invalidstr01': testcase('{{ var|default:"Foo" }}', {}, 1190 lambda tdebug, invalid_str: invalid_str and 'INVALID' or 'Foo'), 1161 1191 1192 'invalidstr02': testcase('{{ var|default_if_none:"Foo" }}', {}, 1193 lambda tdebug, invalid_str: invalid_str and 'INVALID' or ''), 1194 1195 'invalidstr03': testcase('{% for v in var %}({{ v }}){% endfor %}', {}, ''), 1196 'invalidstr04': testcase('{% if var %}Yes{% else %}No{% endif %}', {}, 'No'), 1197 'invalidstr04': testcase('{% if var|default:"Foo" %}Yes{% else %}No{% endif %}', {}, 'Yes'), 1198 # what nested lambda is actually doing is settings invalid_str to 'INVALID %s' if invalid_str is specified 1199 'invalidstr05': testcase('{{ var }}', {}, 1200 lambda tdebug, invalid_str: invalid_str and "INVALID var" or "", invalid_str="INVALID %s"), 1201 'invalidstr06': testcase('{{ var.prop }}', {'var': {}}, 1202 lambda tdebug, invalid_str: invalid_str and "INVALID var.prop" or "", invalid_str="INVALID %s"), 1203 1162 1204 ### MULTILINE ############################################################# 1163 1205 1164 'multiline01': ("""1206 'multiline01': testcase(""" 1165 1207 Hello, 1166 1208 boys. 1167 1209 How … … 1180 1222 """), 1181 1223 1182 1224 ### REGROUP TAG ########################################################### 1183 'regroup01': ('{% regroup data by bar as grouped %}' + \1225 'regroup01': testcase('{% regroup data by bar as grouped %}' + \ 1184 1226 '{% for group in grouped %}' + \ 1185 1227 '{{ group.grouper }}:' + \ 1186 1228 '{% for item in group.list %}' + \ … … 1195 1237 '1:cd,2:ab,3:x,'), 1196 1238 1197 1239 # Test for silent failure when target variable isn't found 1198 'regroup02': ('{% regroup data by bar as grouped %}' + \1240 'regroup02': testcase('{% regroup data by bar as grouped %}' + \ 1199 1241 '{% for group in grouped %}' + \ 1200 1242 '{{ group.grouper }}:' + \ 1201 1243 '{% for item in group.list %}' + \ … … 1206 1248 ### SSI TAG ######################################################## 1207 1249 1208 1250 # Test normal behavior 1209 'old-ssi01': ('{%% ssi %s %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates', 'ssi_include.html'), {}, 'This is for testing an ssi include. {{ test }}\n'),1210 'old-ssi02': ('{%% ssi %s %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'not_here'), {}, ''),1251 'old-ssi01': testcase('{%% ssi %s %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates', 'ssi_include.html'), {}, 'This is for testing an ssi include. {{ test }}\n'), 1252 'old-ssi02': testcase('{%% ssi %s %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'not_here'), {}, ''), 1211 1253 1212 1254 # Test parsed output 1213 'old-ssi06': ('{%% ssi %s parsed %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates', 'ssi_include.html'), {'test': 'Look ma! It parsed!'}, 'This is for testing an ssi include. Look ma! It parsed!\n'),1214 'old-ssi07': ('{%% ssi %s parsed %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'not_here'), {'test': 'Look ma! It parsed!'}, ''),1255 'old-ssi06': testcase('{%% ssi %s parsed %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates', 'ssi_include.html'), {'test': 'Look ma! It parsed!'}, 'This is for testing an ssi include. Look ma! It parsed!\n'), 1256 'old-ssi07': testcase('{%% ssi %s parsed %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'not_here'), {'test': 'Look ma! It parsed!'}, ''), 1215 1257 1216 1258 # Future compatibility 1217 1259 # Test normal behavior 1218 'ssi01': ('{%% load ssi from future %%}{%% ssi "%s" %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates', 'ssi_include.html'), {}, 'This is for testing an ssi include. {{ test }}\n'),1219 'ssi02': ('{%% load ssi from future %%}{%% ssi "%s" %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'not_here'), {}, ''),1220 'ssi03': ("{%% load ssi from future %%}{%% ssi '%s' %%}" % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'not_here'), {}, ''),1260 'ssi01': testcase('{%% load ssi from future %%}{%% ssi "%s" %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates', 'ssi_include.html'), {}, 'This is for testing an ssi include. {{ test }}\n'), 1261 'ssi02': testcase('{%% load ssi from future %%}{%% ssi "%s" %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'not_here'), {}, ''), 1262 'ssi03': testcase("{%% load ssi from future %%}{%% ssi '%s' %%}" % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'not_here'), {}, ''), 1221 1263 1222 1264 # Test passing as a variable 1223 'ssi04': ('{% load ssi from future %}{% ssi ssi_file %}', {'ssi_file': os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates', 'ssi_include.html')}, 'This is for testing an ssi include. {{ test }}\n'),1224 'ssi05': ('{% load ssi from future %}{% ssi ssi_file %}', {'ssi_file': 'no_file'}, ''),1265 'ssi04': testcase('{% load ssi from future %}{% ssi ssi_file %}', {'ssi_file': os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates', 'ssi_include.html')}, 'This is for testing an ssi include. {{ test }}\n'), 1266 'ssi05': testcase('{% load ssi from future %}{% ssi ssi_file %}', {'ssi_file': 'no_file'}, ''), 1225 1267 1226 1268 # Test parsed output 1227 'ssi06': ('{%% load ssi from future %%}{%% ssi "%s" parsed %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates', 'ssi_include.html'), {'test': 'Look ma! It parsed!'}, 'This is for testing an ssi include. Look ma! It parsed!\n'),1228 'ssi07': ('{%% load ssi from future %%}{%% ssi "%s" parsed %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'not_here'), {'test': 'Look ma! It parsed!'}, ''),1269 'ssi06': testcase('{%% load ssi from future %%}{%% ssi "%s" parsed %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates', 'ssi_include.html'), {'test': 'Look ma! It parsed!'}, 'This is for testing an ssi include. Look ma! It parsed!\n'), 1270 'ssi07': testcase('{%% load ssi from future %%}{%% ssi "%s" parsed %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'not_here'), {'test': 'Look ma! It parsed!'}, ''), 1229 1271 1230 1272 1231 1273 ### TEMPLATETAG TAG ####################################################### 1232 'templatetag01': ('{% templatetag openblock %}', {}, '{%'),1233 'templatetag02': ('{% templatetag closeblock %}', {}, '%}'),1234 'templatetag03': ('{% templatetag openvariable %}', {}, '{{'),1235 'templatetag04': ('{% templatetag closevariable %}', {}, '}}'),1236 'templatetag05': ('{% templatetag %}', {}, template.TemplateSyntaxError),1237 'templatetag06': ('{% templatetag foo %}', {}, template.TemplateSyntaxError),1238 'templatetag07': ('{% templatetag openbrace %}', {}, '{'),1239 'templatetag08': ('{% templatetag closebrace %}', {}, '}'),1240 'templatetag09': ('{% templatetag openbrace %}{% templatetag openbrace %}', {}, '{{'),1241 'templatetag10': ('{% templatetag closebrace %}{% templatetag closebrace %}', {}, '}}'),1242 'templatetag11': ('{% templatetag opencomment %}', {}, '{#'),1243 'templatetag12': ('{% templatetag closecomment %}', {}, '#}'),1274 'templatetag01': testcase('{% templatetag openblock %}', {}, '{%'), 1275 'templatetag02': testcase('{% templatetag closeblock %}', {}, '%}'), 1276 'templatetag03': testcase('{% templatetag openvariable %}', {}, '{{'), 1277 'templatetag04': testcase('{% templatetag closevariable %}', {}, '}}'), 1278 'templatetag05': testcase('{% templatetag %}', {}, template.TemplateSyntaxError), 1279 'templatetag06': testcase('{% templatetag foo %}', {}, template.TemplateSyntaxError), 1280 'templatetag07': testcase('{% templatetag openbrace %}', {}, '{'), 1281 'templatetag08': testcase('{% templatetag closebrace %}', {}, '}'), 1282 'templatetag09': testcase('{% templatetag openbrace %}{% templatetag openbrace %}', {}, '{{'), 1283 'templatetag10': testcase('{% templatetag closebrace %}{% templatetag closebrace %}', {}, '}}'), 1284 'templatetag11': testcase('{% templatetag opencomment %}', {}, '{#'), 1285 'templatetag12': testcase('{% templatetag closecomment %}', {}, '#}'), 1244 1286 1245 1287 ### WIDTHRATIO TAG ######################################################## 1246 'widthratio01': ('{% widthratio a b 0 %}', {'a':50,'b':100}, '0'),1247 'widthratio02': ('{% widthratio a b 100 %}', {'a':0,'b':0}, ''),1248 'widthratio03': ('{% widthratio a b 100 %}', {'a':0,'b':100}, '0'),1249 'widthratio04': ('{% widthratio a b 100 %}', {'a':50,'b':100}, '50'),1250 'widthratio05': ('{% widthratio a b 100 %}', {'a':100,'b':100}, '100'),1288 'widthratio01': testcase('{% widthratio a b 0 %}', {'a':50,'b':100}, '0'), 1289 'widthratio02': testcase('{% widthratio a b 100 %}', {'a':0,'b':0}, ''), 1290 'widthratio03': testcase('{% widthratio a b 100 %}', {'a':0,'b':100}, '0'), 1291 'widthratio04': testcase('{% widthratio a b 100 %}', {'a':50,'b':100}, '50'), 1292 'widthratio05': testcase('{% widthratio a b 100 %}', {'a':100,'b':100}, '100'), 1251 1293 1252 1294 # 62.5 should round to 63 1253 'widthratio06': ('{% widthratio a b 100 %}', {'a':50,'b':80}, '63'),1295 'widthratio06': testcase('{% widthratio a b 100 %}', {'a':50,'b':80}, '63'), 1254 1296 1255 1297 # 71.4 should round to 71 1256 'widthratio07': ('{% widthratio a b 100 %}', {'a':50,'b':70}, '71'),1298 'widthratio07': testcase('{% widthratio a b 100 %}', {'a':50,'b':70}, '71'), 1257 1299 1258 1300 # Raise exception if we don't have 3 args, last one an integer 1259 'widthratio08': ('{% widthratio %}', {}, template.TemplateSyntaxError),1260 'widthratio09': ('{% widthratio a b %}', {'a':50,'b':100}, template.TemplateSyntaxError),1261 'widthratio10': ('{% widthratio a b 100.0 %}', {'a':50,'b':100}, '50'),1301 'widthratio08': testcase('{% widthratio %}', {}, template.TemplateSyntaxError), 1302 'widthratio09': testcase('{% widthratio a b %}', {'a':50,'b':100}, template.TemplateSyntaxError), 1303 'widthratio10': testcase('{% widthratio a b 100.0 %}', {'a':50,'b':100}, '50'), 1262 1304 1263 1305 # #10043: widthratio should allow max_width to be a variable 1264 'widthratio11': ('{% widthratio a b c %}', {'a':50,'b':100, 'c': 100}, '50'),1306 'widthratio11': testcase('{% widthratio a b c %}', {'a':50,'b':100, 'c': 100}, '50'), 1265 1307 1266 1308 ### WITH TAG ######################################################## 1267 'with01': ('{% with dict.key as key %}{{ key }}{% endwith %}', {'dict': {'key':50}}, '50'), 1268 'with02': ('{{ key }}{% with dict.key as key %}{{ key }}-{{ dict.key }}-{{ key }}{% endwith %}{{ key }}', {'dict': {'key':50}}, ('50-50-50', 'INVALID50-50-50INVALID')), 1309 'with01': testcase('{% with dict.key as key %}{{ key }}{% endwith %}', {'dict': {'key':50}}, '50'), 1310 'with02': testcase('{{ key }}{% with dict.key as key %}{{ key }}-{{ dict.key }}-{{ key }}{% endwith %}{{ key }}', {'dict': {'key':50}}, 1311 lambda tdebug, invalid_str: invalid_str and 'INVALID50-50-50INVALID' or '50-50-50'), 1269 1312 1270 'with-error01': ('{% with dict.key xx key %}{{ key }}{% endwith %}', {'dict': {'key':50}}, template.TemplateSyntaxError),1271 'with-error02': ('{% with dict.key as %}{{ key }}{% endwith %}', {'dict': {'key':50}}, template.TemplateSyntaxError),1313 'with-error01': testcase('{% with dict.key xx key %}{{ key }}{% endwith %}', {'dict': {'key':50}}, template.TemplateSyntaxError), 1314 'with-error02': testcase('{% with dict.key as %}{{ key }}{% endwith %}', {'dict': {'key':50}}, template.TemplateSyntaxError), 1272 1315 1273 1316 ### NOW TAG ######################################################## 1274 1317 # Simple case 1275 'now01': ('{% now "j n Y"%}', {}, str(datetime.now().day) + ' ' + str(datetime.now().month) + ' ' + str(datetime.now().year)),1318 'now01': testcase('{% now "j n Y"%}', {}, str(datetime.now().day) + ' ' + str(datetime.now().month) + ' ' + str(datetime.now().year)), 1276 1319 1277 1320 # Check parsing of escaped and special characters 1278 'now02': ('{% now "j "n" Y"%}', {}, template.TemplateSyntaxError),1321 'now02': testcase('{% now "j "n" Y"%}', {}, template.TemplateSyntaxError), 1279 1322 # 'now03': ('{% now "j \"n\" Y"%}', {}, str(datetime.now().day) + '"' + str(datetime.now().month) + '"' + str(datetime.now().year)), 1280 1323 # 'now04': ('{% now "j \nn\n Y"%}', {}, str(datetime.now().day) + '\n' + str(datetime.now().month) + '\n' + str(datetime.now().year)) 1281 1324 1282 1325 ### URL TAG ######################################################## 1283 1326 # Successes 1284 'legacyurl02': ('{% url regressiontests.templates.views.client_action id=client.id,action="update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),1285 'legacyurl02a': ('{% url regressiontests.templates.views.client_action client.id,"update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),1286 'legacyurl02b': ("{% url regressiontests.templates.views.client_action id=client.id,action='update' %}", {'client': {'id': 1}}, '/url_tag/client/1/update/'),1287 'legacyurl02c': ("{% url regressiontests.templates.views.client_action client.id,'update' %}", {'client': {'id': 1}}, '/url_tag/client/1/update/'),1288 'legacyurl10': ('{% url regressiontests.templates.views.client_action id=client.id,action="two words" %}', {'client': {'id': 1}}, '/url_tag/client/1/two%20words/'),1289 'legacyurl13': ('{% url regressiontests.templates.views.client_action id=client.id, action=arg|join:"-" %}', {'client': {'id': 1}, 'arg':['a','b']}, '/url_tag/client/1/a-b/'),1290 'legacyurl14': ('{% url regressiontests.templates.views.client_action client.id, arg|join:"-" %}', {'client': {'id': 1}, 'arg':['a','b']}, '/url_tag/client/1/a-b/'),1291 'legacyurl16': ('{% url regressiontests.templates.views.client_action action="update",id="1" %}', {}, '/url_tag/client/1/update/'),1292 'legacyurl16a': ("{% url regressiontests.templates.views.client_action action='update',id='1' %}", {}, '/url_tag/client/1/update/'),1293 'legacyurl17': ('{% url regressiontests.templates.views.client_action client_id=client.my_id,action=action %}', {'client': {'my_id': 1}, 'action': 'update'}, '/url_tag/client/1/update/'),1327 'legacyurl02': testcase('{% url regressiontests.templates.views.client_action id=client.id,action="update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'), 1328 'legacyurl02a': testcase('{% url regressiontests.templates.views.client_action client.id,"update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'), 1329 'legacyurl02b': testcase("{% url regressiontests.templates.views.client_action id=client.id,action='update' %}", {'client': {'id': 1}}, '/url_tag/client/1/update/'), 1330 'legacyurl02c': testcase("{% url regressiontests.templates.views.client_action client.id,'update' %}", {'client': {'id': 1}}, '/url_tag/client/1/update/'), 1331 'legacyurl10': testcase('{% url regressiontests.templates.views.client_action id=client.id,action="two words" %}', {'client': {'id': 1}}, '/url_tag/client/1/two%20words/'), 1332 'legacyurl13': testcase('{% url regressiontests.templates.views.client_action id=client.id, action=arg|join:"-" %}', {'client': {'id': 1}, 'arg':['a','b']}, '/url_tag/client/1/a-b/'), 1333 'legacyurl14': testcase('{% url regressiontests.templates.views.client_action client.id, arg|join:"-" %}', {'client': {'id': 1}, 'arg':['a','b']}, '/url_tag/client/1/a-b/'), 1334 'legacyurl16': testcase('{% url regressiontests.templates.views.client_action action="update",id="1" %}', {}, '/url_tag/client/1/update/'), 1335 'legacyurl16a': testcase("{% url regressiontests.templates.views.client_action action='update',id='1' %}", {}, '/url_tag/client/1/update/'), 1336 'legacyurl17': testcase('{% url regressiontests.templates.views.client_action client_id=client.my_id,action=action %}', {'client': {'my_id': 1}, 'action': 'update'}, '/url_tag/client/1/update/'), 1294 1337 1295 'old-url01': ('{% url regressiontests.templates.views.client client.id %}', {'client': {'id': 1}}, '/url_tag/client/1/'),1296 'old-url02': ('{% url regressiontests.templates.views.client_action id=client.id action="update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),1297 'old-url02a': ('{% url regressiontests.templates.views.client_action client.id "update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),1298 'old-url02b': ("{% url regressiontests.templates.views.client_action id=client.id action='update' %}", {'client': {'id': 1}}, '/url_tag/client/1/update/'),1299 'old-url02c': ("{% url regressiontests.templates.views.client_action client.id 'update' %}", {'client': {'id': 1}}, '/url_tag/client/1/update/'),1300 'old-url03': ('{% url regressiontests.templates.views.index %}', {}, '/url_tag/'),1301 'old-url04': ('{% url named.client client.id %}', {'client': {'id': 1}}, '/url_tag/named-client/1/'),1302 'old-url05': (u'{% url метка_оператора v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),1303 'old-url06': (u'{% url метка_оператора_2 tag=v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),1304 'old-url07': (u'{% url regressiontests.templates.views.client2 tag=v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),1305 'old-url08': (u'{% url метка_оператора v %}', {'v': 'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),1306 'old-url09': (u'{% url метка_оператора_2 tag=v %}', {'v': 'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),1307 'old-url10': ('{% url regressiontests.templates.views.client_action id=client.id action="two words" %}', {'client': {'id': 1}}, '/url_tag/client/1/two%20words/'),1308 'old-url11': ('{% url regressiontests.templates.views.client_action id=client.id action="==" %}', {'client': {'id': 1}}, '/url_tag/client/1/==/'),1309 'old-url12': ('{% url regressiontests.templates.views.client_action id=client.id action="," %}', {'client': {'id': 1}}, '/url_tag/client/1/,/'),1310 'old-url13': ('{% url regressiontests.templates.views.client_action id=client.id action=arg|join:"-" %}', {'client': {'id': 1}, 'arg':['a','b']}, '/url_tag/client/1/a-b/'),1311 'old-url14': ('{% url regressiontests.templates.views.client_action client.id arg|join:"-" %}', {'client': {'id': 1}, 'arg':['a','b']}, '/url_tag/client/1/a-b/'),1312 'old-url15': ('{% url regressiontests.templates.views.client_action 12 "test" %}', {}, '/url_tag/client/12/test/'),1313 'old-url18': ('{% url regressiontests.templates.views.client "1,2" %}', {}, '/url_tag/client/1,2/'),1338 'old-url01': testcase('{% url regressiontests.templates.views.client client.id %}', {'client': {'id': 1}}, '/url_tag/client/1/'), 1339 'old-url02': testcase('{% url regressiontests.templates.views.client_action id=client.id action="update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'), 1340 'old-url02a': testcase('{% url regressiontests.templates.views.client_action client.id "update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'), 1341 'old-url02b': testcase("{% url regressiontests.templates.views.client_action id=client.id action='update' %}", {'client': {'id': 1}}, '/url_tag/client/1/update/'), 1342 'old-url02c': testcase("{% url regressiontests.templates.views.client_action client.id 'update' %}", {'client': {'id': 1}}, '/url_tag/client/1/update/'), 1343 'old-url03': testcase('{% url regressiontests.templates.views.index %}', {}, '/url_tag/'), 1344 'old-url04': testcase('{% url named.client client.id %}', {'client': {'id': 1}}, '/url_tag/named-client/1/'), 1345 'old-url05': testcase(u'{% url метка_оператора v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'), 1346 'old-url06': testcase(u'{% url метка_оператора_2 tag=v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'), 1347 'old-url07': testcase(u'{% url regressiontests.templates.views.client2 tag=v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'), 1348 'old-url08': testcase(u'{% url метка_оператора v %}', {'v': 'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'), 1349 'old-url09': testcase(u'{% url метка_оператора_2 tag=v %}', {'v': 'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'), 1350 'old-url10': testcase('{% url regressiontests.templates.views.client_action id=client.id action="two words" %}', {'client': {'id': 1}}, '/url_tag/client/1/two%20words/'), 1351 'old-url11': testcase('{% url regressiontests.templates.views.client_action id=client.id action="==" %}', {'client': {'id': 1}}, '/url_tag/client/1/==/'), 1352 'old-url12': testcase('{% url regressiontests.templates.views.client_action id=client.id action="," %}', {'client': {'id': 1}}, '/url_tag/client/1/,/'), 1353 'old-url13': testcase('{% url regressiontests.templates.views.client_action id=client.id action=arg|join:"-" %}', {'client': {'id': 1}, 'arg':['a','b']}, '/url_tag/client/1/a-b/'), 1354 'old-url14': testcase('{% url regressiontests.templates.views.client_action client.id arg|join:"-" %}', {'client': {'id': 1}, 'arg':['a','b']}, '/url_tag/client/1/a-b/'), 1355 'old-url15': testcase('{% url regressiontests.templates.views.client_action 12 "test" %}', {}, '/url_tag/client/12/test/'), 1356 'old-url18': testcase('{% url regressiontests.templates.views.client "1,2" %}', {}, '/url_tag/client/1,2/'), 1314 1357 1315 1358 # Failures 1316 'old-url-fail01': ('{% url %}', {}, template.TemplateSyntaxError), 1317 'old-url-fail02': ('{% url no_such_view %}', {}, urlresolvers.NoReverseMatch), 1318 'old-url-fail03': ('{% url regressiontests.templates.views.client %}', {}, urlresolvers.NoReverseMatch), 1319 'old-url-fail04': ('{% url view id, %}', {}, template.TemplateSyntaxError), 1320 'old-url-fail05': ('{% url view id= %}', {}, template.TemplateSyntaxError), 1321 'old-url-fail06': ('{% url view a.id=id %}', {}, template.TemplateSyntaxError), 1322 'old-url-fail07': ('{% url view a.id!id %}', {}, template.TemplateSyntaxError), 1323 'old-url-fail08': ('{% url view id="unterminatedstring %}', {}, template.TemplateSyntaxError), 1324 'old-url-fail09': ('{% url view id=", %}', {}, template.TemplateSyntaxError), 1359 'old-url-fail01': testcase('{% url %}', {}, template.TemplateSyntaxError), 1360 'old-url-fail02': testcase('{% url no_such_view %}', {}, 1361 lambda tdebug, invalid_str: tdebug and template.TemplateSyntaxError or urlresolvers.NoReverseMatch), 1362 'old-url-fail03': testcase('{% url regressiontests.templates.views.client %}', {}, 1363 lambda tdebug, invalid_str: tdebug and template.TemplateSyntaxError or urlresolvers.NoReverseMatch), 1364 'old-url-fail04': testcase('{% url view id, %}', {}, template.TemplateSyntaxError), 1365 'old-url-fail05': testcase('{% url view id= %}', {}, template.TemplateSyntaxError), 1366 'old-url-fail06': testcase('{% url view a.id=id %}', {}, template.TemplateSyntaxError), 1367 'old-url-fail07': testcase('{% url view a.id!id %}', {}, template.TemplateSyntaxError), 1368 'old-url-fail08': testcase('{% url view id="unterminatedstring %}', {}, template.TemplateSyntaxError), 1369 'old-url-fail09': testcase('{% url view id=", %}', {}, template.TemplateSyntaxError), 1325 1370 1326 1371 # {% url ... as var %} 1327 'old-url-asvar01': ('{% url regressiontests.templates.views.index as url %}', {}, ''),1328 'old-url-asvar02': ('{% url regressiontests.templates.views.index as url %}{{ url }}', {}, '/url_tag/'),1329 'old-url-asvar03': ('{% url no_such_view as url %}{{ url }}', {}, ''),1372 'old-url-asvar01': testcase('{% url regressiontests.templates.views.index as url %}', {}, ''), 1373 'old-url-asvar02': testcase('{% url regressiontests.templates.views.index as url %}{{ url }}', {}, '/url_tag/'), 1374 'old-url-asvar03': testcase('{% url no_such_view as url %}{{ url }}', {}, ''), 1330 1375 1331 1376 # forward compatibility 1332 1377 # Successes 1333 'url01': ('{% load url from future %}{% url "regressiontests.templates.views.client" client.id %}', {'client': {'id': 1}}, '/url_tag/client/1/'),1334 'url02': ('{% load url from future %}{% url "regressiontests.templates.views.client_action" id=client.id action="update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),1335 'url02a': ('{% load url from future %}{% url "regressiontests.templates.views.client_action" client.id "update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),1336 'url02b': ("{% load url from future %}{% url 'regressiontests.templates.views.client_action' id=client.id action='update' %}", {'client': {'id': 1}}, '/url_tag/client/1/update/'),1337 'url02c': ("{% load url from future %}{% url 'regressiontests.templates.views.client_action' client.id 'update' %}", {'client': {'id': 1}}, '/url_tag/client/1/update/'),1338 'url03': ('{% load url from future %}{% url "regressiontests.templates.views.index" %}', {}, '/url_tag/'),1339 'url04': ('{% load url from future %}{% url "named.client" client.id %}', {'client': {'id': 1}}, '/url_tag/named-client/1/'),1340 'url05': (u'{% load url from future %}{% url "метка_оператора" v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),1341 'url06': (u'{% load url from future %}{% url "метка_оператора_2" tag=v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),1342 'url07': (u'{% load url from future %}{% url "regressiontests.templates.views.client2" tag=v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),1343 'url08': (u'{% load url from future %}{% url "метка_оператора" v %}', {'v': 'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),1344 'url09': (u'{% load url from future %}{% url "метка_оператора_2" tag=v %}', {'v': 'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),1345 'url10': ('{% load url from future %}{% url "regressiontests.templates.views.client_action" id=client.id action="two words" %}', {'client': {'id': 1}}, '/url_tag/client/1/two%20words/'),1346 'url11': ('{% load url from future %}{% url "regressiontests.templates.views.client_action" id=client.id action="==" %}', {'client': {'id': 1}}, '/url_tag/client/1/==/'),1347 'url12': ('{% load url from future %}{% url "regressiontests.templates.views.client_action" id=client.id action="," %}', {'client': {'id': 1}}, '/url_tag/client/1/,/'),1348 'url13': ('{% load url from future %}{% url "regressiontests.templates.views.client_action" id=client.id action=arg|join:"-" %}', {'client': {'id': 1}, 'arg':['a','b']}, '/url_tag/client/1/a-b/'),1349 'url14': ('{% load url from future %}{% url "regressiontests.templates.views.client_action" client.id arg|join:"-" %}', {'client': {'id': 1}, 'arg':['a','b']}, '/url_tag/client/1/a-b/'),1350 'url15': ('{% load url from future %}{% url "regressiontests.templates.views.client_action" 12 "test" %}', {}, '/url_tag/client/12/test/'),1351 'url18': ('{% load url from future %}{% url "regressiontests.templates.views.client" "1,2" %}', {}, '/url_tag/client/1,2/'),1378 'url01': testcase('{% load url from future %}{% url "regressiontests.templates.views.client" client.id %}', {'client': {'id': 1}}, '/url_tag/client/1/'), 1379 'url02': testcase('{% load url from future %}{% url "regressiontests.templates.views.client_action" id=client.id action="update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'), 1380 'url02a': testcase('{% load url from future %}{% url "regressiontests.templates.views.client_action" client.id "update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'), 1381 'url02b': testcase("{% load url from future %}{% url 'regressiontests.templates.views.client_action' id=client.id action='update' %}", {'client': {'id': 1}}, '/url_tag/client/1/update/'), 1382 'url02c': testcase("{% load url from future %}{% url 'regressiontests.templates.views.client_action' client.id 'update' %}", {'client': {'id': 1}}, '/url_tag/client/1/update/'), 1383 'url03': testcase('{% load url from future %}{% url "regressiontests.templates.views.index" %}', {}, '/url_tag/'), 1384 'url04': testcase('{% load url from future %}{% url "named.client" client.id %}', {'client': {'id': 1}}, '/url_tag/named-client/1/'), 1385 'url05': testcase(u'{% load url from future %}{% url "метка_оператора" v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'), 1386 'url06': testcase(u'{% load url from future %}{% url "метка_оператора_2" tag=v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'), 1387 'url07': testcase(u'{% load url from future %}{% url "regressiontests.templates.views.client2" tag=v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'), 1388 'url08': testcase(u'{% load url from future %}{% url "метка_оператора" v %}', {'v': 'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'), 1389 'url09': testcase(u'{% load url from future %}{% url "метка_оператора_2" tag=v %}', {'v': 'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'), 1390 'url10': testcase('{% load url from future %}{% url "regressiontests.templates.views.client_action" id=client.id action="two words" %}', {'client': {'id': 1}}, '/url_tag/client/1/two%20words/'), 1391 'url11': testcase('{% load url from future %}{% url "regressiontests.templates.views.client_action" id=client.id action="==" %}', {'client': {'id': 1}}, '/url_tag/client/1/==/'), 1392 'url12': testcase('{% load url from future %}{% url "regressiontests.templates.views.client_action" id=client.id action="," %}', {'client': {'id': 1}}, '/url_tag/client/1/,/'), 1393 'url13': testcase('{% load url from future %}{% url "regressiontests.templates.views.client_action" id=client.id action=arg|join:"-" %}', {'client': {'id': 1}, 'arg':['a','b']}, '/url_tag/client/1/a-b/'), 1394 'url14': testcase('{% load url from future %}{% url "regressiontests.templates.views.client_action" client.id arg|join:"-" %}', {'client': {'id': 1}, 'arg':['a','b']}, '/url_tag/client/1/a-b/'), 1395 'url15': testcase('{% load url from future %}{% url "regressiontests.templates.views.client_action" 12 "test" %}', {}, '/url_tag/client/12/test/'), 1396 'url18': testcase('{% load url from future %}{% url "regressiontests.templates.views.client" "1,2" %}', {}, '/url_tag/client/1,2/'), 1352 1397 1353 'url19': ('{% load url from future %}{% url named_url client.id %}', {'named_url': 'regressiontests.templates.views.client', 'client': {'id': 1}}, '/url_tag/client/1/'),1398 'url19': testcase('{% load url from future %}{% url named_url client.id %}', {'named_url': 'regressiontests.templates.views.client', 'client': {'id': 1}}, '/url_tag/client/1/'), 1354 1399 1355 1400 # Failures 1356 'url-fail01': ('{% load url from future %}{% url %}', {}, template.TemplateSyntaxError), 1357 'url-fail02': ('{% load url from future %}{% url "no_such_view" %}', {}, urlresolvers.NoReverseMatch), 1358 'url-fail03': ('{% load url from future %}{% url "regressiontests.templates.views.client" %}', {}, urlresolvers.NoReverseMatch), 1359 'url-fail04': ('{% load url from future %}{% url "view" id, %}', {}, template.TemplateSyntaxError), 1360 'url-fail05': ('{% load url from future %}{% url "view" id= %}', {}, template.TemplateSyntaxError), 1361 'url-fail06': ('{% load url from future %}{% url "view" a.id=id %}', {}, template.TemplateSyntaxError), 1362 'url-fail07': ('{% load url from future %}{% url "view" a.id!id %}', {}, template.TemplateSyntaxError), 1363 'url-fail08': ('{% load url from future %}{% url "view" id="unterminatedstring %}', {}, template.TemplateSyntaxError), 1364 'url-fail09': ('{% load url from future %}{% url "view" id=", %}', {}, template.TemplateSyntaxError), 1401 'url-fail01': testcase('{% load url from future %}{% url %}', {}, template.TemplateSyntaxError), 1402 'url-fail02': testcase('{% load url from future %}{% url "no_such_view" %}', {}, 1403 lambda tdebug, invalid_str: tdebug and template.TemplateSyntaxError or urlresolvers.NoReverseMatch), 1404 'url-fail03': testcase('{% load url from future %}{% url "regressiontests.templates.views.client" %}', {}, 1405 lambda tdebug, invalid_str: tdebug and template.TemplateSyntaxError or urlresolvers.NoReverseMatch), 1406 'url-fail04': testcase('{% load url from future %}{% url "view" id, %}', {}, template.TemplateSyntaxError), 1407 'url-fail05': testcase('{% load url from future %}{% url "view" id= %}', {}, template.TemplateSyntaxError), 1408 'url-fail06': testcase('{% load url from future %}{% url "view" a.id=id %}', {}, template.TemplateSyntaxError), 1409 'url-fail07': testcase('{% load url from future %}{% url "view" a.id!id %}', {}, template.TemplateSyntaxError), 1410 'url-fail08': testcase('{% load url from future %}{% url "view" id="unterminatedstring %}', {}, template.TemplateSyntaxError), 1411 'url-fail09': testcase('{% load url from future %}{% url "view" id=", %}', {}, template.TemplateSyntaxError), 1365 1412 1366 'url-fail11': ('{% load url from future %}{% url named_url %}', {}, urlresolvers.NoReverseMatch), 1367 'url-fail12': ('{% load url from future %}{% url named_url %}', {'named_url': 'no_such_view'}, urlresolvers.NoReverseMatch), 1368 'url-fail13': ('{% load url from future %}{% url named_url %}', {'named_url': 'regressiontests.templates.views.client'}, urlresolvers.NoReverseMatch), 1369 'url-fail14': ('{% load url from future %}{% url named_url id, %}', {'named_url': 'view'}, template.TemplateSyntaxError), 1370 'url-fail15': ('{% load url from future %}{% url named_url id= %}', {'named_url': 'view'}, template.TemplateSyntaxError), 1371 'url-fail16': ('{% load url from future %}{% url named_url a.id=id %}', {'named_url': 'view'}, template.TemplateSyntaxError), 1372 'url-fail17': ('{% load url from future %}{% url named_url a.id!id %}', {'named_url': 'view'}, template.TemplateSyntaxError), 1373 'url-fail18': ('{% load url from future %}{% url named_url id="unterminatedstring %}', {'named_url': 'view'}, template.TemplateSyntaxError), 1374 'url-fail19': ('{% load url from future %}{% url named_url id=", %}', {'named_url': 'view'}, template.TemplateSyntaxError), 1413 'url-fail11': testcase('{% load url from future %}{% url named_url %}', {}, 1414 lambda tdebug, invalid_str: tdebug and template.TemplateSyntaxError or urlresolvers.NoReverseMatch), 1415 'url-fail12': testcase('{% load url from future %}{% url named_url %}', {'named_url': 'no_such_view'}, 1416 lambda tdebug, invalid_str: tdebug and template.TemplateSyntaxError or urlresolvers.NoReverseMatch), 1417 'url-fail13': testcase('{% load url from future %}{% url named_url %}', {'named_url': 'regressiontests.templates.views.client'}, 1418 lambda tdebug, invalid_str: tdebug and template.TemplateSyntaxError or urlresolvers.NoReverseMatch), 1419 'url-fail14': testcase('{% load url from future %}{% url named_url id, %}', {'named_url': 'view'}, template.TemplateSyntaxError), 1420 'url-fail15': testcase('{% load url from future %}{% url named_url id= %}', {'named_url': 'view'}, template.TemplateSyntaxError), 1421 'url-fail16': testcase('{% load url from future %}{% url named_url a.id=id %}', {'named_url': 'view'}, template.TemplateSyntaxError), 1422 'url-fail17': testcase('{% load url from future %}{% url named_url a.id!id %}', {'named_url': 'view'}, template.TemplateSyntaxError), 1423 'url-fail18': testcase('{% load url from future %}{% url named_url id="unterminatedstring %}', {'named_url': 'view'}, template.TemplateSyntaxError), 1424 'url-fail19': testcase('{% load url from future %}{% url named_url id=", %}', {'named_url': 'view'}, template.TemplateSyntaxError), 1375 1425 1376 1426 # {% url ... as var %} 1377 'url-asvar01': ('{% load url from future %}{% url "regressiontests.templates.views.index" as url %}', {}, ''),1378 'url-asvar02': ('{% load url from future %}{% url "regressiontests.templates.views.index" as url %}{{ url }}', {}, '/url_tag/'),1379 'url-asvar03': ('{% load url from future %}{% url "no_such_view" as url %}{{ url }}', {}, ''),1427 'url-asvar01': testcase('{% load url from future %}{% url "regressiontests.templates.views.index" as url %}', {}, ''), 1428 'url-asvar02': testcase('{% load url from future %}{% url "regressiontests.templates.views.index" as url %}{{ url }}', {}, '/url_tag/'), 1429 'url-asvar03': testcase('{% load url from future %}{% url "no_such_view" as url %}{{ url }}', {}, ''), 1380 1430 1381 1431 ### CACHE TAG ###################################################### 1382 'cache01': ('{% load cache %}{% cache -1 test %}cache01{% endcache %}', {}, 'cache01'),1383 'cache02': ('{% load cache %}{% cache -1 test %}cache02{% endcache %}', {}, 'cache02'),1384 'cache03': ('{% load cache %}{% cache 2 test %}cache03{% endcache %}', {}, 'cache03'),1385 'cache04': ('{% load cache %}{% cache 2 test %}cache04{% endcache %}', {}, 'cache03'),1386 'cache05': ('{% load cache %}{% cache 2 test foo %}cache05{% endcache %}', {'foo': 1}, 'cache05'),1387 'cache06': ('{% load cache %}{% cache 2 test foo %}cache06{% endcache %}', {'foo': 2}, 'cache06'),1388 'cache07': ('{% load cache %}{% cache 2 test foo %}cache07{% endcache %}', {'foo': 1}, 'cache05'),1432 'cache01': testcase('{% load cache %}{% cache -1 test %}cache01{% endcache %}', {}, 'cache01'), 1433 'cache02': testcase('{% load cache %}{% cache -1 test %}cache02{% endcache %}', {}, 'cache02'), 1434 'cache03': testcase('{% load cache %}{% cache 2 test %}cache03{% endcache %}', {}, 'cache03'), 1435 'cache04': testcase('{% load cache %}{% cache 2 test %}cache04{% endcache %}', {}, 'cache03'), 1436 'cache05': testcase('{% load cache %}{% cache 2 test foo %}cache05{% endcache %}', {'foo': 1}, 'cache05'), 1437 'cache06': testcase('{% load cache %}{% cache 2 test foo %}cache06{% endcache %}', {'foo': 2}, 'cache06'), 1438 'cache07': testcase('{% load cache %}{% cache 2 test foo %}cache07{% endcache %}', {'foo': 1}, 'cache05'), 1389 1439 1390 1440 # Allow first argument to be a variable. 1391 'cache08': ('{% load cache %}{% cache time test foo %}cache08{% endcache %}', {'foo': 2, 'time': 2}, 'cache06'),1392 'cache09': ('{% load cache %}{% cache time test foo %}cache09{% endcache %}', {'foo': 3, 'time': -1}, 'cache09'),1393 'cache10': ('{% load cache %}{% cache time test foo %}cache10{% endcache %}', {'foo': 3, 'time': -1}, 'cache10'),1441 'cache08': testcase('{% load cache %}{% cache time test foo %}cache08{% endcache %}', {'foo': 2, 'time': 2}, 'cache06'), 1442 'cache09': testcase('{% load cache %}{% cache time test foo %}cache09{% endcache %}', {'foo': 3, 'time': -1}, 'cache09'), 1443 'cache10': testcase('{% load cache %}{% cache time test foo %}cache10{% endcache %}', {'foo': 3, 'time': -1}, 'cache10'), 1394 1444 1395 1445 # Raise exception if we don't have at least 2 args, first one integer. 1396 'cache11': ('{% load cache %}{% cache %}{% endcache %}', {}, template.TemplateSyntaxError),1397 'cache12': ('{% load cache %}{% cache 1 %}{% endcache %}', {}, template.TemplateSyntaxError),1398 'cache13': ('{% load cache %}{% cache foo bar %}{% endcache %}', {}, template.TemplateSyntaxError),1399 'cache14': ('{% load cache %}{% cache foo bar %}{% endcache %}', {'foo': 'fail'}, template.TemplateSyntaxError),1400 'cache15': ('{% load cache %}{% cache foo bar %}{% endcache %}', {'foo': []}, template.TemplateSyntaxError),1446 'cache11': testcase('{% load cache %}{% cache %}{% endcache %}', {}, template.TemplateSyntaxError), 1447 'cache12': testcase('{% load cache %}{% cache 1 %}{% endcache %}', {}, template.TemplateSyntaxError), 1448 'cache13': testcase('{% load cache %}{% cache foo bar %}{% endcache %}', {}, template.TemplateSyntaxError), 1449 'cache14': testcase('{% load cache %}{% cache foo bar %}{% endcache %}', {'foo': 'fail'}, template.TemplateSyntaxError), 1450 'cache15': testcase('{% load cache %}{% cache foo bar %}{% endcache %}', {'foo': []}, template.TemplateSyntaxError), 1401 1451 1402 1452 # Regression test for #7460. 1403 'cache16': ('{% load cache %}{% cache 1 foo bar %}{% endcache %}', {'foo': 'foo', 'bar': 'with spaces'}, ''),1453 'cache16': testcase('{% load cache %}{% cache 1 foo bar %}{% endcache %}', {'foo': 'foo', 'bar': 'with spaces'}, ''), 1404 1454 1405 1455 # Regression test for #11270. 1406 'cache17': ('{% load cache %}{% cache 10 long_cache_key poem %}Some Content{% endcache %}', {'poem': 'Oh freddled gruntbuggly/Thy micturations are to me/As plurdled gabbleblotchits/On a lurgid bee/That mordiously hath bitled out/Its earted jurtles/Into a rancid festering/Or else I shall rend thee in the gobberwarts with my blurglecruncheon/See if I dont.'}, 'Some Content'),1456 'cache17': testcase('{% load cache %}{% cache 10 long_cache_key poem %}Some Content{% endcache %}', {'poem': 'Oh freddled gruntbuggly/Thy micturations are to me/As plurdled gabbleblotchits/On a lurgid bee/That mordiously hath bitled out/Its earted jurtles/Into a rancid festering/Or else I shall rend thee in the gobberwarts with my blurglecruncheon/See if I dont.'}, 'Some Content'), 1407 1457 1408 1458 1409 1459 ### AUTOESCAPE TAG ############################################## 1410 'autoescape-tag01': ("{% autoescape off %}hello{% endautoescape %}", {}, "hello"),1411 'autoescape-tag02': ("{% autoescape off %}{{ first }}{% endautoescape %}", {"first": "<b>hello</b>"}, "<b>hello</b>"),1412 'autoescape-tag03': ("{% autoescape on %}{{ first }}{% endautoescape %}", {"first": "<b>hello</b>"}, "<b>hello</b>"),1460 'autoescape-tag01': testcase("{% autoescape off %}hello{% endautoescape %}", {}, "hello"), 1461 'autoescape-tag02': testcase("{% autoescape off %}{{ first }}{% endautoescape %}", {"first": "<b>hello</b>"}, "<b>hello</b>"), 1462 'autoescape-tag03': testcase("{% autoescape on %}{{ first }}{% endautoescape %}", {"first": "<b>hello</b>"}, "<b>hello</b>"), 1413 1463 1414 1464 # Autoescape disabling and enabling nest in a predictable way. 1415 'autoescape-tag04': ("{% autoescape off %}{{ first }} {% autoescape on%}{{ first }}{% endautoescape %}{% endautoescape %}", {"first": "<a>"}, "<a> <a>"),1465 'autoescape-tag04': testcase("{% autoescape off %}{{ first }} {% autoescape on%}{{ first }}{% endautoescape %}{% endautoescape %}", {"first": "<a>"}, "<a> <a>"), 1416 1466 1417 'autoescape-tag05': ("{% autoescape on %}{{ first }}{% endautoescape %}", {"first": "<b>first</b>"}, "<b>first</b>"),1467 'autoescape-tag05': testcase("{% autoescape on %}{{ first }}{% endautoescape %}", {"first": "<b>first</b>"}, "<b>first</b>"), 1418 1468 1419 1469 # Strings (ASCII or unicode) already marked as "safe" are not 1420 1470 # auto-escaped 1421 'autoescape-tag06': ("{{ first }}", {"first": mark_safe("<b>first</b>")}, "<b>first</b>"),1422 'autoescape-tag07': ("{% autoescape on %}{{ first }}{% endautoescape %}", {"first": mark_safe(u"<b>Apple</b>")}, u"<b>Apple</b>"),1471 'autoescape-tag06': testcase("{{ first }}", {"first": mark_safe("<b>first</b>")}, "<b>first</b>"), 1472 'autoescape-tag07': testcase("{% autoescape on %}{{ first }}{% endautoescape %}", {"first": mark_safe(u"<b>Apple</b>")}, u"<b>Apple</b>"), 1423 1473 1424 1474 # Literal string arguments to filters, if used in the result, are 1425 1475 # safe. 1426 'autoescape-tag08': (r'{% autoescape on %}{{ var|default_if_none:" endquote\" hah" }}{% endautoescape %}', {"var": None}, ' endquote" hah'),1476 'autoescape-tag08': testcase(r'{% autoescape on %}{{ var|default_if_none:" endquote\" hah" }}{% endautoescape %}', {"var": None}, ' endquote" hah'), 1427 1477 1428 1478 # Objects which return safe strings as their __unicode__ method 1429 1479 # won't get double-escaped. 1430 'autoescape-tag09': (r'{{ unsafe }}', {'unsafe': filters.UnsafeClass()}, 'you & me'),1431 'autoescape-tag10': (r'{{ safe }}', {'safe': filters.SafeClass()}, 'you > me'),1480 'autoescape-tag09': testcase(r'{{ unsafe }}', {'unsafe': filters.UnsafeClass()}, 'you & me'), 1481 'autoescape-tag10': testcase(r'{{ safe }}', {'safe': filters.SafeClass()}, 'you > me'), 1432 1482 1433 1483 # The "safe" and "escape" filters cannot work due to internal 1434 1484 # implementation details (fortunately, the (no)autoescape block 1435 1485 # tags can be used in those cases) 1436 'autoescape-filtertag01': ("{{ first }}{% filter safe %}{{ first }} x<y{% endfilter %}", {"first": "<a>"}, template.TemplateSyntaxError),1486 'autoescape-filtertag01': testcase("{{ first }}{% filter safe %}{{ first }} x<y{% endfilter %}", {"first": "<a>"}, template.TemplateSyntaxError), 1437 1487 1438 1488 # ifqeual compares unescaped vales. 1439 'autoescape-ifequal01': ('{% ifequal var "this & that" %}yes{% endifequal %}', { "var": "this & that" }, "yes"),1489 'autoescape-ifequal01': testcase('{% ifequal var "this & that" %}yes{% endifequal %}', { "var": "this & that" }, "yes"), 1440 1490 1441 1491 # Arguments to filters are 'safe' and manipulate their input unescaped. 1442 'autoescape-filters01': ('{{ var|cut:"&" }}', { "var": "this & that" }, "this that" ),1443 'autoescape-filters02': ('{{ var|join:" & \" }}', { "var": ("Tom", "Dick", "Harry") }, "Tom & Dick & Harry"),1492 'autoescape-filters01': testcase('{{ var|cut:"&" }}', { "var": "this & that" }, "this that" ), 1493 'autoescape-filters02': testcase('{{ var|join:" & \" }}', { "var": ("Tom", "Dick", "Harry") }, "Tom & Dick & Harry"), 1444 1494 1445 1495 # Literal strings are safe. 1446 'autoescape-literals01': ('{{ "this & that" }}',{}, "this & that"),1496 'autoescape-literals01': testcase('{{ "this & that" }}',{}, "this & that"), 1447 1497 1448 1498 # Iterating over strings outputs safe characters. 1449 'autoescape-stringiterations01': ('{% for l in var %}{{ l }},{% endfor %}', {'var': 'K&R'}, "K,&,R,"),1499 'autoescape-stringiterations01': testcase('{% for l in var %}{{ l }},{% endfor %}', {'var': 'K&R'}, "K,&,R,"), 1450 1500 1451 1501 # Escape requirement survives lookup. 1452 'autoescape-lookup01': ('{{ var.key }}', { "var": {"key": "this & that" }}, "this & that"),1502 'autoescape-lookup01': testcase('{{ var.key }}', { "var": {"key": "this & that" }}, "this & that"), 1453 1503 1454 1504 # Static template tags 1455 'static-prefixtag01': ('{% load static %}{% get_static_prefix %}', {}, settings.STATIC_URL),1456 'static-prefixtag02': ('{% load static %}{% get_static_prefix as static_prefix %}{{ static_prefix }}', {}, settings.STATIC_URL),1457 'static-prefixtag03': ('{% load static %}{% get_media_prefix %}', {}, settings.MEDIA_URL),1458 'static-prefixtag04': ('{% load static %}{% get_media_prefix as media_prefix %}{{ media_prefix }}', {}, settings.MEDIA_URL),1505 'static-prefixtag01': testcase('{% load static %}{% get_static_prefix %}', {}, settings.STATIC_URL), 1506 'static-prefixtag02': testcase('{% load static %}{% get_static_prefix as static_prefix %}{{ static_prefix }}', {}, settings.STATIC_URL), 1507 'static-prefixtag03': testcase('{% load static %}{% get_media_prefix %}', {}, settings.MEDIA_URL), 1508 'static-prefixtag04': testcase('{% load static %}{% get_media_prefix as media_prefix %}{{ media_prefix }}', {}, settings.MEDIA_URL), 1459 1509 } 1460 1510 1461 1511 class TemplateTagLoading(unittest.TestCase): -
tests/regressiontests/templates/filters.py
12 12 from django.utils.tzinfo import LocalTimezone, FixedOffset 13 13 from django.utils.safestring import mark_safe 14 14 15 from utils import testcase 16 15 17 # These two classes are used to test auto-escaping of __unicode__ output. 16 18 class UnsafeClass: 17 19 def __unicode__(self): … … 22 24 return mark_safe(u'you > me') 23 25 24 26 # RESULT SYNTAX -- 25 # 'template_name': ('template contents', 'context dict',27 # 'template_name': testcase('template contents', 'context dict', 26 28 # 'expected string output' or Exception class) 27 29 def get_filter_tests(): 28 30 now = datetime.now() … … 32 34 33 35 return { 34 36 # Default compare with datetime.now() 35 'filter-timesince01' : ('{{ a|timesince }}', {'a': datetime.now() + timedelta(minutes=-1, seconds = -10)}, '1 minute'),36 'filter-timesince02' : ('{{ a|timesince }}', {'a': datetime.now() - timedelta(days=1, minutes = 1)}, '1 day'),37 'filter-timesince03' : ('{{ a|timesince }}', {'a': datetime.now() - timedelta(hours=1, minutes=25, seconds = 10)}, '1 hour, 25 minutes'),37 'filter-timesince01' : testcase('{{ a|timesince }}', {'a': datetime.now() + timedelta(minutes=-1, seconds = -10)}, '1 minute'), 38 'filter-timesince02' : testcase('{{ a|timesince }}', {'a': datetime.now() - timedelta(days=1, minutes = 1)}, '1 day'), 39 'filter-timesince03' : testcase('{{ a|timesince }}', {'a': datetime.now() - timedelta(hours=1, minutes=25, seconds = 10)}, '1 hour, 25 minutes'), 38 40 39 41 # Compare to a given parameter 40 'filter-timesince04' : ('{{ a|timesince:b }}', {'a':now - timedelta(days=2), 'b':now - timedelta(days=1)}, '1 day'),41 'filter-timesince05' : ('{{ a|timesince:b }}', {'a':now - timedelta(days=2, minutes=1), 'b':now - timedelta(days=2)}, '1 minute'),42 'filter-timesince04' : testcase('{{ a|timesince:b }}', {'a':now - timedelta(days=2), 'b':now - timedelta(days=1)}, '1 day'), 43 'filter-timesince05' : testcase('{{ a|timesince:b }}', {'a':now - timedelta(days=2, minutes=1), 'b':now - timedelta(days=2)}, '1 minute'), 42 44 43 45 # Check that timezone is respected 44 'filter-timesince06' : ('{{ a|timesince:b }}', {'a':now_tz - timedelta(hours=8), 'b':now_tz}, '8 hours'),46 'filter-timesince06' : testcase('{{ a|timesince:b }}', {'a':now_tz - timedelta(hours=8), 'b':now_tz}, '8 hours'), 45 47 46 48 # Regression for #7443 47 'filter-timesince07': ('{{ earlier|timesince }}', { 'earlier': now - timedelta(days=7) }, '1 week'),48 'filter-timesince08': ('{{ earlier|timesince:now }}', { 'now': now, 'earlier': now - timedelta(days=7) }, '1 week'),49 'filter-timesince09': ('{{ later|timesince }}', { 'later': now + timedelta(days=7) }, '0 minutes'),50 'filter-timesince10': ('{{ later|timesince:now }}', { 'now': now, 'later': now + timedelta(days=7) }, '0 minutes'),49 'filter-timesince07': testcase('{{ earlier|timesince }}', { 'earlier': now - timedelta(days=7) }, '1 week'), 50 'filter-timesince08': testcase('{{ earlier|timesince:now }}', { 'now': now, 'earlier': now - timedelta(days=7) }, '1 week'), 51 'filter-timesince09': testcase('{{ later|timesince }}', { 'later': now + timedelta(days=7) }, '0 minutes'), 52 'filter-timesince10': testcase('{{ later|timesince:now }}', { 'now': now, 'later': now + timedelta(days=7) }, '0 minutes'), 51 53 52 54 # Ensures that differing timezones are calculated correctly 53 'filter-timesince11' : ('{{ a|timesince }}', {'a': now}, '0 minutes'),54 'filter-timesince12' : ('{{ a|timesince }}', {'a': now_tz}, '0 minutes'),55 'filter-timesince13' : ('{{ a|timesince }}', {'a': now_tz_i}, '0 minutes'),56 'filter-timesince14' : ('{{ a|timesince:b }}', {'a': now_tz, 'b': now_tz_i}, '0 minutes'),57 'filter-timesince15' : ('{{ a|timesince:b }}', {'a': now, 'b': now_tz_i}, ''),58 'filter-timesince16' : ('{{ a|timesince:b }}', {'a': now_tz_i, 'b': now}, ''),55 'filter-timesince11' : testcase('{{ a|timesince }}', {'a': now}, '0 minutes'), 56 'filter-timesince12' : testcase('{{ a|timesince }}', {'a': now_tz}, '0 minutes'), 57 'filter-timesince13' : testcase('{{ a|timesince }}', {'a': now_tz_i}, '0 minutes'), 58 'filter-timesince14' : testcase('{{ a|timesince:b }}', {'a': now_tz, 'b': now_tz_i}, '0 minutes'), 59 'filter-timesince15' : testcase('{{ a|timesince:b }}', {'a': now, 'b': now_tz_i}, ''), 60 'filter-timesince16' : testcase('{{ a|timesince:b }}', {'a': now_tz_i, 'b': now}, ''), 59 61 60 62 # Regression for #9065 (two date objects). 61 'filter-timesince17' : ('{{ a|timesince:b }}', {'a': today, 'b': today}, '0 minutes'),62 'filter-timesince18' : ('{{ a|timesince:b }}', {'a': today, 'b': today + timedelta(hours=24)}, '1 day'),63 'filter-timesince17' : testcase('{{ a|timesince:b }}', {'a': today, 'b': today}, '0 minutes'), 64 'filter-timesince18' : testcase('{{ a|timesince:b }}', {'a': today, 'b': today + timedelta(hours=24)}, '1 day'), 63 65 64 66 # Default compare with datetime.now() 65 'filter-timeuntil01' : ('{{ a|timeuntil }}', {'a':datetime.now() + timedelta(minutes=2, seconds = 10)}, '2 minutes'),66 'filter-timeuntil02' : ('{{ a|timeuntil }}', {'a':(datetime.now() + timedelta(days=1, seconds = 10))}, '1 day'),67 'filter-timeuntil03' : ('{{ a|timeuntil }}', {'a':(datetime.now() + timedelta(hours=8, minutes=10, seconds = 10))}, '8 hours, 10 minutes'),67 'filter-timeuntil01' : testcase('{{ a|timeuntil }}', {'a':datetime.now() + timedelta(minutes=2, seconds = 10)}, '2 minutes'), 68 'filter-timeuntil02' : testcase('{{ a|timeuntil }}', {'a':(datetime.now() + timedelta(days=1, seconds = 10))}, '1 day'), 69 'filter-timeuntil03' : testcase('{{ a|timeuntil }}', {'a':(datetime.now() + timedelta(hours=8, minutes=10, seconds = 10))}, '8 hours, 10 minutes'), 68 70 69 71 # Compare to a given parameter 70 'filter-timeuntil04' : ('{{ a|timeuntil:b }}', {'a':now - timedelta(days=1), 'b':now - timedelta(days=2)}, '1 day'),71 'filter-timeuntil05' : ('{{ a|timeuntil:b }}', {'a':now - timedelta(days=2), 'b':now - timedelta(days=2, minutes=1)}, '1 minute'),72 'filter-timeuntil04' : testcase('{{ a|timeuntil:b }}', {'a':now - timedelta(days=1), 'b':now - timedelta(days=2)}, '1 day'), 73 'filter-timeuntil05' : testcase('{{ a|timeuntil:b }}', {'a':now - timedelta(days=2), 'b':now - timedelta(days=2, minutes=1)}, '1 minute'), 72 74 73 75 # Regression for #7443 74 'filter-timeuntil06': ('{{ earlier|timeuntil }}', { 'earlier': now - timedelta(days=7) }, '0 minutes'),75 'filter-timeuntil07': ('{{ earlier|timeuntil:now }}', { 'now': now, 'earlier': now - timedelta(days=7) }, '0 minutes'),76 'filter-timeuntil08': ('{{ later|timeuntil }}', { 'later': now + timedelta(days=7, hours=1) }, '1 week'),77 'filter-timeuntil09': ('{{ later|timeuntil:now }}', { 'now': now, 'later': now + timedelta(days=7) }, '1 week'),76 'filter-timeuntil06': testcase('{{ earlier|timeuntil }}', { 'earlier': now - timedelta(days=7) }, '0 minutes'), 77 'filter-timeuntil07': testcase('{{ earlier|timeuntil:now }}', { 'now': now, 'earlier': now - timedelta(days=7) }, '0 minutes'), 78 'filter-timeuntil08': testcase('{{ later|timeuntil }}', { 'later': now + timedelta(days=7, hours=1) }, '1 week'), 79 'filter-timeuntil09': testcase('{{ later|timeuntil:now }}', { 'now': now, 'later': now + timedelta(days=7) }, '1 week'), 78 80 79 81 # Ensures that differing timezones are calculated correctly 80 'filter-timeuntil10' : ('{{ a|timeuntil }}', {'a': now_tz_i}, '0 minutes'),81 'filter-timeuntil11' : ('{{ a|timeuntil:b }}', {'a': now_tz_i, 'b': now_tz}, '0 minutes'),82 'filter-timeuntil10' : testcase('{{ a|timeuntil }}', {'a': now_tz_i}, '0 minutes'), 83 'filter-timeuntil11' : testcase('{{ a|timeuntil:b }}', {'a': now_tz_i, 'b': now_tz}, '0 minutes'), 82 84 83 85 # Regression for #9065 (two date objects). 84 'filter-timeuntil12' : ('{{ a|timeuntil:b }}', {'a': today, 'b': today}, '0 minutes'),85 'filter-timeuntil13' : ('{{ a|timeuntil:b }}', {'a': today, 'b': today - timedelta(hours=24)}, '1 day'),86 'filter-timeuntil12' : testcase('{{ a|timeuntil:b }}', {'a': today, 'b': today}, '0 minutes'), 87 'filter-timeuntil13' : testcase('{{ a|timeuntil:b }}', {'a': today, 'b': today - timedelta(hours=24)}, '1 day'), 86 88 87 'filter-addslash01': ("{% autoescape off %}{{ a|addslashes }} {{ b|addslashes }}{% endautoescape %}", {"a": "<a>'", "b": mark_safe("<a>'")}, ur"<a>\' <a>\'"),88 'filter-addslash02': ("{{ a|addslashes }} {{ b|addslashes }}", {"a": "<a>'", "b": mark_safe("<a>'")}, ur"<a>\' <a>\'"),89 'filter-addslash01': testcase("{% autoescape off %}{{ a|addslashes }} {{ b|addslashes }}{% endautoescape %}", {"a": "<a>'", "b": mark_safe("<a>'")}, ur"<a>\' <a>\'"), 90 'filter-addslash02': testcase("{{ a|addslashes }} {{ b|addslashes }}", {"a": "<a>'", "b": mark_safe("<a>'")}, ur"<a>\' <a>\'"), 89 91 90 'filter-capfirst01': ("{% autoescape off %}{{ a|capfirst }} {{ b|capfirst }}{% endautoescape %}", {"a": "fred>", "b": mark_safe("fred>")}, u"Fred> Fred>"),91 'filter-capfirst02': ("{{ a|capfirst }} {{ b|capfirst }}", {"a": "fred>", "b": mark_safe("fred>")}, u"Fred> Fred>"),92 'filter-capfirst01': testcase("{% autoescape off %}{{ a|capfirst }} {{ b|capfirst }}{% endautoescape %}", {"a": "fred>", "b": mark_safe("fred>")}, u"Fred> Fred>"), 93 'filter-capfirst02': testcase("{{ a|capfirst }} {{ b|capfirst }}", {"a": "fred>", "b": mark_safe("fred>")}, u"Fred> Fred>"), 92 94 93 95 # Note that applying fix_ampsersands in autoescape mode leads to 94 96 # double escaping. 95 'filter-fix_ampersands01': ("{% autoescape off %}{{ a|fix_ampersands }} {{ b|fix_ampersands }}{% endautoescape %}", {"a": "a&b", "b": mark_safe("a&b")}, u"a&b a&b"),96 'filter-fix_ampersands02': ("{{ a|fix_ampersands }} {{ b|fix_ampersands }}", {"a": "a&b", "b": mark_safe("a&b")}, u"a&amp;b a&b"),97 'filter-fix_ampersands01': testcase("{% autoescape off %}{{ a|fix_ampersands }} {{ b|fix_ampersands }}{% endautoescape %}", {"a": "a&b", "b": mark_safe("a&b")}, u"a&b a&b"), 98 'filter-fix_ampersands02': testcase("{{ a|fix_ampersands }} {{ b|fix_ampersands }}", {"a": "a&b", "b": mark_safe("a&b")}, u"a&amp;b a&b"), 97 99 98 'filter-floatformat01': ("{% autoescape off %}{{ a|floatformat }} {{ b|floatformat }}{% endautoescape %}", {"a": "1.42", "b": mark_safe("1.42")}, u"1.4 1.4"),99 'filter-floatformat02': ("{{ a|floatformat }} {{ b|floatformat }}", {"a": "1.42", "b": mark_safe("1.42")}, u"1.4 1.4"),100 'filter-floatformat01': testcase("{% autoescape off %}{{ a|floatformat }} {{ b|floatformat }}{% endautoescape %}", {"a": "1.42", "b": mark_safe("1.42")}, u"1.4 1.4"), 101 'filter-floatformat02': testcase("{{ a|floatformat }} {{ b|floatformat }}", {"a": "1.42", "b": mark_safe("1.42")}, u"1.4 1.4"), 100 102 101 103 # The contents of "linenumbers" is escaped according to the current 102 104 # autoescape setting. 103 'filter-linenumbers01': ("{{ a|linenumbers }} {{ b|linenumbers }}", {"a": "one\n<two>\nthree", "b": mark_safe("one\n<two>\nthree")}, u"1. one\n2. <two>\n3. three 1. one\n2. <two>\n3. three"),104 'filter-linenumbers02': ("{% autoescape off %}{{ a|linenumbers }} {{ b|linenumbers }}{% endautoescape %}", {"a": "one\n<two>\nthree", "b": mark_safe("one\n<two>\nthree")}, u"1. one\n2. <two>\n3. three 1. one\n2. <two>\n3. three"),105 'filter-linenumbers01': testcase("{{ a|linenumbers }} {{ b|linenumbers }}", {"a": "one\n<two>\nthree", "b": mark_safe("one\n<two>\nthree")}, u"1. one\n2. <two>\n3. three 1. one\n2. <two>\n3. three"), 106 'filter-linenumbers02': testcase("{% autoescape off %}{{ a|linenumbers }} {{ b|linenumbers }}{% endautoescape %}", {"a": "one\n<two>\nthree", "b": mark_safe("one\n<two>\nthree")}, u"1. one\n2. <two>\n3. three 1. one\n2. <two>\n3. three"), 105 107 106 'filter-lower01': ("{% autoescape off %}{{ a|lower }} {{ b|lower }}{% endautoescape %}", {"a": "Apple & banana", "b": mark_safe("Apple & banana")}, u"apple & banana apple & banana"),107 'filter-lower02': ("{{ a|lower }} {{ b|lower }}", {"a": "Apple & banana", "b": mark_safe("Apple & banana")}, u"apple & banana apple & banana"),108 'filter-lower01': testcase("{% autoescape off %}{{ a|lower }} {{ b|lower }}{% endautoescape %}", {"a": "Apple & banana", "b": mark_safe("Apple & banana")}, u"apple & banana apple & banana"), 109 'filter-lower02': testcase("{{ a|lower }} {{ b|lower }}", {"a": "Apple & banana", "b": mark_safe("Apple & banana")}, u"apple & banana apple & banana"), 108 110 109 111 # The make_list filter can destroy existing escaping, so the results are 110 112 # escaped. 111 'filter-make_list01': ("{% autoescape off %}{{ a|make_list }}{% endautoescape %}", {"a": mark_safe("&")}, u"[u'&']"),112 'filter-make_list02': ("{{ a|make_list }}", {"a": mark_safe("&")}, u"[u'&']"),113 'filter-make_list03': ('{% autoescape off %}{{ a|make_list|stringformat:"s"|safe }}{% endautoescape %}', {"a": mark_safe("&")}, u"[u'&']"),114 'filter-make_list04': ('{{ a|make_list|stringformat:"s"|safe }}', {"a": mark_safe("&")}, u"[u'&']"),113 'filter-make_list01': testcase("{% autoescape off %}{{ a|make_list }}{% endautoescape %}", {"a": mark_safe("&")}, u"[u'&']"), 114 'filter-make_list02': testcase("{{ a|make_list }}", {"a": mark_safe("&")}, u"[u'&']"), 115 'filter-make_list03': testcase('{% autoescape off %}{{ a|make_list|stringformat:"s"|safe }}{% endautoescape %}', {"a": mark_safe("&")}, u"[u'&']"), 116 'filter-make_list04': testcase('{{ a|make_list|stringformat:"s"|safe }}', {"a": mark_safe("&")}, u"[u'&']"), 115 117 116 118 # Running slugify on a pre-escaped string leads to odd behaviour, 117 119 # but the result is still safe. 118 'filter-slugify01': ("{% autoescape off %}{{ a|slugify }} {{ b|slugify }}{% endautoescape %}", {"a": "a & b", "b": mark_safe("a & b")}, u"a-b a-amp-b"),119 'filter-slugify02': ("{{ a|slugify }} {{ b|slugify }}", {"a": "a & b", "b": mark_safe("a & b")}, u"a-b a-amp-b"),120 'filter-slugify01': testcase("{% autoescape off %}{{ a|slugify }} {{ b|slugify }}{% endautoescape %}", {"a": "a & b", "b": mark_safe("a & b")}, u"a-b a-amp-b"), 121 'filter-slugify02': testcase("{{ a|slugify }} {{ b|slugify }}", {"a": "a & b", "b": mark_safe("a & b")}, u"a-b a-amp-b"), 120 122 121 123 # Notice that escaping is applied *after* any filters, so the string 122 124 # formatting here only needs to deal with pre-escaped characters. 123 'filter-stringformat01': ('{% autoescape off %}.{{ a|stringformat:"5s" }}. .{{ b|stringformat:"5s" }}.{% endautoescape %}',125 'filter-stringformat01': testcase('{% autoescape off %}.{{ a|stringformat:"5s" }}. .{{ b|stringformat:"5s" }}.{% endautoescape %}', 124 126 {"a": "a<b", "b": mark_safe("a<b")}, u". a<b. . a<b."), 125 'filter-stringformat02': ('.{{ a|stringformat:"5s" }}. .{{ b|stringformat:"5s" }}.', {"a": "a<b", "b": mark_safe("a<b")},127 'filter-stringformat02': testcase('.{{ a|stringformat:"5s" }}. .{{ b|stringformat:"5s" }}.', {"a": "a<b", "b": mark_safe("a<b")}, 126 128 u". a<b. . a<b."), 127 129 128 130 # Test the title filter 129 'filter-title1' : ('{{ a|title }}', {'a' : 'JOE\'S CRAB SHACK'}, u'Joe's Crab Shack'),130 'filter-title2' : ('{{ a|title }}', {'a' : '555 WEST 53RD STREET'}, u'555 West 53rd Street'),131 'filter-title1' : testcase('{{ a|title }}', {'a' : 'JOE\'S CRAB SHACK'}, u'Joe's Crab Shack'), 132 'filter-title2' : testcase('{{ a|title }}', {'a' : '555 WEST 53RD STREET'}, u'555 West 53rd Street'), 131 133 132 'filter-truncatewords01': ('{% autoescape off %}{{ a|truncatewords:"2" }} {{ b|truncatewords:"2"}}{% endautoescape %}',134 'filter-truncatewords01': testcase('{% autoescape off %}{{ a|truncatewords:"2" }} {{ b|truncatewords:"2"}}{% endautoescape %}', 133 135 {"a": "alpha & bravo", "b": mark_safe("alpha & bravo")}, u"alpha & ... alpha & ..."), 134 'filter-truncatewords02': ('{{ a|truncatewords:"2" }} {{ b|truncatewords:"2"}}',136 'filter-truncatewords02': testcase('{{ a|truncatewords:"2" }} {{ b|truncatewords:"2"}}', 135 137 {"a": "alpha & bravo", "b": mark_safe("alpha & bravo")}, u"alpha & ... alpha & ..."), 136 138 137 139 # The "upper" filter messes up entities (which are case-sensitive), 138 140 # so it's not safe for non-escaping purposes. 139 'filter-upper01': ('{% autoescape off %}{{ a|upper }} {{ b|upper }}{% endautoescape %}', {"a": "a & b", "b": mark_safe("a & b")}, u"A & B A & B"),140 'filter-upper02': ('{{ a|upper }} {{ b|upper }}', {"a": "a & b", "b": mark_safe("a & b")}, u"A & B A &AMP; B"),141 'filter-upper01': testcase('{% autoescape off %}{{ a|upper }} {{ b|upper }}{% endautoescape %}', {"a": "a & b", "b": mark_safe("a & b")}, u"A & B A & B"), 142 'filter-upper02': testcase('{{ a|upper }} {{ b|upper }}', {"a": "a & b", "b": mark_safe("a & b")}, u"A & B A &AMP; B"), 141 143 142 'filter-urlize01': ('{% autoescape off %}{{ a|urlize }} {{ b|urlize }}{% endautoescape %}', {"a": "http://example.com/?x=&y=", "b": mark_safe("http://example.com?x=&y=")}, u'<a href="http://example.com/?x=&y=" rel="nofollow">http://example.com/?x=&y=</a> <a href="http://example.com?x=&y=" rel="nofollow">http://example.com?x=&y=</a>'),143 'filter-urlize02': ('{{ a|urlize }} {{ b|urlize }}', {"a": "http://example.com/?x=&y=", "b": mark_safe("http://example.com?x=&y=")}, u'<a href="http://example.com/?x=&y=" rel="nofollow">http://example.com/?x=&y=</a> <a href="http://example.com?x=&y=" rel="nofollow">http://example.com?x=&y=</a>'),144 'filter-urlize03': ('{% autoescape off %}{{ a|urlize }}{% endautoescape %}', {"a": mark_safe("a & b")}, 'a & b'),145 'filter-urlize04': ('{{ a|urlize }}', {"a": mark_safe("a & b")}, 'a & b'),144 'filter-urlize01': testcase('{% autoescape off %}{{ a|urlize }} {{ b|urlize }}{% endautoescape %}', {"a": "http://example.com/?x=&y=", "b": mark_safe("http://example.com?x=&y=")}, u'<a href="http://example.com/?x=&y=" rel="nofollow">http://example.com/?x=&y=</a> <a href="http://example.com?x=&y=" rel="nofollow">http://example.com?x=&y=</a>'), 145 'filter-urlize02': testcase('{{ a|urlize }} {{ b|urlize }}', {"a": "http://example.com/?x=&y=", "b": mark_safe("http://example.com?x=&y=")}, u'<a href="http://example.com/?x=&y=" rel="nofollow">http://example.com/?x=&y=</a> <a href="http://example.com?x=&y=" rel="nofollow">http://example.com?x=&y=</a>'), 146 'filter-urlize03': testcase('{% autoescape off %}{{ a|urlize }}{% endautoescape %}', {"a": mark_safe("a & b")}, 'a & b'), 147 'filter-urlize04': testcase('{{ a|urlize }}', {"a": mark_safe("a & b")}, 'a & b'), 146 148 147 149 # This will lead to a nonsense result, but at least it won't be 148 150 # exploitable for XSS purposes when auto-escaping is on. 149 'filter-urlize05': ('{% autoescape off %}{{ a|urlize }}{% endautoescape %}', {"a": "<script>alert('foo')</script>"}, "<script>alert('foo')</script>"),150 'filter-urlize06': ('{{ a|urlize }}', {"a": "<script>alert('foo')</script>"}, '<script>alert('foo')</script>'),151 'filter-urlize05': testcase('{% autoescape off %}{{ a|urlize }}{% endautoescape %}', {"a": "<script>alert('foo')</script>"}, "<script>alert('foo')</script>"), 152 'filter-urlize06': testcase('{{ a|urlize }}', {"a": "<script>alert('foo')</script>"}, '<script>alert('foo')</script>'), 151 153 152 154 # mailto: testing for urlize 153 'filter-urlize07': ('{{ a|urlize }}', {"a": "Email me at me@example.com"}, 'Email me at <a href="mailto:me@example.com">me@example.com</a>'),154 'filter-urlize08': ('{{ a|urlize }}', {"a": "Email me at <me@example.com>"}, 'Email me at <<a href="mailto:me@example.com">me@example.com</a>>'),155 'filter-urlize07': testcase('{{ a|urlize }}', {"a": "Email me at me@example.com"}, 'Email me at <a href="mailto:me@example.com">me@example.com</a>'), 156 'filter-urlize08': testcase('{{ a|urlize }}', {"a": "Email me at <me@example.com>"}, 'Email me at <<a href="mailto:me@example.com">me@example.com</a>>'), 155 157 156 'filter-urlizetrunc01': ('{% autoescape off %}{{ a|urlizetrunc:"8" }} {{ b|urlizetrunc:"8" }}{% endautoescape %}', {"a": '"Unsafe" http://example.com/x=&y=', "b": mark_safe('"Safe" http://example.com?x=&y=')}, u'"Unsafe" <a href="http://example.com/x=&y=" rel="nofollow">http:...</a> "Safe" <a href="http://example.com?x=&y=" rel="nofollow">http:...</a>'),157 'filter-urlizetrunc02': ('{{ a|urlizetrunc:"8" }} {{ b|urlizetrunc:"8" }}', {"a": '"Unsafe" http://example.com/x=&y=', "b": mark_safe('"Safe" http://example.com?x=&y=')}, u'"Unsafe" <a href="http://example.com/x=&y=" rel="nofollow">http:...</a> "Safe" <a href="http://example.com?x=&y=" rel="nofollow">http:...</a>'),158 'filter-urlizetrunc01': testcase('{% autoescape off %}{{ a|urlizetrunc:"8" }} {{ b|urlizetrunc:"8" }}{% endautoescape %}', {"a": '"Unsafe" http://example.com/x=&y=', "b": mark_safe('"Safe" http://example.com?x=&y=')}, u'"Unsafe" <a href="http://example.com/x=&y=" rel="nofollow">http:...</a> "Safe" <a href="http://example.com?x=&y=" rel="nofollow">http:...</a>'), 159 'filter-urlizetrunc02': testcase('{{ a|urlizetrunc:"8" }} {{ b|urlizetrunc:"8" }}', {"a": '"Unsafe" http://example.com/x=&y=', "b": mark_safe('"Safe" http://example.com?x=&y=')}, u'"Unsafe" <a href="http://example.com/x=&y=" rel="nofollow">http:...</a> "Safe" <a href="http://example.com?x=&y=" rel="nofollow">http:...</a>'), 158 160 159 'filter-wordcount01': ('{% autoescape off %}{{ a|wordcount }} {{ b|wordcount }}{% endautoescape %}', {"a": "a & b", "b": mark_safe("a & b")}, "3 3"),160 'filter-wordcount02': ('{{ a|wordcount }} {{ b|wordcount }}', {"a": "a & b", "b": mark_safe("a & b")}, "3 3"),161 'filter-wordcount01': testcase('{% autoescape off %}{{ a|wordcount }} {{ b|wordcount }}{% endautoescape %}', {"a": "a & b", "b": mark_safe("a & b")}, "3 3"), 162 'filter-wordcount02': testcase('{{ a|wordcount }} {{ b|wordcount }}', {"a": "a & b", "b": mark_safe("a & b")}, "3 3"), 161 163 162 'filter-wordwrap01': ('{% autoescape off %}{{ a|wordwrap:"3" }} {{ b|wordwrap:"3" }}{% endautoescape %}', {"a": "a & b", "b": mark_safe("a & b")}, u"a &\nb a &\nb"),163 'filter-wordwrap02': ('{{ a|wordwrap:"3" }} {{ b|wordwrap:"3" }}', {"a": "a & b", "b": mark_safe("a & b")}, u"a &\nb a &\nb"),164 'filter-wordwrap01': testcase('{% autoescape off %}{{ a|wordwrap:"3" }} {{ b|wordwrap:"3" }}{% endautoescape %}', {"a": "a & b", "b": mark_safe("a & b")}, u"a &\nb a &\nb"), 165 'filter-wordwrap02': testcase('{{ a|wordwrap:"3" }} {{ b|wordwrap:"3" }}', {"a": "a & b", "b": mark_safe("a & b")}, u"a &\nb a &\nb"), 164 166 165 'filter-ljust01': ('{% autoescape off %}.{{ a|ljust:"5" }}. .{{ b|ljust:"5" }}.{% endautoescape %}', {"a": "a&b", "b": mark_safe("a&b")}, u".a&b . .a&b ."),166 'filter-ljust02': ('.{{ a|ljust:"5" }}. .{{ b|ljust:"5" }}.', {"a": "a&b", "b": mark_safe("a&b")}, u".a&b . .a&b ."),167 'filter-ljust01': testcase('{% autoescape off %}.{{ a|ljust:"5" }}. .{{ b|ljust:"5" }}.{% endautoescape %}', {"a": "a&b", "b": mark_safe("a&b")}, u".a&b . .a&b ."), 168 'filter-ljust02': testcase('.{{ a|ljust:"5" }}. .{{ b|ljust:"5" }}.', {"a": "a&b", "b": mark_safe("a&b")}, u".a&b . .a&b ."), 167 169 168 'filter-rjust01': ('{% autoescape off %}.{{ a|rjust:"5" }}. .{{ b|rjust:"5" }}.{% endautoescape %}', {"a": "a&b", "b": mark_safe("a&b")}, u". a&b. . a&b."),169 'filter-rjust02': ('.{{ a|rjust:"5" }}. .{{ b|rjust:"5" }}.', {"a": "a&b", "b": mark_safe("a&b")}, u". a&b. . a&b."),170 'filter-rjust01': testcase('{% autoescape off %}.{{ a|rjust:"5" }}. .{{ b|rjust:"5" }}.{% endautoescape %}', {"a": "a&b", "b": mark_safe("a&b")}, u". a&b. . a&b."), 171 'filter-rjust02': testcase('.{{ a|rjust:"5" }}. .{{ b|rjust:"5" }}.', {"a": "a&b", "b": mark_safe("a&b")}, u". a&b. . a&b."), 170 172 171 'filter-center01': ('{% autoescape off %}.{{ a|center:"5" }}. .{{ b|center:"5" }}.{% endautoescape %}', {"a": "a&b", "b": mark_safe("a&b")}, u". a&b . . a&b ."),172 'filter-center02': ('.{{ a|center:"5" }}. .{{ b|center:"5" }}.', {"a": "a&b", "b": mark_safe("a&b")}, u". a&b . . a&b ."),173 'filter-center01': testcase('{% autoescape off %}.{{ a|center:"5" }}. .{{ b|center:"5" }}.{% endautoescape %}', {"a": "a&b", "b": mark_safe("a&b")}, u". a&b . . a&b ."), 174 'filter-center02': testcase('.{{ a|center:"5" }}. .{{ b|center:"5" }}.', {"a": "a&b", "b": mark_safe("a&b")}, u". a&b . . a&b ."), 173 175 174 'filter-cut01': ('{% autoescape off %}{{ a|cut:"x" }} {{ b|cut:"x" }}{% endautoescape %}', {"a": "x&y", "b": mark_safe("x&y")}, u"&y &y"),175 'filter-cut02': ('{{ a|cut:"x" }} {{ b|cut:"x" }}', {"a": "x&y", "b": mark_safe("x&y")}, u"&y &y"),176 'filter-cut03': ('{% autoescape off %}{{ a|cut:"&" }} {{ b|cut:"&" }}{% endautoescape %}', {"a": "x&y", "b": mark_safe("x&y")}, u"xy xamp;y"),177 'filter-cut04': ('{{ a|cut:"&" }} {{ b|cut:"&" }}', {"a": "x&y", "b": mark_safe("x&y")}, u"xy xamp;y"),176 'filter-cut01': testcase('{% autoescape off %}{{ a|cut:"x" }} {{ b|cut:"x" }}{% endautoescape %}', {"a": "x&y", "b": mark_safe("x&y")}, u"&y &y"), 177 'filter-cut02': testcase('{{ a|cut:"x" }} {{ b|cut:"x" }}', {"a": "x&y", "b": mark_safe("x&y")}, u"&y &y"), 178 'filter-cut03': testcase('{% autoescape off %}{{ a|cut:"&" }} {{ b|cut:"&" }}{% endautoescape %}', {"a": "x&y", "b": mark_safe("x&y")}, u"xy xamp;y"), 179 'filter-cut04': testcase('{{ a|cut:"&" }} {{ b|cut:"&" }}', {"a": "x&y", "b": mark_safe("x&y")}, u"xy xamp;y"), 178 180 # Passing ';' to cut can break existing HTML entities, so those strings 179 181 # are auto-escaped. 180 'filter-cut05': ('{% autoescape off %}{{ a|cut:";" }} {{ b|cut:";" }}{% endautoescape %}', {"a": "x&y", "b": mark_safe("x&y")}, u"x&y x&y"),181 'filter-cut06': ('{{ a|cut:";" }} {{ b|cut:";" }}', {"a": "x&y", "b": mark_safe("x&y")}, u"x&y x&ampy"),182 'filter-cut05': testcase('{% autoescape off %}{{ a|cut:";" }} {{ b|cut:";" }}{% endautoescape %}', {"a": "x&y", "b": mark_safe("x&y")}, u"x&y x&y"), 183 'filter-cut06': testcase('{{ a|cut:";" }} {{ b|cut:";" }}', {"a": "x&y", "b": mark_safe("x&y")}, u"x&y x&ampy"), 182 184 183 185 # The "escape" filter works the same whether autoescape is on or off, 184 186 # but it has no effect on strings already marked as safe. 185 'filter-escape01': ('{{ a|escape }} {{ b|escape }}', {"a": "x&y", "b": mark_safe("x&y")}, u"x&y x&y"),186 'filter-escape02': ('{% autoescape off %}{{ a|escape }} {{ b|escape }}{% endautoescape %}', {"a": "x&y", "b": mark_safe("x&y")}, "x&y x&y"),187 'filter-escape01': testcase('{{ a|escape }} {{ b|escape }}', {"a": "x&y", "b": mark_safe("x&y")}, u"x&y x&y"), 188 'filter-escape02': testcase('{% autoescape off %}{{ a|escape }} {{ b|escape }}{% endautoescape %}', {"a": "x&y", "b": mark_safe("x&y")}, "x&y x&y"), 187 189 188 190 # It is only applied once, regardless of the number of times it 189 191 # appears in a chain. 190 'filter-escape03': ('{% autoescape off %}{{ a|escape|escape }}{% endautoescape %}', {"a": "x&y"}, u"x&y"),191 'filter-escape04': ('{{ a|escape|escape }}', {"a": "x&y"}, u"x&y"),192 'filter-escape03': testcase('{% autoescape off %}{{ a|escape|escape }}{% endautoescape %}', {"a": "x&y"}, u"x&y"), 193 'filter-escape04': testcase('{{ a|escape|escape }}', {"a": "x&y"}, u"x&y"), 192 194 193 195 # Force_escape is applied immediately. It can be used to provide 194 196 # double-escaping, for example. 195 'filter-force-escape01': ('{% autoescape off %}{{ a|force_escape }}{% endautoescape %}', {"a": "x&y"}, u"x&y"),196 'filter-force-escape02': ('{{ a|force_escape }}', {"a": "x&y"}, u"x&y"),197 'filter-force-escape03': ('{% autoescape off %}{{ a|force_escape|force_escape }}{% endautoescape %}', {"a": "x&y"}, u"x&amp;y"),198 'filter-force-escape04': ('{{ a|force_escape|force_escape }}', {"a": "x&y"}, u"x&amp;y"),197 'filter-force-escape01': testcase('{% autoescape off %}{{ a|force_escape }}{% endautoescape %}', {"a": "x&y"}, u"x&y"), 198 'filter-force-escape02': testcase('{{ a|force_escape }}', {"a": "x&y"}, u"x&y"), 199 'filter-force-escape03': testcase('{% autoescape off %}{{ a|force_escape|force_escape }}{% endautoescape %}', {"a": "x&y"}, u"x&amp;y"), 200 'filter-force-escape04': testcase('{{ a|force_escape|force_escape }}', {"a": "x&y"}, u"x&amp;y"), 199 201 200 202 # Because the result of force_escape is "safe", an additional 201 203 # escape filter has no effect. 202 'filter-force-escape05': ('{% autoescape off %}{{ a|force_escape|escape }}{% endautoescape %}', {"a": "x&y"}, u"x&y"),203 'filter-force-escape06': ('{{ a|force_escape|escape }}', {"a": "x&y"}, u"x&y"),204 'filter-force-escape07': ('{% autoescape off %}{{ a|escape|force_escape }}{% endautoescape %}', {"a": "x&y"}, u"x&y"),205 'filter-force-escape08': ('{{ a|escape|force_escape }}', {"a": "x&y"}, u"x&y"),204 'filter-force-escape05': testcase('{% autoescape off %}{{ a|force_escape|escape }}{% endautoescape %}', {"a": "x&y"}, u"x&y"), 205 'filter-force-escape06': testcase('{{ a|force_escape|escape }}', {"a": "x&y"}, u"x&y"), 206 'filter-force-escape07': testcase('{% autoescape off %}{{ a|escape|force_escape }}{% endautoescape %}', {"a": "x&y"}, u"x&y"), 207 'filter-force-escape08': testcase('{{ a|escape|force_escape }}', {"a": "x&y"}, u"x&y"), 206 208 207 209 # The contents in "linebreaks" and "linebreaksbr" are escaped 208 210 # according to the current autoescape setting. 209 'filter-linebreaks01': ('{{ a|linebreaks }} {{ b|linebreaks }}', {"a": "x&\ny", "b": mark_safe("x&\ny")}, u"<p>x&<br />y</p> <p>x&<br />y</p>"),210 'filter-linebreaks02': ('{% autoescape off %}{{ a|linebreaks }} {{ b|linebreaks }}{% endautoescape %}', {"a": "x&\ny", "b": mark_safe("x&\ny")}, u"<p>x&<br />y</p> <p>x&<br />y</p>"),211 'filter-linebreaks01': testcase('{{ a|linebreaks }} {{ b|linebreaks }}', {"a": "x&\ny", "b": mark_safe("x&\ny")}, u"<p>x&<br />y</p> <p>x&<br />y</p>"), 212 'filter-linebreaks02': testcase('{% autoescape off %}{{ a|linebreaks }} {{ b|linebreaks }}{% endautoescape %}', {"a": "x&\ny", "b": mark_safe("x&\ny")}, u"<p>x&<br />y</p> <p>x&<br />y</p>"), 211 213 212 'filter-linebreaksbr01': ('{{ a|linebreaksbr }} {{ b|linebreaksbr }}', {"a": "x&\ny", "b": mark_safe("x&\ny")}, u"x&<br />y x&<br />y"),213 'filter-linebreaksbr02': ('{% autoescape off %}{{ a|linebreaksbr }} {{ b|linebreaksbr }}{% endautoescape %}', {"a": "x&\ny", "b": mark_safe("x&\ny")}, u"x&<br />y x&<br />y"),214 'filter-linebreaksbr01': testcase('{{ a|linebreaksbr }} {{ b|linebreaksbr }}', {"a": "x&\ny", "b": mark_safe("x&\ny")}, u"x&<br />y x&<br />y"), 215 'filter-linebreaksbr02': testcase('{% autoescape off %}{{ a|linebreaksbr }} {{ b|linebreaksbr }}{% endautoescape %}', {"a": "x&\ny", "b": mark_safe("x&\ny")}, u"x&<br />y x&<br />y"), 214 216 215 'filter-safe01': ("{{ a }} -- {{ a|safe }}", {"a": u"<b>hello</b>"}, "<b>hello</b> -- <b>hello</b>"),216 'filter-safe02': ("{% autoescape off %}{{ a }} -- {{ a|safe }}{% endautoescape %}", {"a": "<b>hello</b>"}, u"<b>hello</b> -- <b>hello</b>"),217 'filter-safe01': testcase("{{ a }} -- {{ a|safe }}", {"a": u"<b>hello</b>"}, "<b>hello</b> -- <b>hello</b>"), 218 'filter-safe02': testcase("{% autoescape off %}{{ a }} -- {{ a|safe }}{% endautoescape %}", {"a": "<b>hello</b>"}, u"<b>hello</b> -- <b>hello</b>"), 217 219 218 'filter-safeseq01': ('{{ a|join:", " }} -- {{ a|safeseq|join:", " }}', {"a": ["&", "<"]}, "&, < -- &, <"),219 'filter-safeseq02': ('{% autoescape off %}{{ a|join:", " }} -- {{ a|safeseq|join:", " }}{% endautoescape %}', {"a": ["&", "<"]}, "&, < -- &, <"),220 'filter-safeseq01': testcase('{{ a|join:", " }} -- {{ a|safeseq|join:", " }}', {"a": ["&", "<"]}, "&, < -- &, <"), 221 'filter-safeseq02': testcase('{% autoescape off %}{{ a|join:", " }} -- {{ a|safeseq|join:", " }}{% endautoescape %}', {"a": ["&", "<"]}, "&, < -- &, <"), 220 222 221 'filter-removetags01': ('{{ a|removetags:"a b" }} {{ b|removetags:"a b" }}', {"a": "<a>x</a> <p><b>y</b></p>", "b": mark_safe("<a>x</a> <p><b>y</b></p>")}, u"x <p>y</p> x <p>y</p>"),222 'filter-removetags02': ('{% autoescape off %}{{ a|removetags:"a b" }} {{ b|removetags:"a b" }}{% endautoescape %}', {"a": "<a>x</a> <p><b>y</b></p>", "b": mark_safe("<a>x</a> <p><b>y</b></p>")}, u"x <p>y</p> x <p>y</p>"),223 'filter-removetags01': testcase('{{ a|removetags:"a b" }} {{ b|removetags:"a b" }}', {"a": "<a>x</a> <p><b>y</b></p>", "b": mark_safe("<a>x</a> <p><b>y</b></p>")}, u"x <p>y</p> x <p>y</p>"), 224 'filter-removetags02': testcase('{% autoescape off %}{{ a|removetags:"a b" }} {{ b|removetags:"a b" }}{% endautoescape %}', {"a": "<a>x</a> <p><b>y</b></p>", "b": mark_safe("<a>x</a> <p><b>y</b></p>")}, u"x <p>y</p> x <p>y</p>"), 223 225 224 'filter-striptags01': ('{{ a|striptags }} {{ b|striptags }}', {"a": "<a>x</a> <p><b>y</b></p>", "b": mark_safe("<a>x</a> <p><b>y</b></p>")}, "x y x y"),225 'filter-striptags02': ('{% autoescape off %}{{ a|striptags }} {{ b|striptags }}{% endautoescape %}', {"a": "<a>x</a> <p><b>y</b></p>", "b": mark_safe("<a>x</a> <p><b>y</b></p>")}, "x y x y"),226 'filter-striptags01': testcase('{{ a|striptags }} {{ b|striptags }}', {"a": "<a>x</a> <p><b>y</b></p>", "b": mark_safe("<a>x</a> <p><b>y</b></p>")}, "x y x y"), 227 'filter-striptags02': testcase('{% autoescape off %}{{ a|striptags }} {{ b|striptags }}{% endautoescape %}', {"a": "<a>x</a> <p><b>y</b></p>", "b": mark_safe("<a>x</a> <p><b>y</b></p>")}, "x y x y"), 226 228 227 'filter-first01': ('{{ a|first }} {{ b|first }}', {"a": ["a&b", "x"], "b": [mark_safe("a&b"), "x"]}, "a&b a&b"),228 'filter-first02': ('{% autoescape off %}{{ a|first }} {{ b|first }}{% endautoescape %}', {"a": ["a&b", "x"], "b": [mark_safe("a&b"), "x"]}, "a&b a&b"),229 'filter-first01': testcase('{{ a|first }} {{ b|first }}', {"a": ["a&b", "x"], "b": [mark_safe("a&b"), "x"]}, "a&b a&b"), 230 'filter-first02': testcase('{% autoescape off %}{{ a|first }} {{ b|first }}{% endautoescape %}', {"a": ["a&b", "x"], "b": [mark_safe("a&b"), "x"]}, "a&b a&b"), 229 231 230 'filter-last01': ('{{ a|last }} {{ b|last }}', {"a": ["x", "a&b"], "b": ["x", mark_safe("a&b")]}, "a&b a&b"),231 'filter-last02': ('{% autoescape off %}{{ a|last }} {{ b|last }}{% endautoescape %}', {"a": ["x", "a&b"], "b": ["x", mark_safe("a&b")]}, "a&b a&b"),232 'filter-last01': testcase('{{ a|last }} {{ b|last }}', {"a": ["x", "a&b"], "b": ["x", mark_safe("a&b")]}, "a&b a&b"), 233 'filter-last02': testcase('{% autoescape off %}{{ a|last }} {{ b|last }}{% endautoescape %}', {"a": ["x", "a&b"], "b": ["x", mark_safe("a&b")]}, "a&b a&b"), 232 234 233 'filter-random01': ('{{ a|random }} {{ b|random }}', {"a": ["a&b", "a&b"], "b": [mark_safe("a&b"), mark_safe("a&b")]}, "a&b a&b"),234 'filter-random02': ('{% autoescape off %}{{ a|random }} {{ b|random }}{% endautoescape %}', {"a": ["a&b", "a&b"], "b": [mark_safe("a&b"), mark_safe("a&b")]}, "a&b a&b"),235 'filter-random01': testcase('{{ a|random }} {{ b|random }}', {"a": ["a&b", "a&b"], "b": [mark_safe("a&b"), mark_safe("a&b")]}, "a&b a&b"), 236 'filter-random02': testcase('{% autoescape off %}{{ a|random }} {{ b|random }}{% endautoescape %}', {"a": ["a&b", "a&b"], "b": [mark_safe("a&b"), mark_safe("a&b")]}, "a&b a&b"), 235 237 236 'filter-slice01': ('{{ a|slice:"1:3" }} {{ b|slice:"1:3" }}', {"a": "a&b", "b": mark_safe("a&b")}, "&b &b"),237 'filter-slice02': ('{% autoescape off %}{{ a|slice:"1:3" }} {{ b|slice:"1:3" }}{% endautoescape %}', {"a": "a&b", "b": mark_safe("a&b")}, "&b &b"),238 'filter-slice01': testcase('{{ a|slice:"1:3" }} {{ b|slice:"1:3" }}', {"a": "a&b", "b": mark_safe("a&b")}, "&b &b"), 239 'filter-slice02': testcase('{% autoescape off %}{{ a|slice:"1:3" }} {{ b|slice:"1:3" }}{% endautoescape %}', {"a": "a&b", "b": mark_safe("a&b")}, "&b &b"), 238 240 239 'filter-unordered_list01': ('{{ a|unordered_list }}', {"a": ["x>", [["<y", []]]]}, "\t<li>x>\n\t<ul>\n\t\t<li><y</li>\n\t</ul>\n\t</li>"),240 'filter-unordered_list02': ('{% autoescape off %}{{ a|unordered_list }}{% endautoescape %}', {"a": ["x>", [["<y", []]]]}, "\t<li>x>\n\t<ul>\n\t\t<li><y</li>\n\t</ul>\n\t</li>"),241 'filter-unordered_list03': ('{{ a|unordered_list }}', {"a": ["x>", [[mark_safe("<y"), []]]]}, "\t<li>x>\n\t<ul>\n\t\t<li><y</li>\n\t</ul>\n\t</li>"),242 'filter-unordered_list04': ('{% autoescape off %}{{ a|unordered_list }}{% endautoescape %}', {"a": ["x>", [[mark_safe("<y"), []]]]}, "\t<li>x>\n\t<ul>\n\t\t<li><y</li>\n\t</ul>\n\t</li>"),243 'filter-unordered_list05': ('{% autoescape off %}{{ a|unordered_list }}{% endautoescape %}', {"a": ["x>", [["<y", []]]]}, "\t<li>x>\n\t<ul>\n\t\t<li><y</li>\n\t</ul>\n\t</li>"),241 'filter-unordered_list01': testcase('{{ a|unordered_list }}', {"a": ["x>", [["<y", []]]]}, "\t<li>x>\n\t<ul>\n\t\t<li><y</li>\n\t</ul>\n\t</li>"), 242 'filter-unordered_list02': testcase('{% autoescape off %}{{ a|unordered_list }}{% endautoescape %}', {"a": ["x>", [["<y", []]]]}, "\t<li>x>\n\t<ul>\n\t\t<li><y</li>\n\t</ul>\n\t</li>"), 243 'filter-unordered_list03': testcase('{{ a|unordered_list }}', {"a": ["x>", [[mark_safe("<y"), []]]]}, "\t<li>x>\n\t<ul>\n\t\t<li><y</li>\n\t</ul>\n\t</li>"), 244 'filter-unordered_list04': testcase('{% autoescape off %}{{ a|unordered_list }}{% endautoescape %}', {"a": ["x>", [[mark_safe("<y"), []]]]}, "\t<li>x>\n\t<ul>\n\t\t<li><y</li>\n\t</ul>\n\t</li>"), 245 'filter-unordered_list05': testcase('{% autoescape off %}{{ a|unordered_list }}{% endautoescape %}', {"a": ["x>", [["<y", []]]]}, "\t<li>x>\n\t<ul>\n\t\t<li><y</li>\n\t</ul>\n\t</li>"), 244 246 245 247 # Literal string arguments to the default filter are always treated as 246 248 # safe strings, regardless of the auto-escaping state. 247 249 # 248 250 # Note: we have to use {"a": ""} here, otherwise the invalid template 249 251 # variable string interferes with the test result. 250 'filter-default01': ('{{ a|default:"x<" }}', {"a": ""}, "x<"),251 'filter-default02': ('{% autoescape off %}{{ a|default:"x<" }}{% endautoescape %}', {"a": ""}, "x<"),252 'filter-default03': ('{{ a|default:"x<" }}', {"a": mark_safe("x>")}, "x>"),253 'filter-default04': ('{% autoescape off %}{{ a|default:"x<" }}{% endautoescape %}', {"a": mark_safe("x>")}, "x>"),252 'filter-default01': testcase('{{ a|default:"x<" }}', {"a": ""}, "x<"), 253 'filter-default02': testcase('{% autoescape off %}{{ a|default:"x<" }}{% endautoescape %}', {"a": ""}, "x<"), 254 'filter-default03': testcase('{{ a|default:"x<" }}', {"a": mark_safe("x>")}, "x>"), 255 'filter-default04': testcase('{% autoescape off %}{{ a|default:"x<" }}{% endautoescape %}', {"a": mark_safe("x>")}, "x>"), 254 256 255 'filter-default_if_none01': ('{{ a|default:"x<" }}', {"a": None}, "x<"),256 'filter-default_if_none02': ('{% autoescape off %}{{ a|default:"x<" }}{% endautoescape %}', {"a": None}, "x<"),257 'filter-default_if_none01': testcase('{{ a|default:"x<" }}', {"a": None}, "x<"), 258 'filter-default_if_none02': testcase('{% autoescape off %}{{ a|default:"x<" }}{% endautoescape %}', {"a": None}, "x<"), 257 259 258 'filter-phone2numeric01': ('{{ a|phone2numeric }} {{ b|phone2numeric }}', {"a": "<1-800-call-me>", "b": mark_safe("<1-800-call-me>") }, "<1-800-2255-63> <1-800-2255-63>"),259 'filter-phone2numeric02': ('{% autoescape off %}{{ a|phone2numeric }} {{ b|phone2numeric }}{% endautoescape %}', {"a": "<1-800-call-me>", "b": mark_safe("<1-800-call-me>") }, "<1-800-2255-63> <1-800-2255-63>"),260 'filter-phone2numeric03': ('{{ a|phone2numeric }}', {"a": "How razorback-jumping frogs can level six piqued gymnasts!"}, "469 729672225-5867464 37647 226 53835 749 747833 49662787!"),260 'filter-phone2numeric01': testcase('{{ a|phone2numeric }} {{ b|phone2numeric }}', {"a": "<1-800-call-me>", "b": mark_safe("<1-800-call-me>") }, "<1-800-2255-63> <1-800-2255-63>"), 261 'filter-phone2numeric02': testcase('{% autoescape off %}{{ a|phone2numeric }} {{ b|phone2numeric }}{% endautoescape %}', {"a": "<1-800-call-me>", "b": mark_safe("<1-800-call-me>") }, "<1-800-2255-63> <1-800-2255-63>"), 262 'filter-phone2numeric03': testcase('{{ a|phone2numeric }}', {"a": "How razorback-jumping frogs can level six piqued gymnasts!"}, "469 729672225-5867464 37647 226 53835 749 747833 49662787!"), 261 263 262 264 # Ensure iriencode keeps safe strings: 263 'filter-iriencode01': ('{{ url|iriencode }}', {'url': '?test=1&me=2'}, '?test=1&me=2'),264 'filter-iriencode02': ('{% autoescape off %}{{ url|iriencode }}{% endautoescape %}', {'url': '?test=1&me=2'}, '?test=1&me=2'),265 'filter-iriencode03': ('{{ url|iriencode }}', {'url': mark_safe('?test=1&me=2')}, '?test=1&me=2'),266 'filter-iriencode04': ('{% autoescape off %}{{ url|iriencode }}{% endautoescape %}', {'url': mark_safe('?test=1&me=2')}, '?test=1&me=2'),265 'filter-iriencode01': testcase('{{ url|iriencode }}', {'url': '?test=1&me=2'}, '?test=1&me=2'), 266 'filter-iriencode02': testcase('{% autoescape off %}{{ url|iriencode }}{% endautoescape %}', {'url': '?test=1&me=2'}, '?test=1&me=2'), 267 'filter-iriencode03': testcase('{{ url|iriencode }}', {'url': mark_safe('?test=1&me=2')}, '?test=1&me=2'), 268 'filter-iriencode04': testcase('{% autoescape off %}{{ url|iriencode }}{% endautoescape %}', {'url': mark_safe('?test=1&me=2')}, '?test=1&me=2'), 267 269 268 270 # urlencode 269 'filter-urlencode01': ('{{ url|urlencode }}', {'url': '/test&"/me?/'}, '/test%26%22/me%3F/'),270 'filter-urlencode02': ('/test/{{ urlbit|urlencode:"" }}/', {'urlbit': 'escape/slash'}, '/test/escape%2Fslash/'),271 'filter-urlencode01': testcase('{{ url|urlencode }}', {'url': '/test&"/me?/'}, '/test%26%22/me%3F/'), 272 'filter-urlencode02': testcase('/test/{{ urlbit|urlencode:"" }}/', {'urlbit': 'escape/slash'}, '/test/escape%2Fslash/'), 271 273 272 274 # Chaining a bunch of safeness-preserving filters should not alter 273 275 # the safe status either way. 274 'chaining01': ('{{ a|capfirst|center:"7" }}.{{ b|capfirst|center:"7" }}', {"a": "a < b", "b": mark_safe("a < b")}, " A < b . A < b "),275 'chaining02': ('{% autoescape off %}{{ a|capfirst|center:"7" }}.{{ b|capfirst|center:"7" }}{% endautoescape %}', {"a": "a < b", "b": mark_safe("a < b")}, " A < b . A < b "),276 'chaining01': testcase('{{ a|capfirst|center:"7" }}.{{ b|capfirst|center:"7" }}', {"a": "a < b", "b": mark_safe("a < b")}, " A < b . A < b "), 277 'chaining02': testcase('{% autoescape off %}{{ a|capfirst|center:"7" }}.{{ b|capfirst|center:"7" }}{% endautoescape %}', {"a": "a < b", "b": mark_safe("a < b")}, " A < b . A < b "), 276 278 277 279 # Using a filter that forces a string back to unsafe: 278 'chaining03': ('{{ a|cut:"b"|capfirst }}.{{ b|cut:"b"|capfirst }}', {"a": "a < b", "b": mark_safe("a < b")}, "A < .A < "),279 'chaining04': ('{% autoescape off %}{{ a|cut:"b"|capfirst }}.{{ b|cut:"b"|capfirst }}{% endautoescape %}', {"a": "a < b", "b": mark_safe("a < b")}, "A < .A < "),280 'chaining03': testcase('{{ a|cut:"b"|capfirst }}.{{ b|cut:"b"|capfirst }}', {"a": "a < b", "b": mark_safe("a < b")}, "A < .A < "), 281 'chaining04': testcase('{% autoescape off %}{{ a|cut:"b"|capfirst }}.{{ b|cut:"b"|capfirst }}{% endautoescape %}', {"a": "a < b", "b": mark_safe("a < b")}, "A < .A < "), 280 282 281 283 # Using a filter that forces safeness does not lead to double-escaping 282 'chaining05': ('{{ a|escape|capfirst }}', {"a": "a < b"}, "A < b"),283 'chaining06': ('{% autoescape off %}{{ a|escape|capfirst }}{% endautoescape %}', {"a": "a < b"}, "A < b"),284 'chaining05': testcase('{{ a|escape|capfirst }}', {"a": "a < b"}, "A < b"), 285 'chaining06': testcase('{% autoescape off %}{{ a|escape|capfirst }}{% endautoescape %}', {"a": "a < b"}, "A < b"), 284 286 285 287 # Force to safe, then back (also showing why using force_escape too 286 288 # early in a chain can lead to unexpected results). 287 'chaining07': ('{{ a|force_escape|cut:";" }}', {"a": "a < b"}, "a &lt b"),288 'chaining08': ('{% autoescape off %}{{ a|force_escape|cut:";" }}{% endautoescape %}', {"a": "a < b"}, "a < b"),289 'chaining09': ('{{ a|cut:";"|force_escape }}', {"a": "a < b"}, "a < b"),290 'chaining10': ('{% autoescape off %}{{ a|cut:";"|force_escape }}{% endautoescape %}', {"a": "a < b"}, "a < b"),291 'chaining11': ('{{ a|cut:"b"|safe }}', {"a": "a < b"}, "a < "),292 'chaining12': ('{% autoescape off %}{{ a|cut:"b"|safe }}{% endautoescape %}', {"a": "a < b"}, "a < "),293 'chaining13': ('{{ a|safe|force_escape }}', {"a": "a < b"}, "a < b"),294 'chaining14': ('{% autoescape off %}{{ a|safe|force_escape }}{% endautoescape %}', {"a": "a < b"}, "a < b"),289 'chaining07': testcase('{{ a|force_escape|cut:";" }}', {"a": "a < b"}, "a &lt b"), 290 'chaining08': testcase('{% autoescape off %}{{ a|force_escape|cut:";" }}{% endautoescape %}', {"a": "a < b"}, "a < b"), 291 'chaining09': testcase('{{ a|cut:";"|force_escape }}', {"a": "a < b"}, "a < b"), 292 'chaining10': testcase('{% autoescape off %}{{ a|cut:";"|force_escape }}{% endautoescape %}', {"a": "a < b"}, "a < b"), 293 'chaining11': testcase('{{ a|cut:"b"|safe }}', {"a": "a < b"}, "a < "), 294 'chaining12': testcase('{% autoescape off %}{{ a|cut:"b"|safe }}{% endautoescape %}', {"a": "a < b"}, "a < "), 295 'chaining13': testcase('{{ a|safe|force_escape }}', {"a": "a < b"}, "a < b"), 296 'chaining14': testcase('{% autoescape off %}{{ a|safe|force_escape }}{% endautoescape %}', {"a": "a < b"}, "a < b"), 295 297 296 298 # Filters decorated with stringfilter still respect is_safe. 297 'autoescape-stringfilter01': (r'{{ unsafe|capfirst }}', {'unsafe': UnsafeClass()}, 'You & me'),298 'autoescape-stringfilter02': (r'{% autoescape off %}{{ unsafe|capfirst }}{% endautoescape %}', {'unsafe': UnsafeClass()}, 'You & me'),299 'autoescape-stringfilter03': (r'{{ safe|capfirst }}', {'safe': SafeClass()}, 'You > me'),300 'autoescape-stringfilter04': (r'{% autoescape off %}{{ safe|capfirst }}{% endautoescape %}', {'safe': SafeClass()}, 'You > me'),299 'autoescape-stringfilter01': testcase(r'{{ unsafe|capfirst }}', {'unsafe': UnsafeClass()}, 'You & me'), 300 'autoescape-stringfilter02': testcase(r'{% autoescape off %}{{ unsafe|capfirst }}{% endautoescape %}', {'unsafe': UnsafeClass()}, 'You & me'), 301 'autoescape-stringfilter03': testcase(r'{{ safe|capfirst }}', {'safe': SafeClass()}, 'You > me'), 302 'autoescape-stringfilter04': testcase(r'{% autoescape off %}{{ safe|capfirst }}{% endautoescape %}', {'safe': SafeClass()}, 'You > me'), 301 303 302 'escapejs01': (r'{{ a|escapejs }}', {'a': 'testing\r\njavascript \'string" <b>escaping</b>'}, 'testing\\u000D\\u000Ajavascript \\u0027string\\u0022 \\u003Cb\\u003Eescaping\\u003C/b\\u003E'),303 'escapejs02': (r'{% autoescape off %}{{ a|escapejs }}{% endautoescape %}', {'a': 'testing\r\njavascript \'string" <b>escaping</b>'}, 'testing\\u000D\\u000Ajavascript \\u0027string\\u0022 \\u003Cb\\u003Eescaping\\u003C/b\\u003E'),304 'escapejs01': testcase(r'{{ a|escapejs }}', {'a': 'testing\r\njavascript \'string" <b>escaping</b>'}, 'testing\\u000D\\u000Ajavascript \\u0027string\\u0022 \\u003Cb\\u003Eescaping\\u003C/b\\u003E'), 305 'escapejs02': testcase(r'{% autoescape off %}{{ a|escapejs }}{% endautoescape %}', {'a': 'testing\r\njavascript \'string" <b>escaping</b>'}, 'testing\\u000D\\u000Ajavascript \\u0027string\\u0022 \\u003Cb\\u003Eescaping\\u003C/b\\u003E'), 304 306 305 307 306 308 # length filter. 307 'length01': ('{{ list|length }}', {'list': ['4', None, True, {}]}, '4'),308 'length02': ('{{ list|length }}', {'list': []}, '0'),309 'length03': ('{{ string|length }}', {'string': ''}, '0'),310 'length04': ('{{ string|length }}', {'string': 'django'}, '6'),309 'length01': testcase('{{ list|length }}', {'list': ['4', None, True, {}]}, '4'), 310 'length02': testcase('{{ list|length }}', {'list': []}, '0'), 311 'length03': testcase('{{ string|length }}', {'string': ''}, '0'), 312 'length04': testcase('{{ string|length }}', {'string': 'django'}, '6'), 311 313 # Invalid uses that should fail silently. 312 'length05': ('{{ int|length }}', {'int': 7}, ''),313 'length06': ('{{ None|length }}', {'None': None}, ''),314 'length05': testcase('{{ int|length }}', {'int': 7}, ''), 315 'length06': testcase('{{ None|length }}', {'None': None}, ''), 314 316 315 317 # length_is filter. 316 'length_is01': ('{% if some_list|length_is:"4" %}Four{% endif %}', {'some_list': ['4', None, True, {}]}, 'Four'),317 'length_is02': ('{% if some_list|length_is:"4" %}Four{% else %}Not Four{% endif %}', {'some_list': ['4', None, True, {}, 17]}, 'Not Four'),318 'length_is03': ('{% if mystring|length_is:"4" %}Four{% endif %}', {'mystring': 'word'}, 'Four'),319 'length_is04': ('{% if mystring|length_is:"4" %}Four{% else %}Not Four{% endif %}', {'mystring': 'Python'}, 'Not Four'),320 'length_is05': ('{% if mystring|length_is:"4" %}Four{% else %}Not Four{% endif %}', {'mystring': ''}, 'Not Four'),321 'length_is06': ('{% with var|length as my_length %}{{ my_length }}{% endwith %}', {'var': 'django'}, '6'),318 'length_is01': testcase('{% if some_list|length_is:"4" %}Four{% endif %}', {'some_list': ['4', None, True, {}]}, 'Four'), 319 'length_is02': testcase('{% if some_list|length_is:"4" %}Four{% else %}Not Four{% endif %}', {'some_list': ['4', None, True, {}, 17]}, 'Not Four'), 320 'length_is03': testcase('{% if mystring|length_is:"4" %}Four{% endif %}', {'mystring': 'word'}, 'Four'), 321 'length_is04': testcase('{% if mystring|length_is:"4" %}Four{% else %}Not Four{% endif %}', {'mystring': 'Python'}, 'Not Four'), 322 'length_is05': testcase('{% if mystring|length_is:"4" %}Four{% else %}Not Four{% endif %}', {'mystring': ''}, 'Not Four'), 323 'length_is06': testcase('{% with var|length as my_length %}{{ my_length }}{% endwith %}', {'var': 'django'}, '6'), 322 324 # Boolean return value from length_is should not be coerced to a string 323 'length_is07': (r'{% if "X"|length_is:0 %}Length is 0{% else %}Length not 0{% endif %}', {}, 'Length not 0'),324 'length_is08': (r'{% if "X"|length_is:1 %}Length is 1{% else %}Length not 1{% endif %}', {}, 'Length is 1'),325 'length_is07': testcase(r'{% if "X"|length_is:0 %}Length is 0{% else %}Length not 0{% endif %}', {}, 'Length not 0'), 326 'length_is08': testcase(r'{% if "X"|length_is:1 %}Length is 1{% else %}Length not 1{% endif %}', {}, 'Length is 1'), 325 327 # Invalid uses that should fail silently. 326 'length_is09': ('{{ var|length_is:"fish" }}', {'var': 'django'}, ''),327 'length_is10': ('{{ int|length_is:"1" }}', {'int': 7}, ''),328 'length_is11': ('{{ none|length_is:"1" }}', {'none': None}, ''),328 'length_is09': testcase('{{ var|length_is:"fish" }}', {'var': 'django'}, ''), 329 'length_is10': testcase('{{ int|length_is:"1" }}', {'int': 7}, ''), 330 'length_is11': testcase('{{ none|length_is:"1" }}', {'none': None}, ''), 329 331 330 'join01': (r'{{ a|join:", " }}', {'a': ['alpha', 'beta & me']}, 'alpha, beta & me'),331 'join02': (r'{% autoescape off %}{{ a|join:", " }}{% endautoescape %}', {'a': ['alpha', 'beta & me']}, 'alpha, beta & me'),332 'join03': (r'{{ a|join:" & " }}', {'a': ['alpha', 'beta & me']}, 'alpha & beta & me'),333 'join04': (r'{% autoescape off %}{{ a|join:" & " }}{% endautoescape %}', {'a': ['alpha', 'beta & me']}, 'alpha & beta & me'),332 'join01': testcase(r'{{ a|join:", " }}', {'a': ['alpha', 'beta & me']}, 'alpha, beta & me'), 333 'join02': testcase(r'{% autoescape off %}{{ a|join:", " }}{% endautoescape %}', {'a': ['alpha', 'beta & me']}, 'alpha, beta & me'), 334 'join03': testcase(r'{{ a|join:" & " }}', {'a': ['alpha', 'beta & me']}, 'alpha & beta & me'), 335 'join04': testcase(r'{% autoescape off %}{{ a|join:" & " }}{% endautoescape %}', {'a': ['alpha', 'beta & me']}, 'alpha & beta & me'), 334 336 335 337 # Test that joining with unsafe joiners don't result in unsafe strings (#11377) 336 'join05': (r'{{ a|join:var }}', {'a': ['alpha', 'beta & me'], 'var': ' & '}, 'alpha & beta & me'),337 'join06': (r'{{ a|join:var }}', {'a': ['alpha', 'beta & me'], 'var': mark_safe(' & ')}, 'alpha & beta & me'),338 'join07': (r'{{ a|join:var|lower }}', {'a': ['Alpha', 'Beta & me'], 'var': ' & ' }, 'alpha & beta & me'),339 'join08': (r'{{ a|join:var|lower }}', {'a': ['Alpha', 'Beta & me'], 'var': mark_safe(' & ')}, 'alpha & beta & me'),338 'join05': testcase(r'{{ a|join:var }}', {'a': ['alpha', 'beta & me'], 'var': ' & '}, 'alpha & beta & me'), 339 'join06': testcase(r'{{ a|join:var }}', {'a': ['alpha', 'beta & me'], 'var': mark_safe(' & ')}, 'alpha & beta & me'), 340 'join07': testcase(r'{{ a|join:var|lower }}', {'a': ['Alpha', 'Beta & me'], 'var': ' & ' }, 'alpha & beta & me'), 341 'join08': testcase(r'{{ a|join:var|lower }}', {'a': ['Alpha', 'Beta & me'], 'var': mark_safe(' & ')}, 'alpha & beta & me'), 340 342 341 'date01': (r'{{ d|date:"m" }}', {'d': datetime(2008, 1, 1)}, '01'),342 'date02': (r'{{ d|date }}', {'d': datetime(2008, 1, 1)}, 'Jan. 1, 2008'),343 'date01': testcase(r'{{ d|date:"m" }}', {'d': datetime(2008, 1, 1)}, '01'), 344 'date02': testcase(r'{{ d|date }}', {'d': datetime(2008, 1, 1)}, 'Jan. 1, 2008'), 343 345 #Ticket 9520: Make sure |date doesn't blow up on non-dates 344 'date03': (r'{{ d|date:"m" }}', {'d': 'fail_string'}, ''),346 'date03': testcase(r'{{ d|date:"m" }}', {'d': 'fail_string'}, ''), 345 347 346 348 # Tests for #11687 347 'add01': (r'{{ i|add:"5" }}', {'i': 2000}, '2005'),348 'add02': (r'{{ i|add:"napis" }}', {'i': 2000}, '2000'),349 'add03': (r'{{ i|add:16 }}', {'i': 'not_an_int'}, 'not_an_int'),350 'add04': (r'{{ i|add:"16" }}', {'i': 'not_an_int'}, 'not_an_int16'),351 'add05': (r'{{ l1|add:l2 }}', {'l1': [1, 2], 'l2': [3, 4]}, '[1, 2, 3, 4]'),352 'add06': (r'{{ t1|add:t2 }}', {'t1': (3, 4), 't2': (1, 2)}, '(3, 4, 1, 2)'),353 'add07': (r'{{ d|add:t }}', {'d': date(2000, 1, 1), 't': timedelta(10)}, 'Jan. 11, 2000'),349 'add01': testcase(r'{{ i|add:"5" }}', {'i': 2000}, '2005'), 350 'add02': testcase(r'{{ i|add:"napis" }}', {'i': 2000}, '2000'), 351 'add03': testcase(r'{{ i|add:16 }}', {'i': 'not_an_int'}, 'not_an_int'), 352 'add04': testcase(r'{{ i|add:"16" }}', {'i': 'not_an_int'}, 'not_an_int16'), 353 'add05': testcase(r'{{ l1|add:l2 }}', {'l1': [1, 2], 'l2': [3, 4]}, '[1, 2, 3, 4]'), 354 'add06': testcase(r'{{ t1|add:t2 }}', {'t1': (3, 4), 't2': (1, 2)}, '(3, 4, 1, 2)'), 355 'add07': testcase(r'{{ d|add:t }}', {'d': date(2000, 1, 1), 't': timedelta(10)}, 'Jan. 11, 2000'), 354 356 } -
tests/runtests.py
1 1 #!/usr/bin/env python 2 2 import os, subprocess, sys, traceback 3 sys.path.insert(0, os.path.abspath(os.path.join(__file__, "../.."))) 3 4 4 5 import django.contrib as contrib 6 5 7 from django.utils import unittest 6 8 7 9 CONTRIB_DIR_NAME = 'django.contrib' -
AUTHORS
522 522 Gasper Zejn <zejn@kiberpipa.org> 523 523 Jarek Zgoda <jarek.zgoda@gmail.com> 524 524 Cheng Zhang 525 George Karpenkov <george@metaworld.ru> 525 526 526 527 A big THANK YOU goes to: 527 528 -
docs/ref/settings.txt
1641 1641 Note that Django only displays fancy error pages if ``DEBUG`` is ``True``, so 1642 1642 you'll want to set that to take advantage of this setting. 1643 1643 1644 .. warning:: 1645 1646 Note that when TEMPLATE_DEBUG is ``True``, all errors raised inside templates 1647 will be hidden and ``TemplateSyntaxError`` will be raised instead. Also note 1648 that included templates which raise errors will be ignored and errors inside them will be 1649 silenced. 1650 1644 1651 See also ``DEBUG``. 1645 1652 1646 1653 .. setting:: TEMPLATE_DIRS