Ticket #13956: 13956r16406.diff

File 13956r16406.diff, 13.4 KB (added by Stephen Burrows, 13 years ago)
  • django/template/base.py

    diff --git a/django/template/base.py b/django/template/base.py
    index b96e446..0cc2daa 100644
    a b class VariableNode(Node):  
    799799            return ''
    800800        return _render_value_in_context(output, context)
    801801
    802 def generic_tag_compiler(params, defaults, name, node_class, parser, token):
    803     "Returns a template.Node subclass."
    804     bits = token.split_contents()[1:]
     802def generic_tag_syntax_check(bits, params, defaults, name, varargs):
    805803    bmax = len(params)
    806804    def_len = defaults and len(defaults) or 0
    807805    bmin = bmax - def_len
    808     if(len(bits) < bmin or len(bits) > bmax):
    809         if bmin == bmax:
    810             message = "%s takes %s arguments" % (name, bmin)
    811         else:
    812             message = "%s takes between %s and %s arguments" % (name, bmin, bmax)
    813         raise TemplateSyntaxError(message)
     806    if varargs is None:
     807        if(len(bits) < bmin or len(bits) > bmax):
     808            if bmin == bmax:
     809                message = "%s takes %s arguments" % (name, bmin)
     810            else:
     811                message = "%s takes between %s and %s arguments" % (name, bmin, bmax)
     812            raise TemplateSyntaxError(message)
     813    else:
     814        if(len(bits) < bmin):
     815            message = "%s takes at least %s arguments" % (name, bmin)
     816            raise TemplateSyntaxError(message)
     817
     818def generic_tag_compiler(parser, token, params, defaults, name, node_class, varargs):
     819    "Returns a template.Node subclass."
     820    bits = token.split_contents()[1:]
     821    generic_tag_syntax_check(bits, params, defaults, name, varargs)
    814822    return node_class(bits)
    815823
    816824class Library(object):
    class Library(object):  
    868876
    869877    def simple_tag(self, func=None, takes_context=None, name=None):
    870878        def dec(func):
    871             params, xx, xxx, defaults = getargspec(func)
     879            params, varargs, xxx, defaults = getargspec(func)
    872880            if takes_context:
    873881                if params[0] == 'context':
    874882                    params = params[1:]
    class Library(object):  
    888896                    return func(*func_args)
    889897
    890898            function_name = name or getattr(func, '_decorated_function', func).__name__
    891             compile_func = partial(generic_tag_compiler, params, defaults, function_name, SimpleNode)
     899            compile_func = partial(generic_tag_compiler, params=params, defaults=defaults, name=function_name, node_class=SimpleNode, varargs=varargs)
    892900            compile_func.__doc__ = func.__doc__
    893901            self.tag(function_name, compile_func)
    894902            return func
    class Library(object):  
    904912
    905913    def assignment_tag(self, func=None, takes_context=None, name=None):
    906914        def dec(func):
    907             params, xx, xxx, defaults = getargspec(func)
     915            params, varargs, xxx, defaults = getargspec(func)
    908916            if takes_context:
    909917                if params[0] == 'context':
    910918                    params = params[1:]
    class Library(object):  
    925933                    context[self.target_var] = func(*func_args)
    926934                    return ''
    927935
     936            function_name = name or getattr(func, '_decorated_function', func).__name__
     937
    928938            def compile_func(parser, token):
    929                 bits = token.split_contents()
    930                 tag_name = bits[0]
    931                 bits = bits[1:]
    932                 params_max = len(params)
    933                 defaults_length = defaults and len(defaults) or 0
    934                 params_min = params_max - defaults_length
     939                bits = token.split_contents()[1:]
    935940                if (len(bits) < 2 or bits[-2] != 'as'):
    936941                    raise TemplateSyntaxError(
    937942                        "'%s' tag takes at least 2 arguments and the "
    938                         "second last argument must be 'as'" % tag_name)
    939                 params_vars = bits[:-2]
     943                        "second last argument must be 'as'" % function_name)
    940944                target_var = bits[-1]
    941                 if (len(params_vars) < params_min or
    942                         len(params_vars) > params_max):
    943                     if params_min == params_max:
    944                         raise TemplateSyntaxError(
    945                             "%s takes %s arguments" % (tag_name, params_min))
    946                     else:
    947                         raise TemplateSyntaxError(
    948                             "%s takes between %s and %s arguments"
    949                             % (tag_name, params_min, params_max))
    950                 return AssignmentNode(params_vars, target_var)
     945                args = bits[:-2]
     946                generic_tag_syntax_check(args, params, defaults, function_name, varargs)
     947                return AssignmentNode(args, target_var)
    951948
    952             function_name = name or getattr(func, '_decorated_function', func).__name__
    953949            compile_func.__doc__ = func.__doc__
    954950            self.tag(function_name, compile_func)
    955951            return func
    class Library(object):  
    965961
    966962    def inclusion_tag(self, file_name, context_class=Context, takes_context=False, name=None):
    967963        def dec(func):
    968             params, xx, xxx, defaults = getargspec(func)
     964            params, varargs, xxx, defaults = getargspec(func)
    969965            if takes_context:
    970966                if params[0] == 'context':
    971967                    params = params[1:]
    class Library(object):  
    10081004                    return self.nodelist.render(new_context)
    10091005
    10101006            function_name = name or getattr(func, '_decorated_function', func).__name__
    1011             compile_func = partial(generic_tag_compiler, params, defaults, function_name, InclusionNode)
     1007            compile_func = partial(generic_tag_compiler, params=params, defaults=defaults, name=function_name, node_class=InclusionNode, varargs=varargs)
    10121008            compile_func.__doc__ = func.__doc__
    10131009            self.tag(function_name, compile_func)
    10141010            return func
  • tests/regressiontests/templates/templatetags/custom.py

    diff --git a/tests/regressiontests/templates/templatetags/custom.py b/tests/regressiontests/templates/templatetags/custom.py
    index dfa4171..ce8588d 100644
    a b def params_and_context(context, arg):  
    4040    return "params_and_context - Expected result (context value: %s): %s" % (context['value'], arg)
    4141params_and_context.anything = "Expected params_and_context __dict__"
    4242
     43@register.simple_tag
     44def simple_tag_with_three_arguments(one, two, three):
     45    return ', '.join((one, two, three))
     46
     47@register.simple_tag
     48def simple_tag_with_two_default_arguments(one, two='2', three='3'):
     49    return ', '.join((one, two, three))
     50
     51@register.simple_tag
     52def simple_tag_with_unlimited_arguments(one, two='2', *args):
     53    return ', '.join([one, two] + list(args))
     54
     55@register.simple_tag
     56def simple_tag_with_only_unlimited_arguments(*args):
     57    return ', '.join(args)
     58
    4359@register.inclusion_tag('inclusion.html')
    4460def inclusion_no_params():
    4561    """Expected inclusion_no_params __doc__"""
    def inclusion_params_and_context_from_template(context, arg):  
    100116    return {"result" : "inclusion_params_and_context_from_template - Expected result (context value: %s): %s" % (context['value'], arg)}
    101117inclusion_params_and_context_from_template.anything = "Expected inclusion_params_and_context_from_template __dict__"
    102118
     119@register.inclusion_tag('basic-syntax03')
     120def inclusion_tag_with_two_arguments(one, two):
     121    return {
     122        'first': one,
     123        'second': two
     124    }
     125
     126@register.inclusion_tag('basic-syntax03')
     127def inclusion_tag_with_one_default_argument(one, two='hi'):
     128    return {
     129        'first': one,
     130        'second': two
     131    }
     132
     133@register.inclusion_tag('for-tag01')
     134def inclusion_tag_with_unlimited_arguments(one, two='hi', *args):
     135    return {
     136        'values': [one, two] + list(args)
     137    }
     138
     139@register.inclusion_tag('for-tag01')
     140def inclusion_tag_with_only_unlimited_arguments(*args):
     141    return {
     142        'values': args
     143    }
     144
    103145@register.simple_tag(takes_context=True)
    104146def current_app(context):
    105147    return "%s" % context.current_app
  • tests/regressiontests/templates/tests.py

    diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py
    index 36a1ca3..d959059 100644
    a b class Templates(unittest.TestCase):  
    16081608            'static-prefixtag02': ('{% load static %}{% get_static_prefix as static_prefix %}{{ static_prefix }}', {}, settings.STATIC_URL),
    16091609            'static-prefixtag03': ('{% load static %}{% get_media_prefix %}', {}, settings.MEDIA_URL),
    16101610            'static-prefixtag04': ('{% load static %}{% get_media_prefix as media_prefix %}{{ media_prefix }}', {}, settings.MEDIA_URL),
     1611
     1612
     1613            ### SIMPLE TAGS ######################################################
     1614            'simpletags01': ('{% load custom %}{% simple_tag_with_three_arguments "one" "two" "three" %}', {}, 'one, two, three'),
     1615            'simpletags02': ('{% load custom %}{% simple_tag_with_three_arguments one two three %}', {'one': '1', 'two': '2', 'three': '3'}, '1, 2, 3'),
     1616
     1617            # Default arguments
     1618            'simpletags-default01': ('{% load custom %}{% simple_tag_with_two_default_arguments "one" "two" "three" %}', {}, 'one, two, three'),
     1619            'simpletags-default02': ('{% load custom %}{% simple_tag_with_two_default_arguments one three %}', {'one': '1', 'two': '2', 'three': '3'}, '1, 3, 3'),
     1620            'simpletags-default03': ('{% load custom %}{% simple_tag_with_two_default_arguments one %}', {'one': 'first'}, 'first, 2, 3'),
     1621
     1622            # Unlimited arguments
     1623            'simpletags-unlimited01': ('{% load custom %}{% simple_tag_with_unlimited_arguments "one" "two" "three" %}', {}, 'one, two, three'),
     1624            'simpletags-unlimited02': ('{% load custom %}{% simple_tag_with_unlimited_arguments "one" %}', {}, 'one, 2'),
     1625            'simpletags-unlimited03': ('{% load custom %}{% simple_tag_with_unlimited_arguments one two three four five %}', {'one': '1', 'two': '2', 'three': '3', 'four': '4', 'five': '5'}, '1, 2, 3, 4, 5'),
     1626            'simpletags-unlimited04': ('{% load custom %}{% simple_tag_with_unlimited_arguments one %}', {'one': 'first'}, 'first, 2'),
     1627            'simpletags-unlimited05': ('{% load custom %}{% simple_tag_with_only_unlimited_arguments one %}', {'one': 'first'}, 'first'),
     1628            'simpletags-unlimited06': ('{% load custom %}{% simple_tag_with_only_unlimited_arguments %}', {}, ''),
     1629            'simpletags-unlimited07': ('{% load custom %}{% simple_tag_with_only_unlimited_arguments "one" "2" "3" %}', {}, 'one, 2, 3'),
     1630
     1631            # Failures
     1632            'simpletags-fail01': ('{% load custom %}{% simple_tag_with_three_arguments "one" "three" %}', {}, template.TemplateSyntaxError),
     1633            'simpletags-fail02': ('{% load custom %}{% simple_tag_with_three_arguments "one" "two" "three" "four" %}', {}, template.TemplateSyntaxError),
     1634            'simpletags-fail03': ('{% load custom %}{% simple_tag_with_two_default_arguments %}', {}, template.TemplateSyntaxError),
     1635            'simpletags-fail04': ('{% load custom %}{% simple_tag_with_two_default_arguments "one" "two" "three" "four" %}', {}, template.TemplateSyntaxError),
     1636            'simpletags-fail05': ('{% load custom %}{% simple_tag_with_unlimited_arguments %}', {}, template.TemplateSyntaxError),
     1637
     1638
     1639
     1640            ### INCLUSION TAGS ######################################################
     1641            'inclusiontags01': ('{% load custom %}{% inclusion_tag_with_two_arguments "1" "2" %}', {}, "1 --- 2"),
     1642            'inclusiontags02': ('{% load custom %}{% inclusion_tag_with_two_arguments "1" two %}', {'two': '2'}, "1 --- 2"),
     1643
     1644            # Default arguments
     1645            'inclusiontags-default01': ('{% load custom %}{% inclusion_tag_with_one_default_argument "1" "2" %}', {}, "1 --- 2"),
     1646            'inclusiontags-default02': ('{% load custom %}{% inclusion_tag_with_one_default_argument one %}', {'one': "1"}, "1 --- hi"),
     1647
     1648            # Unlimited arguments
     1649            'inclusiontags-unlimited01': ('{% load custom %}{% inclusion_tag_with_unlimited_arguments "1" "2" %}', {}, "12"),
     1650            'inclusiontags-unlimited02': ('{% load custom %}{% inclusion_tag_with_unlimited_arguments one %}', {'one': 'first'}, "firsthi"),
     1651            'inclusiontags-unlimited03': ('{% load custom %}{% inclusion_tag_with_unlimited_arguments "1" "2" "3" "5" "7" %}', {}, "12357"),
     1652            'inclusiontags-unlimited04': ('{% load custom %}{% inclusion_tag_with_only_unlimited_arguments %}', {}, ""),
     1653            'inclusiontags-unlimited05': ('{% load custom %}{% inclusion_tag_with_only_unlimited_arguments "1" "2" "3" "5" hello %}', {'hello': 'hello'}, "1235hello"),
     1654
     1655            # Failures
     1656            'inclusiontags-fail01': ('{% load custom %}{% inclusion_tag_with_two_arguments "1" %}', {}, template.TemplateSyntaxError),
     1657            'inclusiontags-fail02': ('{% load custom %}{% inclusion_tag_with_two_arguments "1" two "3" %}', {'two': '2'}, template.TemplateSyntaxError),
     1658            'inclusiontags-fail03': ('{% load custom %}{% inclusion_tag_with_one_default_argument %}', {}, template.TemplateSyntaxError),
     1659            'inclusiontags-fail04': ('{% load custom %}{% inclusion_tag_with_one_default_argument "1" two "3" %}', {'two': '2'}, template.TemplateSyntaxError),
     1660            'inclusiontags-fail05': ('{% load custom %}{% inclusion_tag_with_unlimited_arguments %}', {}, template.TemplateSyntaxError),
    16111661        }
    16121662
    16131663class TemplateTagLoading(unittest.TestCase):
Back to Top