Ticket #3453: resolve_variable-correct-bitrot.patch

File resolve_variable-correct-bitrot.patch, 19.5 KB (added by (removed), 8 years ago)

correct bitrot (again)

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

    === modified file 'django/contrib/admin/templatetags/admin_modify.py'
     
    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

    === modified file 'django/contrib/comments/templatetags/comments.py'
     
    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

    === modified file 'django/template/__init__.py'
     
    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

    === modified file 'django/template/defaultfilters.py'
     
    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

    === modified file 'django/template/defaulttags.py'
     
    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

    === modified file 'django/template/loader_tags.py'
     
    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

    === modified file 'django/templatetags/i18n.py'
     
    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

    === modified file 'docs/templates_python.txt'
     
    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~~~~~~~~~~~~~~~~~~~~~~~~
Back to Top