Merge branch 'templating'

Conflicts:
	tests/test_base.py
This commit is contained in:
Mark McClain
2011-01-04 15:15:02 -05:00
4 changed files with 148 additions and 57 deletions

View File

@@ -1,6 +1,6 @@
from configuration import _runtime_conf from configuration import _runtime_conf
from monitor import MonitorableProcess from monitor import MonitorableProcess
from templating import renderers from templating import RendererFactory
from routing import lookup_controller from routing import lookup_controller
from webob import Request, Response, exc from webob import Request, Response, exc
@@ -62,13 +62,15 @@ def error_for(field):
class Pecan(MonitorableProcess): class Pecan(MonitorableProcess):
def __init__(self, root, def __init__(self, root,
renderers = renderers, default_renderer = 'mako',
default_renderer = 'kajiki', template_path = 'templates',
template_path = 'templates', hooks = [],
hooks = []): custom_renderers = {},
extra_template_vars = {}
):
self.root = root self.root = root
self.renderers = renderers self.renderers = RendererFactory(custom_renderers, extra_template_vars)
self.default_renderer = default_renderer self.default_renderer = default_renderer
self.hooks = hooks self.hooks = hooks
self.template_path = template_path self.template_path = template_path
@@ -289,4 +291,4 @@ class Pecan(MonitorableProcess):
del state.response del state.response
del state.hooks del state.hooks
if hasattr(state, 'controller'): if hasattr(state, 'controller'):
del state.controller del state.controller

View File

@@ -1,26 +1,6 @@
__all__ = ['renderers'] __all__ = ['RendererFactory']
_renderers = {} _builtin_renderers = {}
class RendererFactory(object):
def create(self, name, template_path):
if name == 'genshi':
return GenshiRenderer(template_path)
elif name == 'kajiki':
return KajikiRenderer(template_path)
elif name == 'mako':
return MakoRenderer(template_path)
elif name == 'json':
return JsonRenderer(template_path)
def get(self, name, template_path):
key = name+template_path
if key not in _renderers:
_renderers[key] = self.create(name, template_path)
return _renderers[key]
renderers = RendererFactory()
# #
# JSON rendering engine # JSON rendering engine
@@ -29,59 +9,130 @@ renderers = RendererFactory()
class JsonRenderer(object): class JsonRenderer(object):
content_type = 'application/json' content_type = 'application/json'
def __init__(self, path): def __init__(self, path, extra_vars):
pass pass
def render(self, template_path, namespace): def render(self, template_path, namespace):
from jsonify import encode from jsonify import encode
return encode(namespace) return encode(namespace)
_builtin_renderers['json'] = JsonRenderer
# #
# Genshi rendering engine # Genshi rendering engine
# #
class GenshiRenderer(object): try:
content_type = 'text/html' from genshi.template import TemplateLoader
def __init__(self, path): class GenshiRenderer(object):
from genshi.template import TemplateLoader content_type = 'text/html'
self.loader = TemplateLoader([path], auto_reload=True)
def __init__(self, path, extra_vars):
self.loader = TemplateLoader([path], auto_reload=True)
self.extra_vars = extra_vars
def render(self, template_path, namespace): def render(self, template_path, namespace):
tmpl = self.loader.load(template_path) tmpl = self.loader.load(template_path)
stream = tmpl.generate(**namespace) stream = tmpl.generate(**self.extra_vars.make_ns(namespace))
return stream.render('html') return stream.render('html')
_builtin_renderers['genshi'] = GenshiRenderer
except ImportError: #pragma no cover
pass
# #
# Mako rendering engine # Mako rendering engine
# #
class MakoRenderer(object): try:
content_type = 'text/html' from mako.lookup import TemplateLookup
def __init__(self, path): class MakoRenderer(object):
from mako.lookup import TemplateLookup content_type = 'text/html'
self.loader = TemplateLookup(directories=[path])
def __init__(self, path, extra_vars):
self.loader = TemplateLookup(directories=[path])
self.extra_vars = extra_vars
def render(self, template_path, namespace): def render(self, template_path, namespace):
tmpl = self.loader.get_template(template_path) tmpl = self.loader.get_template(template_path)
return tmpl.render(**namespace) return tmpl.render(**self.extra_vars.make_ns(namespace))
_builtin_renderers['mako'] = MakoRenderer
except ImportError: # pragma no cover
pass
# #
# Kajiki rendering engine # Kajiki rendering engine
# #
class KajikiRenderer(object): try:
content_type = 'text/html' from kajiki.loader import FileLoader
def __init__(self, path): class KajikiRenderer(object):
from kajiki.loader import FileLoader content_type = 'text/html'
self.loader = FileLoader(path, reload=True)
def __init__(self, path, extra_vars):
self.loader = FileLoader(path, reload=True)
self.extra_vars = extra_vars
def render(self, template_path, namespace): def render(self, template_path, namespace):
Template = self.loader.import_(template_path) Template = self.loader.import_(template_path)
stream = Template(namespace) stream = Template(self.extra_vars.make_ns(namespace))
return stream.render() return stream.render()
_builtin_renderers['kajiki'] = KajikiRenderer
except ImportError: # pragma no cover
pass
#
# Extra Vars Rendering
#
class ExtraNamespace(object):
def __init__(self, extras={}):
self.namespace = dict(extras)
def update(self, d):
self.namespace.update(d)
def make_ns(self, ns):
if self.namespace:
retval = {}
retval.update(self.namespace)
retval.update(ns)
return retval
else:
return ns
#
# Rendering Factory
#
class RendererFactory(object):
def __init__(self, custom_renderers={}, extra_vars={}):
self._renderers = {}
self._renderer_classes = dict(_builtin_renderers)
self.add_renderers(custom_renderers)
self.extra_vars = ExtraNamespace(extra_vars)
def add_renderers(self, custom_dict):
self._renderer_classes.update(custom_dict)
def available(self, name):
return name in self._renderer_classes
def create(self, name, template_path):
cls = self._renderer_classes.get(name)
if cls is None:
return None
else:
return cls(template_path, self.extra_vars)
def get(self, name, template_path):
key = name+template_path
if key not in self._renderers:
self._renderers[key] = self.create(name, template_path)
return self._renderers[key]

