diff -r 261778de26ff -r 620f9b141567 thirdparty/google_appengine/google/appengine/ext/webapp/template.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thirdparty/google_appengine/google/appengine/ext/webapp/template.py Tue Aug 26 21:49:54 2008 +0000 @@ -0,0 +1,219 @@ +#!/usr/bin/env python +# +# Copyright 2007 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +"""A simple wrapper for Django templates. + +The main purpose of this module is to hide all of the package import pain +you normally have to go through to get Django to work. We expose the Django +Template and Context classes from this module, handling the import nonsense +on behalf of clients. + +Typical usage: + + from google.appengine.ext.webapp import template + print template.render('templates/index.html', {'foo': 'bar'}) + +Django uses a global setting for the directory in which it looks for templates. +This is not natural in the context of the webapp module, so our load method +takes in a complete template path, and we set these settings on the fly +automatically. Because we have to set and use a global setting on every +method call, this module is not thread safe, though that is not an issue +for applications. + +Django template documentation is available at: +http://www.djangoproject.com/documentation/templates/ +""" + + + + + +import md5 +import os + +try: + from django import v0_96 +except ImportError: + pass +import django + +import django.conf +try: + django.conf.settings.configure( + DEBUG=False, + TEMPLATE_DEBUG=False, + TEMPLATE_LOADERS=( + 'django.template.loaders.filesystem.load_template_source', + ), + ) +except (EnvironmentError, RuntimeError): + pass +import django.template +import django.template.loader + +from google.appengine.ext import webapp + +def render(template_path, template_dict, debug=False): + """Renders the template at the given path with the given dict of values. + + Example usage: + render("templates/index.html", {"name": "Bret", "values": [1, 2, 3]}) + + Args: + template_path: path to a Django template + template_dict: dictionary of values to apply to the template + """ + t = load(template_path, debug) + return t.render(Context(template_dict)) + + +template_cache = {} +def load(path, debug=False): + """Loads the Django template from the given path. + + It is better to use this function than to construct a Template using the + class below because Django requires you to load the template with a method + if you want imports and extends to work in the template. + """ + abspath = os.path.abspath(path) + + if not debug: + template = template_cache.get(abspath, None) + else: + template = None + + if not template: + directory, file_name = os.path.split(abspath) + new_settings = { + 'TEMPLATE_DIRS': (directory,), + 'TEMPLATE_DEBUG': debug, + 'DEBUG': debug, + } + old_settings = _swap_settings(new_settings) + try: + template = django.template.loader.get_template(file_name) + finally: + _swap_settings(old_settings) + + if not debug: + template_cache[abspath] = template + + def wrap_render(context, orig_render=template.render): + URLNode = django.template.defaulttags.URLNode + save_urlnode_render = URLNode.render + old_settings = _swap_settings(new_settings) + try: + URLNode.render = _urlnode_render_replacement + return orig_render(context) + finally: + _swap_settings(old_settings) + URLNode.render = save_urlnode_render + + template.render = wrap_render + + return template + + +def _swap_settings(new): + """Swap in selected Django settings, returning old settings. + + Example: + save = _swap_settings({'X': 1, 'Y': 2}) + try: + ...new settings for X and Y are in effect here... + finally: + _swap_settings(save) + + Args: + new: A dict containing settings to change; the keys should + be setting names and the values settings values. + + Returns: + Another dict structured the same was as the argument containing + the original settings. Original settings that were not set at all + are returned as None, and will be restored as None by the + 'finally' clause in the example above. This shouldn't matter; we + can't delete settings that are given as None, since None is also a + legitimate value for some settings. Creating a separate flag value + for 'unset' settings seems overkill as there is no known use case. + """ + settings = django.conf.settings + old = {} + for key, value in new.iteritems(): + old[key] = getattr(settings, key, None) + setattr(settings, key, value) + return old + + +def create_template_register(): + """Used to extend the Django template library with custom filters and tags. + + To extend the template library with a custom filter module, create a Python + module, and create a module-level variable named "register", and register + all custom filters to it as described at + http://www.djangoproject.com/documentation/templates_python/ + #extending-the-template-system: + + templatefilters.py + ================== + register = webapp.template.create_template_register() + + def cut(value, arg): + return value.replace(arg, '') + register.filter(cut) + + Then, register the custom template module with the register_template_module + function below in your application module: + + myapp.py + ======== + webapp.template.register_template_module('templatefilters') + """ + return django.template.Library() + + +def register_template_library(package_name): + """Registers a template extension module to make it usable in templates. + + See the documentation for create_template_register for more information.""" + if not django.template.libraries.get(package_name, None): + django.template.add_to_builtins(package_name) + + +Template = django.template.Template +Context = django.template.Context + + +def _urlnode_render_replacement(self, context): + """Replacement for django's {% url %} block. + + This version uses WSGIApplication's url mapping to create urls. + + Examples: + + + {% url MyPageHandler implicit_args=False %} + {% url MyPageHandler "calendar" %} + {% url MyPageHandler "jsmith","calendar" %} + """ + args = [arg.resolve(context) for arg in self.args] + try: + app = webapp.WSGIApplication.active_instance + handler = app.get_registered_handler_by_name(self.view_name) + return handler.get_url(implicit_args=True, *args) + except webapp.NoUrlFoundError: + return ''