changes for templating refactor

This commit is contained in:
Mark McClain
2011-01-04 15:10:21 -05:00
parent 618cbb6e3e
commit 0b8b22d380
4 changed files with 106 additions and 51 deletions

View File

@@ -62,14 +62,15 @@ def error_for(field):
class Pecan(MonitorableProcess): class Pecan(MonitorableProcess):
def __init__(self, root, def __init__(self, root,
default_renderer = 'kajiki', default_renderer = 'mako',
template_path = 'templates', template_path = 'templates',
hooks = [], hooks = [],
custom_renderers = {}, custom_renderers = {},
extra_template_vars = {}
): ):
self.root = root self.root = root
self.renderers = RendererFactory(custom_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

View File

@@ -1,5 +1,6 @@
__all__ = ['renderers'] __all__ = ['RendererFactory']
_builtin_renderers = {}
# #
# JSON rendering engine # JSON rendering engine
@@ -8,72 +9,91 @@ __all__ = ['renderers']
class JsonRenderer(object): class JsonRenderer(object):
content_type = 'application/json' content_type = 'application/json'
def __init__(self, path, context): 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
# #
try:
from genshi.template import TemplateLoader
class GenshiRenderer(object): class GenshiRenderer(object):
content_type = 'text/html' content_type = 'text/html'
def __init__(self, path, context): def __init__(self, path, extra_vars):
from genshi.template import TemplateLoader
self.loader = TemplateLoader([path], auto_reload=True) self.loader = TemplateLoader([path], auto_reload=True)
self.context = context 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(**self.context.make_ns(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
# #
try:
from mako.lookup import TemplateLookup
class MakoRenderer(object): class MakoRenderer(object):
content_type = 'text/html' content_type = 'text/html'
def __init__(self, path, context): def __init__(self, path, extra_vars):
from mako.lookup import TemplateLookup
self.loader = TemplateLookup(directories=[path]) self.loader = TemplateLookup(directories=[path])
self.context = context 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(**self.context.make_ns(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
# #
try:
from kajiki.loader import FileLoader
class KajikiRenderer(object): class KajikiRenderer(object):
content_type = 'text/html' content_type = 'text/html'
def __init__(self, path, context): def __init__(self, path, extra_vars):
from kajiki.loader import FileLoader
self.loader = FileLoader(path, reload=True) self.loader = FileLoader(path, reload=True)
self.context = context 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(self.context.make_ns(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
# #
# Rendering Context # Extra Vars Rendering
# #
class RenderingContext(object): class ExtraNamespace(object):
def __init__(self, globals={}): def __init__(self, extras={}):
self.namespace = dict(globals) self.namespace = dict(extras)
def update(self, d): def update(self, d):
self.namespace.update(d) self.namespace.update(d)
@@ -91,28 +111,25 @@ class RenderingContext(object):
# Rendering Factory # Rendering Factory
# #
class RendererFactory(object): class RendererFactory(object):
def __init__(self, custom_renderers={}, extra_namespace={}): def __init__(self, custom_renderers={}, extra_vars={}):
self._renderers = {} self._renderers = {}
self._renderer_classes = { self._renderer_classes = dict(_builtin_renderers)
'genshi': GenshiRenderer,
'kajiki': KajikiRenderer,
'mako' : MakoRenderer,
'json' : JsonRenderer
}
self.add_renderers(custom_renderers) self.add_renderers(custom_renderers)
self.context = RenderingContext(extra_namespace) self.extra_vars = ExtraNamespace(extra_vars)
def add_renderers(self, custom_dict): def add_renderers(self, custom_dict):
self._renderer_classes.update(custom_dict) self._renderer_classes.update(custom_dict)
def available(self, name):
return name in self._renderer_classes
def create(self, name, template_path): def create(self, name, template_path):
cls = self._renderer_classes.get(name) cls = self._renderer_classes.get(name)
if cls is None: if cls is None:
return None return None
else: else:
return cls(template_path, self.context) return cls(template_path, self.extra_vars)
def get(self, name, template_path): def get(self, name, template_path):
key = name+template_path key = name+template_path

View File

@@ -1,5 +1,6 @@
import os import os
from pecan import Pecan, expose, request, response, redirect, abort from pecan import Pecan, expose, request, response, 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
@@ -104,6 +105,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'):
@@ -120,6 +124,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'):
@@ -136,6 +143,8 @@ class TestEngines(object):
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})