View File

@@ -1,5 +1,7 @@
import os import os
from pecan import Pecan, expose, request, redirect, abort from pecan import Pecan, expose, request, redirect, abort
from pecan import Pecan, expose, request, redirect, abort
from pecan.templating import _builtin_renderers as builtin_renderers
from webtest import TestApp from webtest import TestApp
from formencode import Schema, validators from formencode import Schema, validators
@@ -122,6 +124,9 @@ class TestEngines(object):
template_path = os.path.join(os.path.dirname(__file__), 'templates') template_path = os.path.join(os.path.dirname(__file__), 'templates')
def test_genshi(self): def test_genshi(self):
if 'genshi' not in builtin_renderers:
return
class RootController(object): class RootController(object):
@expose('genshi:genshi.html') @expose('genshi:genshi.html')
def index(self, name='Jonathan'): def index(self, name='Jonathan'):
@@ -138,6 +143,9 @@ class TestEngines(object):
assert "<h1>Hello, World!</h1>" in r.body assert "<h1>Hello, World!</h1>" in r.body
def test_kajiki(self): def test_kajiki(self):
if 'kajiki' not in builtin_renderers:
return
class RootController(object): class RootController(object):
@expose('kajiki:kajiki.html') @expose('kajiki:kajiki.html')
def index(self, name='Jonathan'): def index(self, name='Jonathan'):
@@ -152,8 +160,10 @@ class TestEngines(object):
r = app.get('/index.html?name=World') r = app.get('/index.html?name=World')
assert r.status_int == 200 assert r.status_int == 200
assert "<h1>Hello, World!</h1>" in r.body assert "<h1>Hello, World!</h1>" in r.body
def test_mako(self): def test_mako(self):
if 'mako' not in builtin_renderers:
return
class RootController(object): class RootController(object):
@expose('mako:mako.html') @expose('mako:mako.html')
def index(self, name='Jonathan'): def index(self, name='Jonathan'):

28
tests/test_templating.py Normal file
View File

@@ -0,0 +1,28 @@
from unittest import TestCase
from pecan.templating import RendererFactory
class TestTemplate(TestCase):
def setUp(self):
self.rf = RendererFactory()
def test_available(self):
self.assertTrue(self.rf.available('json'))
self.assertFalse(self.rf.available('badrenderer'))
def test_create_bad(self):
self.assertEqual(self.rf.get('doesnotexist', '/'), None)
def test_extra_vars(self):
extra_vars = self.rf.extra_vars
self.assertEqual(extra_vars.make_ns({}), {})
extra_vars.update({'foo': 1})
self.assertEqual(extra_vars.make_ns({}), {'foo':1})
def test_update_extra_vars(self):
extra_vars = self.rf.extra_vars
extra_vars.update({'foo': 1})
self.assertEqual(extra_vars.make_ns({'bar':2}), {'foo':1, 'bar':2})
self.assertEqual(extra_vars.make_ns({'foo':2}), {'foo':2})