Django

Code

Changeset 6442

Show
Ignore:
Timestamp:
09/30/07 22:58:05 (1 year ago)
Author:
jbronn
Message:

gis: Merged revisions 6394-6441 via svnmerge from trunk.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/gis

    • Property svnmerge-integrated changed from /django/trunk:1-6393 to /django/trunk:1-6441
  • django/branches/gis/AUTHORS

    r6394 r6442  
    115115    A. Murat Eren <meren@pardus.org.tr> 
    116116    Ludvig Ericson <ludvig.ericson@gmail.com> 
     117    eriks@win.tue.nl 
    117118    Dirk Eschler <dirk.eschler@gmx.net> 
    118119    Marc Fargas <telenieko@telenieko.com> 
     
    235236    pavithran s <pavithran.s@gmail.com> 
    236237    Barry Pederson <bp@barryp.org> 
     238    permonik@mesias.brnonet.cz 
    237239    petr.marhoun@gmail.com 
    238240    pgross@thoughtworks.com 
     
    241243    phil.h.smith@gmail.com 
    242244    Gustavo Picon 
    243     pigletto 
    244245    Luke Plant <http://lukeplant.me.uk/> 
    245246    plisk 
     
    322323    Gary Wilson <gary.wilson@gmail.com> 
    323324    Jakub Wiśniowski <restless.being@gmail.com> 
     325    Maciej Wiśniowski <pigletto@gmail.com> 
    324326    wojtek 
    325327    ye7cakf02@sneakemail.com 
  • django/branches/gis/django/contrib/admin/templatetags/admin_modify.py

    r6018 r6442  
    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): 
     
    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() 
     
    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: 
  • django/branches/gis/django/contrib/auth/backends.py

    r6394 r6442  
    22from django.contrib.auth.models import User 
    33 
     4try:  
     5    set  
     6except NameError:  
     7    from sets import Set as set # Python 2.3 fallback 
     8         
    49class ModelBackend: 
    510    """ 
  • django/branches/gis/django/contrib/comments/templatetags/comments.py

    r6018 r6442  
    2020        is_public=True): 
    2121        self.content_type = content_type 
     22        if obj_id_lookup_var is not None: 
     23            obj_id_lookup_var = template.Variable(obj_id_lookup_var) 
    2224        self.obj_id_lookup_var, self.obj_id, self.free = obj_id_lookup_var, obj_id, free 
    2325        self.photos_optional, self.photos_required = photos_optional, photos_required 
     
    3335        if self.obj_id_lookup_var is not None: 
    3436            try: 
    35                 self.obj_id = template.resolve_variable(self.obj_id_lookup_var, context) 
     37                self.obj_id = self.obj_id_lookup_var.resolve(context) 
    3638            except template.VariableDoesNotExist: 
    3739                return '' 
     
    7678    def __init__(self, package, module, context_var_name, obj_id, var_name, free): 
    7779        self.package, self.module = package, module 
     80        if context_var_name is not None: 
     81            context_var_name = template.Variable(context_var_name) 
    7882        self.context_var_name, self.obj_id = context_var_name, obj_id 
    7983        self.var_name, self.free = var_name, free 
     
    8387        manager = self.free and FreeComment.objects or Comment.objects 
    8488        if self.context_var_name is not None: 
    85             self.obj_id = template.resolve_variable(self.context_var_name, context) 
     89            self.obj_id = self.context_var_name.resolve(context) 
    8690        comment_count = manager.filter(object_id__exact=self.obj_id, 
    8791            content_type__app_label__exact=self.package, 
     
    9397    def __init__(self, package, module, context_var_name, obj_id, var_name, free, ordering, extra_kwargs=None): 
    9498        self.package, self.module = package, module 
     99        if context_var_name is not None: 
     100            context_var_name = template.Variable(context_var_name) 
    95101        self.context_var_name, self.obj_id = context_var_name, obj_id 
    96102        self.var_name, self.free = var_name, free 
     
    103109        if self.context_var_name is not None: 
    104110            try: 
    105                 self.obj_id = template.resolve_variable(self.context_var_name, context) 
     111                self.obj_id = self.context_var_name.resolve(context) 
    106112            except template.VariableDoesNotExist: 
    107113                return '' 
  • django/branches/gis/django/contrib/sessions/models.py

    r6394 r6442  
    1 import base64, md5, random, sys, datetime 
     1import os 
     2import sys 
     3import time 
     4import datetime 
     5import base64 
     6import md5 
     7import random 
    28import cPickle as pickle 
     9 
    310from django.db import models 
    411from django.utils.translation import ugettext_lazy as _ 
  • django/branches/gis/django/core/handlers/wsgi.py

    r6394 r6442  
     1from threading import Lock 
     2from pprint import pformat 
     3try: 
     4    from cStringIO import StringIO 
     5except ImportError: 
     6    from StringIO import StringIO 
     7 
    18from django.core.handlers.base import BaseHandler 
    29from django.core import signals 
     
    512from django.utils.encoding import force_unicode 
    613from django import http 
    7 from pprint import pformat 
    8 from shutil import copyfileobj 
    9 from threading import Lock 
    10 try: 
    11     from cStringIO import StringIO 
    12 except ImportError: 
    13     from StringIO import StringIO 
    1414 
    1515# See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html 
     
    106106 
    107107    def is_secure(self): 
    108         return 'HTTPS' in self.environ and self.environ['HTTPS'] == 'on' 
     108        return 'wsgi.url_scheme' in self.environ \ 
     109            and self.environ['wsgi.url_scheme'] == 'https' 
    109110 
    110111    def _load_post_and_files(self): 
  • django/branches/gis/django/core/management/base.py

    r6394 r6442  
    1010    pass 
    1111 
     12def handle_default_options(options): 
     13    """ 
     14    Include any default options that all commands should accept 
     15    here so that ManagementUtility can handle them before searching 
     16    for user commands. 
     17    """ 
     18    if options.settings: 
     19        os.environ['DJANGO_SETTINGS_MODULE'] = options.settings 
     20    if options.pythonpath: 
     21        sys.path.insert(0, options.pythonpath) 
     22                 
    1223class BaseCommand(object): 
    1324    # Metadata about this command. 
     
    5667        parser = self.create_parser(argv[0], argv[1]) 
    5768        options, args = parser.parse_args(argv[2:]) 
    58         if options.settings: 
    59             os.environ['DJANGO_SETTINGS_MODULE'] = options.settings 
    60         if options.pythonpath: 
    61             sys.path.insert(0, options.pythonpath) 
     69        handle_default_options(options) 
    6270        self.execute(*args, **options.__dict__) 
    6371 
  • django/branches/gis/django/core/management/__init__.py

    r6394 r6442  
    11import django 
     2from django.core.management.base import BaseCommand, CommandError, handle_default_options  
    23from optparse import OptionParser 
    34import os 
    45import sys 
     6from imp import find_module 
    57 
    68# For backwards compatibility: get_version() used to be in this module. 
    79get_version = django.get_version 
    810 
    9 def load_command_class(name): 
    10     """ 
    11     Given a command name, returns the Command class instance. Raises 
    12     ImportError if it doesn't exist. 
    13     """ 
    14     # Let the ImportError propogate. 
    15     return getattr(__import__('django.core.management.commands.%s' % name, {}, {}, ['Command']), 'Command')() 
     11# A cache of loaded commands, so that call_command  
     12# doesn't have to reload every time it is called 
     13_commands = None 
     14 
     15def find_commands(management_dir): 
     16    """ 
     17    Given a path to a management directory, return a list of all the command names  
     18    that are available. Returns an empty list if no commands are defined. 
     19    """ 
     20    command_dir = os.path.join(management_dir,'commands') 
     21    try: 
     22        return [f[:-3] for f in os.listdir(command_dir) if not f.startswith('_') and f.endswith('.py')] 
     23    except OSError: 
     24        return [] 
     25 
     26def find_management_module(app_name): 
     27    """ 
     28    Determine the path to the management module for the application named, 
     29    without acutally importing the application or the management module. 
     30 
     31    Raises ImportError if the management module cannot be found for any reason. 
     32    """ 
     33    parts = app_name.split('.') 
     34    parts.append('management') 
     35    parts.reverse() 
     36    path = None 
     37    while parts: 
     38        part = parts.pop() 
     39        f,path,descr = find_module(part, path and [path] or None) 
     40    return path 
     41     
     42def load_command_class(app_name, name): 
     43    """ 
     44    Given a command name and an application name, returns the Command  
     45    class instance. All errors raised by the importation process 
     46    (ImportError, AttributeError) are allowed to propagate. 
     47    """ 
     48    return getattr(__import__('%s.management.commands.%s' % (app_name, name),  
     49                   {}, {}, ['Command']), 'Command')() 
     50 
     51def get_commands(load_user_commands=True, project_directory=None): 
     52    """ 
     53    Returns a dictionary of commands against the application in which 
     54    those commands can be found. This works by looking for a  
     55    management.commands package in django.core, and in each installed  
     56    application -- if a commands package exists, all commands in that 
     57    package are registered. 
     58 
     59    Core commands are always included; user-defined commands will also 
     60    be included if ``load_user_commands`` is True. If a project directory 
     61    is provided, the startproject command will be disabled, and the 
     62    startapp command will be modified to use that directory. 
     63 
     64    The dictionary is in the format {command_name: app_name}. Key-value 
     65    pairs from this dictionary can then be used in calls to  
     66    load_command_class(app_name, command_name) 
     67     
     68    If a specific version of a command must be loaded (e.g., with the 
     69    startapp command), the instantiated module can be placed in the 
     70    dictionary in place of the application name. 
     71     
     72    The dictionary is cached on the first call, and reused on subsequent 
     73    calls. 
     74    """ 
     75    global _commands 
     76    if _commands is None: 
     77        _commands = dict([(name, 'django.core')  
     78                          for name in find_commands(__path__[0])]) 
     79        if load_user_commands: 
     80            # Get commands from all installed apps 
     81            from django.conf import settings 
     82            for app_name in settings.INSTALLED_APPS: 
     83                try: 
     84                    path = find_management_module(app_name) 
     85                    _commands.update(dict([(name, app_name)  
     86                                           for name in find_commands(path)])) 
     87                except ImportError: 
     88                    pass # No management module - ignore this app 
     89                     
     90        if project_directory: 
     91            # Remove the "startproject" command from self.commands, because 
     92            # that's a django-admin.py command, not a manage.py command. 
     93            del _commands['startproject'] 
     94 
     95            # Override the startapp command so that it always uses the 
     96            # project_directory, not the current working directory  
     97            # (which is default). 
     98            from django.core.management.commands.startapp import ProjectCommand 
     99            _commands['startapp'] = ProjectCommand(project_directory) 
     100 
     101    return _commands 
    16102 
    17103def call_command(name, *args, **options): 
     
    26112        call_command('sqlall', 'myapp') 
    27113    """ 
    28     klass = load_command_class(name) 
     114    try: 
     115        app_name = get_commands()[name] 
     116        if isinstance(app_name, BaseCommand):  
     117            # If the command is already loaded, use it directly. 
     118            klass = app_name 
     119        else: 
     120            klass = load_command_class(app_name, name) 
     121    except KeyError: 
     122        raise CommandError, "Unknown command: %r" % name 
    29123    return klass.execute(*args, **options) 
     124     
     125class LaxOptionParser(OptionParser):  
     126    """ 
     127    An option parser that doesn't raise any errors on unknown options. 
     128     
     129    This is needed because the --settings and --pythonpath options affect 
     130    the commands (and thus the options) that are available to the user.  
     131    """ 
     132    def error(self, msg):  
     133            pass 
    30134 
    31135class ManagementUtility(object): 
     
    39143        self.argv = argv or sys.argv[:] 
    40144        self.prog_name = os.path.basename(self.argv[0]) 
    41         self.commands = self.default_commands() 
    42  
    43     def default_commands(self): 
    44         """ 
    45         Returns a dictionary of instances of all available Command classes. 
    46  
    47         This works by looking for and loading all Python modules in the 
    48         django.core.management.commands package. 
    49  
    50         The dictionary is in the format {name: command_instance}. 
    51         """ 
    52         command_dir = os.path.join(__path__[0], 'commands') 
    53         names = [f[:-3] for f in os.listdir(command_dir) if not f.startswith('_') and f.endswith('.py')] 
    54         return dict([(name, load_command_class(name)) for name in names]) 
    55  
     145        self.project_directory = None 
     146        self.user_commands = False 
     147         
    56148    def main_help_text(self): 
    57149        """ 
     
    62154        usage.append("Type '%s help <subcommand>' for help on a specific subcommand." % self.prog_name) 
    63155        usage.append('Available subcommands:') 
    64         commands = self.commands.keys() 
     156        commands = get_commands(self.user_commands, self.project_directory).keys() 
    65157        commands.sort() 
    66158        for cmd in commands: 
     
    75167        """ 
    76168        try: 
    77             return self.commands[subcommand] 
     169            app_name = get_commands(self.user_commands, self.project_directory)[subcommand] 
     170            if isinstance(app_name, BaseCommand):  
     171                # If the command is already loaded, use it directly. 
     172                klass = app_name 
     173            else: 
     174                klass = load_command_class(app_name, subcommand) 
    78175        except KeyError: 
    79176            sys.stderr.write("Unknown command: %r\nType '%s help' for usage.\n" % (subcommand, self.prog_name)) 
    80177            sys.exit(1) 
    81  
     178        return klass 
     179         
    82180    def execute(self): 
    83181        """ 
     
    85183        being run, creates a parser appropriate to that command, and runs it. 
    86184        """ 
     185        # Preprocess options to extract --settings and --pythonpath. These options 
     186        # could affect the commands that are available, so they must be processed 
     187        # early 
     188        parser = LaxOptionParser(version=get_version(),  
     189                                 option_list=BaseCommand.option_list)  
     190        try: 
     191            options, args = parser.parse_args(self.argv)  
     192            handle_default_options(options) 
     193        except:  
     194            pass # Ignore any option errors at this point. 
     195          
    87196        try: 
    88197            subcommand = self.argv[1] 
     
    92201 
    93202        if subcommand == 'help': 
    94             if len(self.argv) > 2: 
    95                 self.fetch_command(self.argv[2]).print_help(self.prog_name, self.argv[2]) 
     203            if len(args) > 2: 
     204                self.fetch_command(args[2]).print_help(self.prog_name, args[2]) 
    96205            else: 
    97206                sys.stderr.write(self.main_help_text() + '\n') 
     
    117226    def __init__(self, argv, project_directory): 
    118227        super(ProjectManagementUtility, self).__init__(argv) 
    119  
    120         # Remove the "startproject" command from self.commands, because 
    121         # that's a django-admin.py command, not a manage.py command. 
    122         del self.commands['startproject'] 
    123  
    124         # Override the startapp command so that it always uses the 
    125         # project_directory, not the current working directory (which is default). 
    126         from django.core.management.commands.startapp import ProjectCommand 
    127         self.commands['startapp'] = ProjectCommand(project_directory) 
    128  
     228        self.project_directory = project_directory 
     229        self.user_commands = True 
     230                 
    129231def setup_environ(settings_mod): 
    130232    """ 
  • django/branches/gis/django/db/models/query.py

    r6394 r6442  
    11811181                    setattr(instance, field.attname, None) 
    11821182 
     1183            dispatcher.send(signal=signals.post_delete, sender=cls, instance=instance) 
    11831184            setattr(instance, cls._meta.pk.attname, None) 
    1184             dispatcher.send(signal=signals.post_delete, sender=cls, instance=instance) 
    11851185 
    11861186    transaction.commit_unless_managed() 
  • django/branches/gis/django/middleware/http.py

    r6394 r6442  
    5555            return None 
    5656        else: 
    57             # HTTP_X_FORWARDED_FOR can be a comma-separated list of IPs. 
    58             # Take just the last one. 
    59             # See http://bob.pythonmac.org/archives/2005/09/23/apache-x-forwarded-for-caveat/ 
    60             real_ip = real_ip.split(",")[-1].strip() 
     57            # HTTP_X_FORWARDED_FOR can be a comma-separated list of IPs. The 
     58            # client's IP will be the first one. 
     59            real_ip = real_ip.split(",")[0].strip() 
    6160            request.META['REMOTE_ADDR'] = real_ip 
  • django/branches/gis/django/template/defaultfilters.py

    r6394 r6442  
    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 
     
    298298    the argument. 
    299299    """ 
    300     decorated = [(resolve_variable(u'var.' + arg, {u'var' : item}), item) for item in value] 
     300    var_resolve = Variable(arg).resolve 
     301    decorated = [(var_resolve(item), item) for item in value] 
    301302    decorated.sort() 
    302303    return [item[1] for item in decorated] 
     
    307308    property given in the argument. 
    308309    """ 
    309     decorated = [(resolve_variable(u'var.' + arg, {u'var' : item}), item) for item in value] 
     310    var_resolve = Variable(arg).resolve 
     311    decorated = [(var_resolve(item), item) for item in value] 
    310312    decorated.sort() 
    311313    decorated.reverse() 
  • django/branches/gis/django/template/defaulttags.py

    r6394 r6442  
    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 
     
    3131        self.counter += 1 
    3232        value = self.cyclevars[self.counter % self.cyclevars_len] 
    33         value = resolve_variable(value, context) 
     33        value = Variable(value).resolve(context) 
    3434        if self.variable_name: 
    3535            context[self.variable_name] = value 
     
    5858class FirstOfNode(Node): 
    5959    def __init__(self, vars): 
    60         self.vars = vars 
     60        self.vars = map(Variable, vars) 
    6161 
    6262    def render(self, context): 
    6363        for var in self.vars: 
    6464            try: 
    65                 value = resolve_variable(var, context) 
     65                value = var.resolve(context) 
    6666            except VariableDoesNotExist: 
    6767                continue 
     
    148148        self.nodelist = nodelist 
    149149        self._last_seen = None 
    150         self._varlist = varlist 
     150        self._varlist = map(Variable, varlist) 
    151151 
    152152    def render(self, context): 
     
    157157                # Consider multiple parameters. 
    158158                # This automatically behaves like a OR evaluation of the multiple variables. 
    159                 compare_to = [resolve_variable(var, context) for var in self._varlist] 
     159                compare_to = [var.resolve(context) for var in self._varlist] 
    160160            else: 
    161161                compare_to = self.nodelist.render(context) 
     
    176176class IfEqualNode(Node): 
    177177    def __init__(self, var1, var2, nodelist_true, nodelist_false, negate): 
    178         self.var1, self.var2 = var1, var2 
     178        self.var1, self.var2 = Variable(var1), Variable(var2) 
    179179        self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false 
    180180        self.negate = negate 
     
    185185    def render(self, context): 
    186186        try: 
    187             val1 = resolve_variable(self.var1, context) 
     187            val1 = self.var1.resolve(context) 
    188188        except VariableDoesNotExist: 
    189189            val1 = None 
    190190        try: 
    191             val2 = resolve_variable(self.var2, context) 
     191            val2 = self.var2.resolve(context) 
    192192        except VariableDoesNotExist: 
    193193            val2 = None 
  • django/branches/gis/django/template/__init__.py

    r6394 r6442  
    8989                                          re.escape(VARIABLE_TAG_START), re.escape(VARIABLE_TAG_END), 
    9090                                          re.escape(COMMENT_TAG_START), re.escape(COMMENT_TAG_END))) 
    91 # matches if the string is valid number 
    92 number_re = re.compile(r'[-+]?(\d+|\d*\.\d+)$') 
    9391 
    9492# global dictionary of libraries that have been loaded using get_library 
     
    565563                    args.append((False, constant_arg.replace(r'\"', '"'))) 
    566564                elif var_arg: 
    567                     args.append((True, var_arg)) 
     565                    args.append((True, Variable(var_arg))) 
    568566                filter_func = parser.find_filter(filter_name) 
    569567                self.args_check(filter_name,filter_func, args) 
     
    572570        if upto != len(token): 
    573571            raise TemplateSyntaxError, "Could not parse the remainder: '%s' from '%s'" % (token[upto:], token) 
    574         self.var, self.filters = var, filters 
     572        self.filters = filters 
     573        self.var = Variable(var) 
    575574 
    576575    def resolve(self, context, ignore_failures=False): 
    577576        try: 
    578             obj = resolve_variable(self.var, context) 
     577            obj = self.var.resolve(context) 
    579578        except VariableDoesNotExist: 
    580579            if ignore_failures: 
     
    596595                    arg_vals.append(arg) 
    597596                else: 
    598                     arg_vals.append(resolve_variable(arg, context)) 
     597                    arg_vals.append(arg.resolve(context)) 
    599598            obj = func(obj, *arg_vals) 
    600599        return obj 
     
    638637    """ 
    639638    Returns the resolved variable, which may contain attribute syntax, within 
    640     the given context. The variable may be a hard-coded string (if it begins 
    641     and ends with single or double quote marks). 
    642  
    643     >>> c = {'article': {'section':'News'}} 
    644     >>> resolve_variable('article.section', c) 
    645     u'News' 
    646     >>> resolve_variable('article', c) 
    647     {'section': 'News'} 
    648     >>> class AClass: pass 
    649     >>> c = AClass() 
    650     >>> c.article = AClass() 
    651     >>> c.article.section = 'News' 
    652     >>> resolve_variable('article.section', c) 
    653     u'News' 
     639    the given context. 
     640     
     641    Deprecated; use the Variable class instead. 
     642    """ 
     643    return Variable(path).resolve(context) 
     644 
     645class Variable(object): 
     646    """ 
     647    A template variable, resolvable against a given context. The variable may be 
     648    a hard-coded string (if it begins and ends with single or double quote 
     649    marks):: 
     650     
     651        >>> c = {'article': {'section':'News'}} 
     652        >>> Variable('article.section').resolve(c) 
     653        u'News' 
     654        >>> Variable('article').resolve(c) 
     655        {'section': 'News'} 
     656        >>> class AClass: pass 
     657        >>> c = AClass() 
     658        >>> c.article = AClass() 
     659        >>> c.article.section = 'News' 
     660        >>> Variable('article.section').resolve(c) 
     661        u'News' 
    654662 
    655663    (The example assumes VARIABLE_ATTRIBUTE_SEPARATOR is '.') 
    656664    """ 
    657     if number_re.match(path): 
    658         number_type = '.' in path and float or int 
    659         current = number_type(path) 
    660     elif path[0] in ('"', "'") and path[0] == path[-1]: 
    661         current = path[1:-1] 
    662     else: 
     665     
     666    def __init__(self, var): 
     667        self.var = var 
     668        self.literal = None 
     669        self.lookups = None 
     670         
     671        try: 
     672            # First try to treat this variable as a number. 
     673            # 
     674            # Note that this could cause an OverflowError here that we're not  
     675            # catching. Since this should only happen at compile time, that's 
     676            # probably OK. 
     677            self.literal = float(var) 
     678         
     679            # So it's a float... is it an int? If the original value contained a 
     680            # dot or an "e" then it was a float, not an int. 
     681            if '.' not in var and 'e' not in var.lower(): 
     682                self.literal = int(self.literal) 
     683                 
     684            # "2." is invalid 
     685            if var.endswith('.'): 
     686                raise ValueError 
     687 
     688        except ValueError: 
     689            # A ValueError means that the variable isn't a number. 
     690            # If it's wrapped with quotes (single or double), then 
     691            # we're also dealing with a literal. 
     692            if var[0] in "\"'" and var[0] == var[-1]: 
     693                self.literal = var[1:-1] 
     694             
     695            else: 
     696                # Otherwise we'll set self.lookups so that resolve() knows we're 
     697                # dealing with a bonafide variable 
     698                self.lookups = tuple(var.split(VARIABLE_ATTRIBUTE_SEPARATOR)) 
     699     
     700    def resolve(self, context): 
     701        """Resolve this variable against a given context.""" 
     702        if self.lookups is not None: 
     703            # We're dealing with a variable that needs to be resolved 
     704            return self._resolve_lookup(context) 
     705        else: 
     706            # We're dealing with a literal, so it's already been "resolved" 
     707            return self.literal 
     708             
     709    def __repr__(self): 
     710        return "<%s: %r>" % (self.__class__.__name__, self.var) 
     711     
     712    def __str__(self): 
     713        return self.var 
     714 
     715    def _resolve_lookup(self, context): 
     716        """ 
     717        Performs resolution of a real variable (i.e. not a literal) against the 
     718        given context.  
     719         
     720        As indicated by the method's name, this method is an implementation 
     721        detail and shouldn't be called by external code. Use Variable.resolve() 
     722        instead. 
     723        """ 
    663724        current = context 
    664         bits = path.split(VARIABLE_ATTRIBUTE_SEPARATOR) 
    665         while bits: 
     725        for bit in self.lookups: 
    666726            try: # dictionary lookup 
    667                 current = current[bits[0]
     727                current = current[bit
    668728            except (TypeError, AttributeError, KeyError): 
    669729                try: # attribute lookup 
    670                     current = getattr(current, bits[0]
     730                    current = getattr(current, bit
    671731                    if callable(current): 
    672732                        if getattr(current, 'alters_data', False): 
     
    686746                except (TypeError, AttributeError): 
    687747                    try: # list-index lookup 
    688                         current = current[int(bits[0])] 
     748                        current = current[int(bit)] 
    689749                    except (IndexError, # list index out of range 
    690750                            ValueError, # invalid literal for int() 
    691                             KeyError,   # current is a dict without `int(bits[0])` key 
     751                            KeyError,   # current is a dict without `int(bit)` key 
    692752                            TypeError,  # unsubscriptable object 
    693753                            ): 
    694                         raise VariableDoesNotExist("Failed lookup for key [%s] in %r", (bits[0], current)) # missing attribute 
     754                        raise VariableDoesNotExist("Failed lookup for key [%s] in %r", (bit, current)) # missing attribute 
    695755                except Exception, e: 
    696756                    if getattr(e, 'silent_variable_failure', False): 
     
    698758                    else: 
    699759                        raise 
    700             del bits[0] 
    701     if isinstance(current, (basestring, Promise)): 
    702         try: 
    703             current = force_unicode(current) 
    704         except UnicodeDecodeError: 
    705             # Failing to convert to unicode can happen sometimes (e.g. debug 
    706             # tracebacks). So we allow it in this particular instance. 
    707             pass 
    708     return current 
     760     
     761        if isinstance(current, (basestring, Promise)): 
     762            try: 
     763                current = force_unicode(current) 
     764            except UnicodeDecodeError: 
     765                # Failing to convert to unicode can happen sometimes (e.g. debug 
     766                # tracebacks). So we allow it in this particular instance. 
     767                pass 
     768        return current 
    709769 
    710770class Node(object): 
     
    862922        class SimpleNode(Node): 
    863923            def __init__(self, vars_to_resolve): 
    864                 self.vars_to_resolve = vars_to_resolve 
     924                self.vars_to_resolve = map(Variable, vars_to_resolve) 
    865925 
    866926            def render(self, context): 
    867                 resolved_vars = [resolve_variable(var, context) for var in self.vars_to_resolve] 
     927                resolved_vars = [var.resolve(context) for var in self.vars_to_resolve] 
    868928                return func(*resolved_vars) 
    869929 
     
    884944            class InclusionNode(Node): 
    885945                def __init__(self, vars_to_resolve): 
    886                     self.vars_to_resolve = vars_to_resolve 
     946                    self.vars_to_resolve = map(Variable, vars_to_resolve) 
    887947 
    888948                def render(self, context): 
    889                     resolved_vars = [resolve_variable(var, context) for var in self.vars_to_resolve] 
     949                    resolved_vars = [var.resolve(context) for var in self.vars_to_resolve] 
    890950                    if takes_context: 
    891951                        args = [context] + resolved_vars 
  • django/branches/gis/django/template/loader_tags.py

    r6018 r6442  
    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 
     
    100100class IncludeNode(Node): 
    101101    def __init__(self, template_name): 
    102         self.template_name = template_name 
     102        self.template_name =