Django

Code

Ticket #3453: patch

File patch, 16.5 kB (added by Brian Harring <ferringb@gmail.com>, 2 years ago)

resolve_variable refactoring

  • django-new/django/contrib/admin/templatetags/admin_modify.py

    old new  
    6969    default = None 
    7070 
    7171    def __init__(self, bound_field_var): 
    72         self.bound_field_var = bound_field_var 
     72        self.bound_field_var = template.Variable(bound_field_var) 
    7373 
    7474    def get_nodelist(cls, klass): 
    7575        if not cls.nodelists.has_key(klass): 
     
    9393    get_nodelist = classmethod(get_nodelist) 
    9494 
    9595    def render(self, context): 
    96         bound_field = template.resolve_variable(self.bound_field_var, context) 
     96        bound_field = self.bound_field_var.resolve(context) 
    9797 
    9898        context.push() 
    9999        context['bound_field'] = bound_field 
     
    153153 
    154154class EditInlineNode(template.Node): 
    155155    def __init__(self, rel_var): 
    156         self.rel_var = rel_var 
     156        self.rel_var = template.Variable(rel_var) 
    157157 
    158158    def render(self, context): 
    159         relation = template.resolve_variable(self.rel_var, context) 
     159        relation = self.rel_var.resolve(context) 
    160160        context.push() 
    161161        if relation.field.rel.edit_inline == models.TABULAR: 
    162162            bound_related_object_class = TabularBoundRelatedObject 
  • django-new/django/contrib/comments/templatetags/comments.py

    old new  
    1818        ratings_optional=False, ratings_required=False, rating_options='', 
    1919        is_public=True): 
    2020        self.content_type = content_type 
     21        if obj_id_lookup_var is not None: 
     22            obj_id_lookup_var = template.Variable(obj_id_lookup_var) 
    2123        self.obj_id_lookup_var, self.obj_id, self.free = obj_id_lookup_var, obj_id, free 
    2224        self.photos_optional, self.photos_required = photos_optional, photos_required 
    2325        self.ratings_optional, self.ratings_required = ratings_optional, ratings_required 
     
    3032        context.push() 
    3133        if self.obj_id_lookup_var is not None: 
    3234            try: 
    33                 self.obj_id = template.resolve_variable(self.obj_id_lookup_var, context) 
     35                self.obj_id = self.obj_id_lookup_var.resolve(context) 
    3436            except template.VariableDoesNotExist: 
    3537                return '' 
    3638            # Validate that this object ID is valid for this content-type. 
     
    7375    def __init__(self, package, module, context_var_name, obj_id, var_name, free): 
    7476        self.package, self.module = package, module 
    7577        self.context_var_name, self.obj_id = context_var_name, obj_id 
     78        if var_name is not None: 
     79            var_name = template.Variable(var_name) 
    7680        self.var_name, self.free = var_name, free 
    7781 
    7882    def render(self, context): 
    7983        from django.conf import settings 
    8084        manager = self.free and FreeComment.objects or Comment.objects 
    8185        if self.context_var_name is not None: 
    82             self.obj_id = template.resolve_variable(self.context_var_name, context) 
     86            self.obj_id = self.var_name.resolve(context) 
    8387        comment_count = manager.filter(object_id__exact=self.obj_id, 
    8488            content_type__app_label__exact=self.package, 
    8589            content_type__model__exact=self.module, site__id__exact=settings.SITE_ID).count() 
     
    8993class CommentListNode(template.Node): 
    9094    def __init__(self, package, module, context_var_name, obj_id, var_name, free, ordering, extra_kwargs=None): 
    9195        self.package, self.module = package, module 
     96        if context_var_name is not None: 
     97            context_var_name = template.Variable(context_var_name) 
    9298        self.context_var_name, self.obj_id = context_var_name, obj_id 
    9399        self.var_name, self.free = var_name, free 
    94100        self.ordering = ordering 
     
    99105        get_list_function = self.free and FreeComment.objects.filter or Comment.objects.get_list_with_karma 
    100106        if self.context_var_name is not None: 
    101107            try: 
    102                 self.obj_id = template.resolve_variable(self.context_var_name, context) 
     108                self.obj_id = self.context_var_name.resolve(context) 
    103109            except template.VariableDoesNotExist: 
    104110                return '' 
    105111        kwargs = { 
  • django-new/django/template/__init__.py

    old new  
    554554                upto = match.end() 
    555555        if upto != len(token): 
    556556            raise TemplateSyntaxError, "Could not parse the remainder: %s" % token[upto:] 
    557         self.var, self.filters = var, filters 
     557        self.var, self.filters = Variable(var), filters 
    558558 
    559559    def resolve(self, context, ignore_failures=False): 
    560560        try: 
    561             obj = resolve_variable(self.var, context) 
     561            obj = self.var.resolve(context) 
    562562        except VariableDoesNotExist: 
    563563            if ignore_failures: 
    564564                obj = None 
     
    610610    def __str__(self): 
    611611        return self.token 
    612612 
    613 def resolve_variable(path, context): 
     613 
     614class Variable(object): 
    614615    """ 
    615616    Returns the resolved variable, which may contain attribute syntax, within 
    616617    the given context. The variable may be a hard-coded string (if it begins 
    617618    and ends with single or double quote marks). 
    618619 
    619620    >>> c = {'article': {'section':'News'}} 
    620     >>> resolve_variable('article.section', c) 
     621    >>> v = Variable('article.section') 
     622    >>> v.resolve(c) 
    621623    'News' 
    622     >>> resolve_variable('article', c) 
     624    >>> Variable('article').resolve(c) 
    623625    {'section': 'News'} 
    624626    >>> class AClass: pass 
    625627    >>> c = AClass() 
    626628    >>> c.article = AClass() 
    627629    >>> c.article.section = 'News' 
    628     >>> resolve_variable('article.section', c) 
     630    >>> v.resolve(c) 
    629631    'News' 
    630632 
    631633    (The example assumes VARIABLE_ATTRIBUTE_SEPARATOR is '.') 
    632634    """ 
    633     if path[0].isdigit(): 
    634         number_type = '.' in path and float or int 
    635         try: 
    636             current = number_type(path) 
    637         except ValueError: 
    638             current = settings.TEMPLATE_STRING_IF_INVALID 
    639     elif path[0] in ('"', "'") and path[0] == path[-1]: 
    640         current = path[1:-1] 
    641     else: 
     635 
     636    def __init__(self, path): 
     637        if path[0].isdigit(): 
     638            number_type = ('.' in path and float) or int 
     639            try: 
     640                self.forced_value = number_type(path) 
     641            except ValueError: 
     642                self.forced_value = settings.TEMPLATE_STRING_IF_INVALID 
     643        elif path[0] in ('"', "'") and path[0] == path[-1]: 
     644            self.forced_value = path[1:-1] 
     645        else: 
     646            self.forced_value = None 
     647            self.split_path = path.split(VARIABLE_ATTRIBUTE_SEPARATOR) 
     648 
     649    def resolve(self, context): 
     650        if self.forced_value is not None: 
     651            return self.forced_value 
    642652        current = context 
    643         bits = path.split(VARIABLE_ATTRIBUTE_SEPARATOR) 
    644         while bits: 
     653        for bit in self.split_path: 
    645654            try: # dictionary lookup 
    646                 current = current[bits[0]
     655                current = current[bit
    647656            except (TypeError, AttributeError, KeyError): 
    648657                try: # attribute lookup 
    649                     current = getattr(current, bits[0]
     658                    current = getattr(current, bit
    650659                    if callable(current): 
    651660                        if getattr(current, 'alters_data', False): 
    652661                            current = settings.TEMPLATE_STRING_IF_INVALID 
     
    658667                                # raised in the function itself. 
    659668                                current = settings.TEMPLATE_STRING_IF_INVALID # invalid method call 
    660669                            except Exception, e: 
    661                                 if getattr(e, 'silent_variable_failure', False): 
    662                                     current = settings.TEMPLATE_STRING_IF_INVALID 
    663                                 else: 
     670                                if not getattr(e, 'silent_variable_failure', False): 
    664671                                    raise 
     672                                current = settings.TEMPLATE_STRING_IF_INVALID 
    665673                except (TypeError, AttributeError): 
    666674                    try: # list-index lookup 
    667                         current = current[int(bits[0])] 
     675                        current = current[int(bit)] 
    668676                    except (IndexError, ValueError, KeyError): 
    669                         raise VariableDoesNotExist("Failed lookup for key [%s] in %r", (bits[0], current)) # missing attribute 
     677                        raise VariableDoesNotExist("Failed lookup for key [%s] in %r", (bit, current)) # missing attribute 
    670678                except Exception, e: 
    671                     if getattr(e, 'silent_variable_failure', False): 
    672                         current = settings.TEMPLATE_STRING_IF_INVALID 
    673                     else: 
     679                    if not getattr(e, 'silent_variable_failure', False): 
    674680                        raise 
    675             del bits[0] 
    676     return current 
     681                    current = settings.TEMPLATE_STRING_IF_INVALID 
     682        return current 
     683 
     684def resolve_variable(path, context): 
     685    """ 
     686    Shortcut to resolve a variable- primary usage should be for resolving a 
     687    variable once.  If the variable may be resolved multiple times, use the  
     688    Variable class. 
     689     
     690    See Variable class for information on allowed variable names 
     691 
     692    >>> c = {'article': {'section':'News'}} 
     693    >>> resolve_variable('article.section', c) 
     694    'News' 
     695    >>> resolve_variable('article', c) 
     696    {'section': 'News'} 
     697    >>> class AClass: pass 
     698    >>> c = AClass() 
     699    >>> c.article = AClass() 
     700    >>> c.article.section = 'News' 
     701    >>> resolve_variable('article.section', c) 
     702    'News' 
     703 
     704    (The example assumes VARIABLE_ATTRIBUTE_SEPARATOR is '.') 
     705    """ 
     706    return Variable(path).resolve(context) 
    677707 
    678708class Node(object): 
    679709    def render(self, context): 
     
    710740        return nodes 
    711741 
    712742    def render_node(self, node, context): 
    713         return(node.render(context)
     743        return node.render(context
    714744 
    715745class DebugNodeList(NodeList): 
    716746    def render_node(self, node, context): 
  • django-new/django/template/defaultfilters.py

    old new  
    11"Default variable filters" 
    22 
    3 from django.template import resolve_variable, Library 
     3from django.template import Variable, Library 
    44from django.conf import settings 
    55from django.utils.translation import gettext 
    66import re 
     
    224224    Takes a list of dicts, returns that list sorted by the property given in 
    225225    the argument. 
    226226    """ 
    227     decorated = [(resolve_variable('var.' + arg, {'var' : item}), item) for item in value] 
     227    var = Variable('var.%s' % arg) 
     228    decorated = [(var.resolve({'var' : item}), item) for item in value] 
    228229    decorated.sort() 
    229230    return [item[1] for item in decorated] 
    230231 
     
    233234    Takes a list of dicts, returns that list sorted in reverse order by the 
    234235    property given in the argument. 
    235236    """ 
    236     decorated = [(resolve_variable('var.' + arg, {'var' : item}), item) for item in value] 
    237     decorated.sort() 
    238     decorated.reverse(
     237    var = Variable('var.%s' % arg) 
     238    decorated = [(var.resolve({'var' : item}), item) for item in value] 
     239    decorated.sort(reverse=True
    239240    return [item[1] for item in decorated] 
    240241 
    241242def first(value): 
  • django-new/django/template/defaulttags.py

    old new  
    11"Default tags used by the template system, available to all templates." 
    22 
    3 from django.template import Node, NodeList, Template, Context, resolve_variable 
     3from django.template import Node, NodeList, Template, Context, Variable 
    44from django.template import TemplateSyntaxError, VariableDoesNotExist, BLOCK_TAG_START, BLOCK_TAG_END, VARIABLE_TAG_START, VARIABLE_TAG_END, SINGLE_BRACE_START, SINGLE_BRACE_END, COMMENT_TAG_START, COMMENT_TAG_END 
    55from django.template import get_library, Library, InvalidTemplateLibrary 
    66from django.conf import settings 
     
    4545 
    4646class FirstOfNode(Node): 
    4747    def __init__(self, vars): 
    48         self.vars = vars 
     48        self.vars = map(Variable, vars) 
    4949 
    5050    def render(self, context): 
    5151        for var in self.vars: 
    5252            try: 
    53                 value = resolve_variable(var, context) 
     53                value = var.resolve(context) 
    5454            except VariableDoesNotExist: 
    5555                continue 
    5656            if value: 
     
    127127    def __init__(self, nodelist, *varlist): 
    128128        self.nodelist = nodelist 
    129129        self._last_seen = None 
    130         self._varlist = varlist 
     130        self._varlist = map(Variable, varlist) 
    131131 
    132132    def render(self, context): 
    133133        if context.has_key('forloop') and context['forloop']['first']: 
     
    136136            if self._varlist: 
    137137                # Consider multiple parameters. 
    138138                # This automatically behaves like a OR evaluation of the multiple variables. 
    139                 compare_to = [resolve_variable(var, context) for var in self._varlist] 
     139                compare_to = [x.resolve(context) for x in self._varlist] 
    140140            else: 
    141141                compare_to = self.nodelist.render(context) 
    142142        except VariableDoesNotExist: 
     
    155155 
    156156class IfEqualNode(Node): 
    157157    def __init__(self, var1, var2, nodelist_true, nodelist_false, negate): 
    158         self.var1, self.var2 = var1, var2 
     158        self.var1, self.var2 = Variable(var1), Variable(var2) 
    159159        self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false 
    160160        self.negate = negate 
    161161 
     
    164164 
    165165    def render(self, context): 
    166166        try: 
    167             val1 = resolve_variable(self.var1, context) 
     167            val1 = self.var1.resolve(context) 
    168168        except VariableDoesNotExist: 
    169169            val1 = None 
    170170        try: 
    171             val2 = resolve_variable(self.var2, context) 
     171            val2 = self.var2.resolve(context) 
    172172        except VariableDoesNotExist: 
    173173            val2 = None 
    174174        if (self.negate and val1 != val2) or (not self.negate and val1 == val2): 
  • django-new/django/template/loader_tags.py

    old new  
    1 from django.template import TemplateSyntaxError, TemplateDoesNotExist, resolve_variable 
     1from django.template import TemplateSyntaxError, TemplateDoesNotExist, Variable 
    22from django.template import Library, Node 
    33from django.template.loader import get_template, get_template_from_string, find_template_source 
    44from django.conf import settings 
     
    9999 
    100100class IncludeNode(Node): 
    101101    def __init__(self, template_name): 
    102         self.template_name = template_name 
     102        self.template_name = Variable(template_name) 
    103103 
    104104    def render(self, context): 
    105105        try: 
    106             template_name = resolve_variable(self.template_name, context) 
     106            template_name = self.template_name.resolve(context) 
    107107            t = get_template(template_name) 
    108108            return t.render(context) 
    109109        except TemplateSyntaxError, e: 
  • django-new/django/templatetags/i18n.py

    old new  
    1 from django.template import Node, resolve_variable 
     1from django.template import Node, Variable 
    22from django.template import TemplateSyntaxError, TokenParser, Library 
    33from django.template import TOKEN_TEXT, TOKEN_VAR 
    44from django.utils import translation 
     
    3232 
    3333class TranslateNode(Node): 
    3434    def __init__(self, value, noop): 
    35         self.value = value 
     35        self.value = Variable(value) 
    3636        self.noop = noop 
    3737 
    3838    def render(self, context): 
    39         value = resolve_variable(self.value, context) 
     39        value = self.value.resolve(context) 
    4040        if self.noop: 
    4141            return value 
    4242        else: