~nchohan/appscale/zk3.3.4

« back to all changes in this revision

Viewing changes to AppServer/google/appengine/_internal/django/template/loader.py

  • Committer: Chris Bunch
  • Date: 2012-02-17 08:19:21 UTC
  • mfrom: (787.2.3 appscale-raj-merge)
  • Revision ID: cgb@cs.ucsb.edu-20120217081921-pakidyksaenlpzur
merged with main branch, gaining rabbitmq and upgrades for hbase, cassandra, and hypertable, as well as upgrading to gae 1.6.1 for python and go

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Wrapper for loading templates from storage of some sort (e.g. filesystem, database).
 
2
#
 
3
# This uses the TEMPLATE_LOADERS setting, which is a list of loaders to use.
 
4
# Each loader is expected to have this interface:
 
5
#
 
6
#    callable(name, dirs=[])
 
7
#
 
8
# name is the template name.
 
9
# dirs is an optional list of directories to search instead of TEMPLATE_DIRS.
 
10
#
 
11
# The loader should return a tuple of (template_source, path). The path returned
 
12
# might be shown to the user for debugging purposes, so it should identify where
 
13
# the template was loaded from.
 
14
#
 
15
# A loader may return an already-compiled template instead of the actual
 
16
# template source. In that case the path returned should be None, since the
 
17
# path information is associated with the template during the compilation,
 
18
# which has already been done.
 
19
#
 
20
# Each loader should have an "is_usable" attribute set. This is a boolean that
 
21
# specifies whether the loader can be used in this Python installation. Each
 
22
# loader is responsible for setting this when it's initialized.
 
23
#
 
24
# For example, the eggs loader (which is capable of loading templates from
 
25
# Python eggs) sets is_usable to False if the "pkg_resources" module isn't
 
26
# installed, because pkg_resources is necessary to read eggs.
 
27
 
 
28
from google.appengine._internal.django.core.exceptions import ImproperlyConfigured
 
29
from google.appengine._internal.django.template import Origin, Template, Context, TemplateDoesNotExist, add_to_builtins
 
30
from google.appengine._internal.django.utils.importlib import import_module
 
31
from google.appengine._internal.django.conf import settings
 
32
 
 
33
template_source_loaders = None
 
34
 
 
35
class BaseLoader(object):
 
36
    is_usable = False
 
37
 
 
38
    def __init__(self, *args, **kwargs):
 
39
        pass
 
40
 
 
41
    def __call__(self, template_name, template_dirs=None):
 
42
        return self.load_template(template_name, template_dirs)
 
43
 
 
44
    def load_template(self, template_name, template_dirs=None):
 
45
        source, display_name = self.load_template_source(template_name, template_dirs)
 
46
        origin = make_origin(display_name, self.load_template_source, template_name, template_dirs)
 
47
        try:
 
48
            template = get_template_from_string(source, origin, template_name)
 
49
            return template, None
 
50
        except TemplateDoesNotExist:
 
51
            # If compiling the template we found raises TemplateDoesNotExist, back off to
 
52
            # returning the source and display name for the template we were asked to load.
 
53
            # This allows for correct identification (later) of the actual template that does
 
54
            # not exist.
 
55
            return source, display_name
 
56
 
 
57
    def load_template_source(self, template_name, template_dirs=None):
 
58
        """
 
59
        Returns a tuple containing the source and origin for the given template
 
60
        name.
 
61
 
 
62
        """
 
63
        raise NotImplementedError
 
64
 
 
65
    def reset(self):
 
66
        """
 
67
        Resets any state maintained by the loader instance (e.g., cached
 
68
        templates or cached loader modules).
 
69
 
 
70
        """
 
71
        pass
 
72
 
 
73
class LoaderOrigin(Origin):
 
74
    def __init__(self, display_name, loader, name, dirs):
 
75
        super(LoaderOrigin, self).__init__(display_name)
 
76
        self.loader, self.loadname, self.dirs = loader, name, dirs
 
77
 
 
78
    def reload(self):
 
79
        return self.loader(self.loadname, self.dirs)[0]
 
80
 
 
81
def make_origin(display_name, loader, name, dirs):
 
82
    if settings.TEMPLATE_DEBUG and display_name:
 
83
        return LoaderOrigin(display_name, loader, name, dirs)
 
84
    else:
 
85
        return None
 
86
 
 
87
def find_template_loader(loader):
 
88
    if isinstance(loader, (tuple, list)):
 
89
        loader, args = loader[0], loader[1:]
 
90
    else:
 
91
        args = []
 
92
    if isinstance(loader, basestring):
 
93
        module, attr = loader.rsplit('.', 1)
 
94
        try:
 
95
            mod = import_module(module)
 
96
        except ImportError, e:
 
97
            raise ImproperlyConfigured('Error importing template source loader %s: "%s"' % (loader, e))
 
98
        try:
 
99
            TemplateLoader = getattr(mod, attr)
 
100
        except AttributeError, e:
 
101
            raise ImproperlyConfigured('Error importing template source loader %s: "%s"' % (loader, e))
 
102
 
 
103
        if hasattr(TemplateLoader, 'load_template_source'):
 
104
            func = TemplateLoader(*args)
 
105
        else:
 
106
            # Try loading module the old way - string is full path to callable
 
107
            if args:
 
108
                raise ImproperlyConfigured("Error importing template source loader %s - can't pass arguments to function-based loader." % loader)
 
109
            func = TemplateLoader
 
110
 
 
111
        if not func.is_usable:
 
112
            import warnings
 
113
            warnings.warn("Your TEMPLATE_LOADERS setting includes %r, but your Python installation doesn't support that type of template loading. Consider removing that line from TEMPLATE_LOADERS." % loader)
 
114
            return None
 
115
        else:
 
116
            return func
 
117
    else:
 
118
        raise ImproperlyConfigured('Loader does not define a "load_template" callable template source loader')
 
119
 
 
120
def find_template(name, dirs=None):
 
121
    # Calculate template_source_loaders the first time the function is executed
 
122
    # because putting this logic in the module-level namespace may cause
 
123
    # circular import errors. See Django ticket #1292.
 
124
    global template_source_loaders
 
125
    if template_source_loaders is None:
 
126
        loaders = []
 
127
        for loader_name in settings.TEMPLATE_LOADERS:
 
128
            loader = find_template_loader(loader_name)
 
129
            if loader is not None:
 
130
                loaders.append(loader)
 
131
        template_source_loaders = tuple(loaders)
 
132
    for loader in template_source_loaders:
 
133
        try:
 
134
            source, display_name = loader(name, dirs)
 
135
            return (source, make_origin(display_name, loader, name, dirs))
 
136
        except TemplateDoesNotExist:
 
137
            pass
 
138
    raise TemplateDoesNotExist(name)
 
139
 
 
140
def find_template_source(name, dirs=None):
 
141
    # For backward compatibility
 
142
    import warnings
 
143
    warnings.warn(
 
144
        "`django.template.loaders.find_template_source` is deprecated; use `django.template.loaders.find_template` instead.",
 
145
        PendingDeprecationWarning
 
146
    )
 
147
    template, origin = find_template(name, dirs)
 
148
    if hasattr(template, 'render'):
 
149
        raise Exception("Found a compiled template that is incompatible with the deprecated `django.template.loaders.find_template_source` function.")
 
150
    return template, origin
 
151
 
 
152
def get_template(template_name):
 
153
    """
 
154
    Returns a compiled Template object for the given template name,
 
155
    handling template inheritance recursively.
 
156
    """
 
157
    template, origin = find_template(template_name)
 
158
    if not hasattr(template, 'render'):
 
159
        # template needs to be compiled
 
160
        template = get_template_from_string(template, origin, template_name)
 
161
    return template
 
162
 
 
163
def get_template_from_string(source, origin=None, name=None):
 
164
    """
 
165
    Returns a compiled Template object for the given template code,
 
166
    handling template inheritance recursively.
 
167
    """
 
168
    return Template(source, origin, name)
 
169
 
 
170
def render_to_string(template_name, dictionary=None, context_instance=None):
 
171
    """
 
172
    Loads the given template_name and renders it with the given dictionary as
 
173
    context. The template_name may be a string to load a single template using
 
174
    get_template, or it may be a tuple to use select_template to find one of
 
175
    the templates in the list. Returns a string.
 
176
    """
 
177
    dictionary = dictionary or {}
 
178
    if isinstance(template_name, (list, tuple)):
 
179
        t = select_template(template_name)
 
180
    else:
 
181
        t = get_template(template_name)
 
182
    if context_instance:
 
183
        context_instance.update(dictionary)
 
184
    else:
 
185
        context_instance = Context(dictionary)
 
186
    return t.render(context_instance)
 
187
 
 
188
def select_template(template_name_list):
 
189
    "Given a list of template names, returns the first that can be loaded."
 
190
    for template_name in template_name_list:
 
191
        try:
 
192
            return get_template(template_name)
 
193
        except TemplateDoesNotExist:
 
194
            continue
 
195
    # If we get here, none of the templates could be loaded
 
196
    raise TemplateDoesNotExist(', '.join(template_name_list))
 
197
 
 
198
add_to_builtins('google.appengine._internal.django.template.loader_tags')