Merge branch 'templating'
Conflicts: tests/test_base.py
This commit is contained in:
@@ -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
|
||||||
|
@@ -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]
|
||||||
|
@@ -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
28
tests/test_templating.py
Normal 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})
|
Reference in New Issue
Block a user