Django

Code

Ticket #3453: resolve_variable-correct-bitrot.patch

File resolve_variable-correct-bitrot.patch, 19.5 kB (added by Brian Harring <ferringb@gmail.com>, 1 year ago)

correct bitrot (again)

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

    old new  
    7272    default = None 
    7373 
    7474    def __init__(self, bound_field_var): 
    75         self.bound_field_var = bound_field_var 
     75        self.bound_field_var = template.Variable(bound_field_var) 
    7676 
    7777    def get_nodelist(cls, klass): 
    7878        if klass not in cls.nodelists: 
     
    9696    get_nodelist = classmethod(get_nodelist) 
    9797 
    9898    def render(self, context): 
    99         bound_field = template.resolve_variable(self.bound_field_var, context) 
     99        bound_field = self.bound_field_var.resolve(context) 
    100100 
    101101        context.push() 
    102102        context['bound_field'] = bound_field 
     
    156156 
    157157class EditInlineNode(template.Node): 
    158158    def __init__(self, rel_var): 
    159         self.rel_var = rel_var 
     159        self.rel_var = template.Variable(rel_var) 
    160160 
    161161    def render(self, context): 
    162         relation = template.resolve_variable(self.rel_var, context) 
     162        relation = self.rel_var.resolve(context) 
    163163        context.push() 
    164164        if relation.field.rel.edit_inline == models.TABULAR: 
    165165            bound_related_object_class = TabularBoundRelatedObject 
  • 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 is not None: 
     22            obj_id_lookup = template.Variable 
    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 
     
    3133        context.push() 
    3234        if self.obj_id_lookup_var is not None: 
    3335            try: 
    34                 self.obj_id = template.resolve_variable(self.obj_id_lookup_var, context) 
     36                self.obj_id = self.obj_id_lookup_var.resolve(context) 
    3537            except template.VariableDoesNotExist: 
    3638                return '' 
    3739            # Validate that this object ID is valid for this content-type. 
     
    7476class CommentCountNode(template.Node): 
    7577    def __init__(self, package, module, context_var_name, obj_id, var_name, free): 
    7678        self.package, self.module = package, module 
     79        if context_var_name is not None: 
     80            context_var_name = template.Variable(context_var_name) 
    7781        self.context_var_name, self.obj_id = context_var_name, obj_id 
    7882        self.var_name, self.free = var_name, free 
    7983 
     
    8185        from django.conf import settings 
    8286        manager = self.free and FreeComment.objects or Comment.objects 
    8387        if self.context_var_name is not None: 
    84             self.obj_id = template.resolve_variable(self.context_var_name, context) 
     88            self.obj_id = self.context_var_name.resolve(context) 
    8589        comment_count = manager.filter(object_id__exact=self.obj_id, 
    8690            content_type__app_label__exact=self.package, 
    8791            content_type__model__exact=self.module, site__id__exact=settings.SITE_ID).count() 
     
    9195class CommentListNode(template.Node): 
    9296    def __init__(self, package, module, context_var_name, obj_id, var_name, free, ordering, extra_kwargs=None): 
    9397        self.package, self.module = package, module 
     98        if context_var_name is not None: 
     99            context_var_name = template.Variable(context_var_name) 
    94100        self.context_var_name, self.obj_id = context_var_name, obj_id 
    95101        self.var_name, self.free = var_name, free 
    96102        self.ordering = ordering 
     
    101107        get_list_function = self.free and FreeComment.objects.filter or Comment.objects.get_list_with_karma 
    102108        if self.context_var_name is not None: 
    103109            try: 
    104                 self.obj_id = template.resolve_variable(self.context_var_name, context) 
     110                self.obj_id = self.context_var_name.resolve(context) 
    105111            except template.VariableDoesNotExist: 
    106112                return '' 
    107113        kwargs = { 
  • django/template/__init__.py

    old new  
    9393tag_re = re.compile('(%s.*?%s|%s.*?%s|%s.*?%s)' % (re.escape(BLOCK_TAG_START), re.escape(BLOCK_TAG_END), 
    9494                                          re.escape(VARIABLE_TAG_START), re.escape(VARIABLE_TAG_END), 
    9595                                          re.escape(COMMENT_TAG_START), re.escape(COMMENT_TAG_END))) 
    96 # matches if the string is valid number 
    97 number_re = re.compile(r'[-+]?(\d+|\d*\.\d+)$') 
    9896 
    9997# global dictionary of libraries that have been loaded using get_library 
    10098libraries = {} 
     
    568566                elif constant_arg is not None: 
    569567                    args.append((False, constant_arg.replace(r'\"', '"'))) 
    570568                elif var_arg: 
    571                     args.append((True, var_arg)) 
     569                    args.append((True, Variable(var_arg))) 
    572570                filter_func = parser.find_filter(filter_name) 
    573571                self.args_check(filter_name,filter_func, args) 
    574572                filters.append( (filter_func,args)) 
    575573                upto = match.end() 
    576574        if upto != len(token): 
    577575            raise TemplateSyntaxError, "Could not parse the remainder: '%s' from '%s'" % (token[upto:], token) 
    578         self.var, self.filters = var, filters 
     576        self.filters = filters 
     577        self.var = Variable(var) 
    579578 
    580579    def resolve(self, context, ignore_failures=False): 
    581580        try: 
    582             obj = resolve_variable(self.var, context) 
     581            obj = self.var.resolve(context) 
    583582        except VariableDoesNotExist: 
    584583            if ignore_failures: 
    585584                obj = None 
     
    599598                if not lookup: 
    600599                    arg_vals.append(arg) 
    601600                else: 
    602                     arg_vals.append(resolve_variable(arg, context)) 
     601                    arg_vals.append(arg.resolve(context)) 
    603602            obj = func(obj, *arg_vals) 
    604603        return obj 
    605604 
     
    658657 
    659658    (The example assumes VARIABLE_ATTRIBUTE_SEPARATOR is '.') 
    660659    """ 
    661     if number_re.match(path): 
    662         number_type = '.' in path and float or int 
    663         current = number_type(path) 
    664     elif path[0] in ('"', "'") and path[0] == path[-1]: 
    665         current = path[1:-1] 
    666     else: 
     660    return Variable(path).resolve(context) 
     661 
     662class LiteralVariable(object): 
     663 
     664    def __init__(self, val): 
     665        self.val = val 
     666 
     667    def resolve(self, context): 
     668        return self.val 
     669 
     670    def __str__(self): 
     671        return self.val 
     672 
     673def Variable(val): 
     674    try: 
     675        # note we're not catching OverflowError here; point of debate on how best to handle that... 
     676        current = float(val) 
     677        if '.' not in val: 
     678            # downside to this approach is that 1e07 becomes an int; float may be preferable still. 
     679            current = int(current) 
     680        elif val[-1] == '.': 
     681            # 2. is invalid 
     682            raise ValueError 
     683        return LiteralVariable(current) 
     684    except ValueError: 
     685        pass 
     686    if val[0] in "\"'" and val[0] == val[-1]: 
     687        return LiteralVariable(val[1:-1]) 
     688    return ChainedLookupVariable(val) 
     689     
     690class ChainedLookupVariable(object): 
     691 
     692    def __init__(self, val): 
     693        self.lookups = tuple(val.split(VARIABLE_ATTRIBUTE_SEPARATOR)) 
     694     
     695    def resolve(self, context): 
    667696        current = context 
    668         bits = path.split(VARIABLE_ATTRIBUTE_SEPARATOR) 
    669         while bits: 
     697        for bit in self.lookups: 
    670698            try: # dictionary lookup 
    671                 current = current[bits[0]
     699                current = current[bit
    672700            except (TypeError, AttributeError, KeyError): 
    673701                try: # attribute lookup 
    674                     current = getattr(current, bits[0]
     702                    current = getattr(current, bit
    675703                    if callable(current): 
    676704                        if getattr(current, 'alters_data', False): 
    677705                            current = settings.TEMPLATE_STRING_IF_INVALID 
     
    689717                                    raise 
    690718                except (TypeError, AttributeError): 
    691719                    try: # list-index lookup 
    692                         current = current[int(bits[0])] 
     720                        current = current[int(bit)] 
    693721                    except (IndexError, # list index out of range 
    694722                            ValueError, # invalid literal for int() 
    695                             KeyError,   # current is a dict without `int(bits[0])` key 
     723                            KeyError,   # current is a dict without `int(bit)` key 
    696724                            TypeError,  # unsubscriptable object 
    697725                            ): 
    698                         raise VariableDoesNotExist("Failed lookup for key [%s] in %r", (bits[0], current)) # missing attribute 
     726                        raise VariableDoesNotExist("Failed lookup for key [%s] in %r", (bit, current)) # missing attribute 
    699727                except Exception, e: 
    700728                    if getattr(e, 'silent_variable_failure', False): 
    701729                        current = settings.TEMPLATE_STRING_IF_INVALID 
    702730                    else: 
    703731                        raise 
    704             del bits[0] 
    705     if isinstance(current, (basestring, Promise)): 
    706         try: 
    707             current = force_unicode(current) 
    708         except UnicodeDecodeError: 
    709             # Failing to convert to unicode can happen sometimes (e.g. debug 
    710             # tracebacks). So we allow it in this particular instance. 
    711             pass 
    712     return current 
     732     
     733        if isinstance(current, (basestring, Promise)): 
     734            try: 
     735                current = force_unicode(current) 
     736            except UnicodeDecodeError: 
     737                # Failing to convert to unicode can happen sometimes (e.g. debug 
     738                # tracebacks). So we allow it in this particular instance. 
     739                pass 
     740        return current 
     741 
     742    def __str__(self): 
     743        return VARIABLE_ATTRIBUTE_SEPARATOR.join(self.lookups) 
    713744 
    714745class Node(object): 
    715746    def render(self, context): 
     
    865896 
    866897        class SimpleNode(Node): 
    867898            def __init__(self, vars_to_resolve): 
    868                 self.vars_to_resolve = vars_to_resolve 
     899                self.vars_to_resolve = map(Variable, vars_to_resolve) 
    869900 
    870901            def render(self, context): 
    871                 resolved_vars = [resolve_variable(var, context) for var in self.vars_to_resolve] 
    872                 return func(*resolved_vars) 
     902                return func(*[var.resolve(context) for var in self.vars_to_resolve]) 
    873903 
    874904        compile_func = curry(generic_tag_compiler, params, defaults, getattr(func, "_decorated_function", func).__name__, SimpleNode) 
    875905        compile_func.__doc__ = func.__doc__ 
     
    887917 
    888918            class InclusionNode(Node): 
    889919                def __init__(self, vars_to_resolve): 
    890                     self.vars_to_resolve = vars_to_resolve 
     920                    self.vars_to_resolve = map(Variable, vars_to_resolve) 
    891921 
    892922                def render(self, context): 
    893                     resolved_vars = [resolve_variable(var, context) for var in self.vars_to_resolve] 
     923                    resolved_vars = [var.resolve(context) for var in self.vars_to_resolve] 
    894924                    if takes_context: 
    895925                        args = [context] + resolved_vars 
    896926                    else: 
  • 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 ugettext, ungettext 
    66from django.utils.encoding import force_unicode, smart_str, iri_to_uri 
     
    290290    Takes a list of dicts, returns that list sorted by the property given in 
    291291    the argument. 
    292292    """ 
    293     decorated = [(resolve_variable(u'var.' + arg, {u'var' : item}), item) for item in value] 
     293    var_resolve = Variable(arg).resolve 
     294    decorated = [(var_resolve(item), item) for item in value] 
    294295    decorated.sort() 
    295296    return [item[1] for item in decorated] 
    296297 
     
    299300    Takes a list of dicts, returns that list sorted in reverse order by the 
    300301    property given in the argument. 
    301302    """ 
    302     decorated = [(resolve_variable(u'var.' + arg, {u'var' : item}), item) for item in value] 
     303    var_resolve = Variable(arg).resolve 
     304    decorated = [(var_resolve(item), item) for item in value] 
    303305    decorated.sort() 
    304306    decorated.reverse() 
    305307    return [item[1] for item in decorated] 
  • 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 
     
    5656 
    5757class FirstOfNode(Node): 
    5858    def __init__(self, vars): 
    59         self.vars = vars 
     59        self.vars = map(Variable, vars) 
    6060 
    6161    def render(self, context): 
    6262        for var in self.vars: 
    6363            try: 
    64                 value = resolve_variable(var, context) 
     64                value = var.resolve(context) 
    6565            except VariableDoesNotExist: 
    6666                continue 
    6767            if value: 
     
    146146    def __init__(self, nodelist, *varlist): 
    147147        self.nodelist = nodelist 
    148148        self._last_seen = None 
    149         self._varlist = varlist 
     149        self._varlist = map(Variable, varlist) 
    150150 
    151151    def render(self, context): 
    152152        if 'forloop' in context and context['forloop']['first']: 
     
    155155            if self._varlist: 
    156156                # Consider multiple parameters. 
    157157                # This automatically behaves like a OR evaluation of the multiple variables. 
    158                 compare_to = [resolve_variable(var, context) for var in self._varlist] 
     158                compare_to = [var.resolve(context) for var in self._varlist] 
    159159            else: 
    160160                compare_to = self.nodelist.render(context) 
    161161        except VariableDoesNotExist: 
     
    174174 
    175175class IfEqualNode(Node): 
    176176    def __init__(self, var1, var2, nodelist_true, nodelist_false, negate): 
    177         self.var1, self.var2 = var1, var2 
     177        self.var1, self.var2 = Variable(var1), Variable(var2) 
    178178        self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false 
    179179        self.negate = negate 
    180180 
     
    183183 
    184184    def render(self, context): 
    185185        try: 
    186             val1 = resolve_variable(self.var1, context) 
     186            val1 = self.var1.resolve(context) 
    187187        except VariableDoesNotExist: 
    188188            val1 = None 
    189189        try: 
    190             val2 = resolve_variable(self.var2, context) 
     190            val2 = self.var2.resolve(context) 
    191191        except VariableDoesNotExist: 
    192192            val2 = None 
    193193        if (self.negate and val1 != val2) or (not self.negate and val1 == val2): 
  • 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/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: 
  • docs/templates_python.txt

    old new  
    864864 
    865865You also have to change the renderer to retrieve the actual contents of the 
    866866``date_updated`` property of the ``blog_entry`` object.  This can be 
    867 accomplished by using the ``resolve_variable()`` function in 
    868 ``django.template``. You pass ``resolve_variable()`` the variable name and the 
    869 current context, available in the ``render`` method:: 
     867accomplished by using the ``Variable`` class in ``django.template``.  
     868You pass ``Variable`` the variable name, and invoke the ``resolve`` method with the 
     869current context:: 
    870870 
    871871    from django import template 
    872     from django.template import resolve_variable 
     872    from django.template import Variable 
    873873    import datetime 
    874874    class FormatTimeNode(template.Node): 
    875875        def __init__(self, date_to_be_formatted, format_string): 
    876             self.date_to_be_formatted = date_to_be_formatted 
     876            self.date_to_be_formatted = Variable(date_to_be_formatted) 
    877877            self.format_string = format_string 
    878878         
    879879        def render(self, context): 
    880880            try: 
    881                 actual_date = resolve_variable(self.date_to_be_formatted, context) 
     881                actual_date = self.date_to_be_formatted.resolve(context) 
    882882                return actual_date.strftime(self.format_string) 
    883883            except template.VariableDoesNotExist: 
    884884                return '' 
    885885 
    886 ``resolve_variable`` will try to resolve ``blog_entry.date_updated`` and then 
    887 format it accordingly. 
     886``render`` will try to resolve ``blog_entry.date_updated`` via ``Variable.resolve``, 
     887and then format it accordingly. 
    888888 
    889889.. note:: 
    890     The ``resolve_variable()`` function will throw a ``VariableDoesNotExist`` 
     890    The ``Variable.resolve`` method will throw a ``VariableDoesNotExist`` 
    891891    exception if it cannot resolve the string passed to it in the current 
    892892    context of the page. 
     893     
     894    Additionally, ``resolve_variable(arg, context)`` is a function invoking 
     895    ``Variable(arg).resolve(context)``.  The ``Variable`` should be used instead, 
     896    since ``resolve_variable`` is deprecated. 
    893897 
    894898Shortcut for simple tags 
    895899~~~~~~~~~~~~~~~~~~~~~~~~