Ticket #7438: kwdarg_template_tag.patch
File kwdarg_template_tag.patch, 6.4 KB (added by , 16 years ago) |
---|
-
template/__init__.py
55 55 from django.utils.itercompat import is_iterable 56 56 from django.utils.functional import curry, Promise 57 57 from django.utils.text import smart_split 58 from django.utils.encoding import smart_ unicode, force_unicode58 from django.utils.encoding import smart_str, smart_unicode, force_unicode 59 59 from django.utils.translation import ugettext as _ 60 60 from django.utils.safestring import SafeData, EscapeData, mark_safe, mark_for_escaping 61 61 from django.utils.html import escape 62 try: 63 set 64 except NameError: 65 from sets import Set as set # Python 2.3 fallback 62 66 63 67 __all__ = ('Template', 'Context', 'RequestContext', 'compile_string') 64 68 … … 71 75 FILTER_SEPARATOR = '|' 72 76 FILTER_ARGUMENT_SEPARATOR = ':' 73 77 VARIABLE_ATTRIBUTE_SEPARATOR = '.' 78 TAG_KEYWORD_ARGUMENT_SEPARATOR = '=' 74 79 BLOCK_TAG_START = '{%' 75 80 BLOCK_TAG_END = '%}' 76 81 VARIABLE_TAG_START = '{{' … … 592 597 """ 593 598 return Variable(path).resolve(context) 594 599 600 def resolve_all_variables_for_call(variables, context, name, params, num_default, 601 varargs, varkw): 602 """ 603 resolve an iterable of Variable objects into a list of args and a dict 604 of keyword arguments. support full python style keyword argument 605 processing:: 606 >>> def foo(a, b, c=1, d=2): 607 ... pass 608 >>> foo(1, 2) 609 >>> foo(1, b=2) 610 >>> foo(b=2, a=1, d=3) 611 """ 612 args = [] 613 kwdargs = {} 614 found_kwd = False 615 for variable in variables: 616 if not found_kwd: 617 try: 618 args.append(variable.resolve(context)) 619 except VariableDoesNotExist: 620 if variable.var.count(TAG_KEYWORD_ARGUMENT_SEPARATOR) != 1: 621 raise 622 found_kwd = True 623 if found_kwd: 624 try: 625 var, path = variable.var.split(TAG_KEYWORD_ARGUMENT_SEPARATOR) 626 except ValueError: 627 raise TemplateSyntaxError( 628 "Expected keyword assignemnt, found '%s' instead" % 629 variable.var) 630 if params and not varkw and name not in params: 631 raise TemplateSyntaxError( 632 "%s got an unexpected keyword argument '%s'" % (name, var)) 633 if var in kwdargs: 634 raise TemplateSyntaxError( 635 "got multiple values for keyword argument '%s'"%(name,var)) 636 kwdargs[smart_str(var)] = Variable(path).resolve(context) 637 if ((len(args) > len(params) and not varargs) or 638 ((len(args)+len(kwdargs)) > len(params) and not varkw)): 639 raise TemplateSyntaxError( 640 "%s takes at most %s arguments. (%s given)" % ( 641 name, len(params), len(args) + len(kwdargs)) ) 642 if len(args) != (len(params)-num_default): 643 if len(args)>(len(params)-num_default): 644 # some args are kwd args (maybe multiple keyword error) 645 if not varargs: 646 allowed = set(params[len(args):]) 647 not_allowed = set(kwdargs) - allowed 648 if not_allowed: 649 raise TemplateSyntaxError( 650 "%s got multiple values for keyword arguments: %s" % ( 651 name, ", ".join(not_allowed) )) 652 elif not varkw: 653 # not enough required parameters error 654 required = set(params[len(args):-num_default]) 655 missing = required - set(kwdargs) 656 if missing: 657 raise TemplateSyntaxError( 658 "%s takes at least %s non-keyword arguments (%s given)" % ( 659 name, len(params) - num_default, len(args))) 660 return args, kwdargs 661 595 662 class Variable(object): 596 663 """ 597 664 A template variable, resolvable against a given context. The variable may be … … 860 927 return func 861 928 862 929 def simple_tag(self,func): 863 params, xx, xxx, defaults = getargspec(func)930 params, varargs, varkw, defaults = getargspec(func) 864 931 865 932 class SimpleNode(Node): 866 933 def __init__(self, vars_to_resolve): 867 934 self.vars_to_resolve = map(Variable, vars_to_resolve) 868 935 869 936 def render(self, context): 870 resolved_vars = [var.resolve(context) for var in self.vars_to_resolve] 871 return func(*resolved_vars) 937 args, kwdargs = resolve_all_variables_for_call( 938 self.vars_to_resolve, context, 939 getattr(func, "_decorated_function", func).__name__, 940 params, defaults and len(defaults) or 0, 941 varargs, varkw) 872 942 943 return func(*args, **kwdargs) 944 873 945 compile_func = curry(generic_tag_compiler, params, defaults, getattr(func, "_decorated_function", func).__name__, SimpleNode) 874 946 compile_func.__doc__ = func.__doc__ 875 947 self.tag(getattr(func, "_decorated_function", func).__name__, compile_func) … … 877 949 878 950 def inclusion_tag(self, file_name, context_class=Context, takes_context=False): 879 951 def dec(func): 880 params, xx, xxx, defaults = getargspec(func)952 params, varargs, varkw, defaults = getargspec(func) 881 953 if takes_context: 882 954 if params[0] == 'context': 883 955 params = params[1:] … … 889 961 self.vars_to_resolve = map(Variable, vars_to_resolve) 890 962 891 963 def render(self, context): 892 resolved_vars = [var.resolve(context) for var in self.vars_to_resolve] 964 args, kwdargs = resolve_all_variables_for_call( 965 self.vars_to_resolve, context, 966 getattr(func, "_decorated_function", func).__name__, 967 params, defaults and len(defaults) or 0, 968 varargs, varkw) 893 969 if takes_context: 894 args = [context] + resolved_vars 895 else: 896 args = resolved_vars 970 args = [context] + args 897 971 898 dict = func(*args )972 dict = func(*args, **kwdargs) 899 973 900 974 if not getattr(self, 'nodelist', False): 901 975 from django.template.loader import get_template, select_template