diff --git a/pecan/templating.py b/pecan/templating.py index 385e106..d76ddcc 100644 --- a/pecan/templating.py +++ b/pecan/templating.py @@ -91,6 +91,37 @@ try: except ImportError: # pragma no cover pass +# +# Jinja2 rendering engine +# +try: + from jinja2 import Environment, FileSystemLoader + from jinja2 import exceptions as jinja_exceptions + + class JinjaRenderer(object): + def __init__(self, path, extra_vars): + self.env = Environment(loader=FileSystemLoader(path)) + self.extra_vars = extra_vars + + def render(self, template_path, namespace): + template = self.env.get_template(template_path) + return template.render(self.extra_vars.make_ns(namespace)) + _builtin_renderers['jinja'] = JinjaRenderer + + def format_jinja_error(exc_value): + import cgi + if isinstance(exc_value, (jinja_exceptions.TemplateSyntaxError)): + retval = '

Jinja2 template syntax error in \'%s\' on line %d

' % (exc_value.name, exc_value.lineno) + lines = [cgi.escape(x) for x in open(exc_value.filename)] + lineno = exc_value.lineno - 1 # files are 1 not 0 index + lines[lineno] = '%s' % lines[lineno] + + retval +='
%s
' % '
'.join(lines) + return retval + error_formatters.append(format_jinja_error) +except ImportError: # pragma no cover + pass + # # Extra Vars Rendering # diff --git a/tests/templates/jinja.html b/tests/templates/jinja.html new file mode 100644 index 0000000..e96835a --- /dev/null +++ b/tests/templates/jinja.html @@ -0,0 +1,11 @@ + + + + Hello, {{name}}! + + + +

Hello, {{name}}!

+ + + diff --git a/tests/templates/jinja_bad.html b/tests/templates/jinja_bad.html new file mode 100644 index 0000000..db01676 --- /dev/null +++ b/tests/templates/jinja_bad.html @@ -0,0 +1,12 @@ + + + + Hello, {{name}}! + + + +

Hello, {{name}}!

+ +{% block %} + + diff --git a/tests/test_base.py b/tests/test_base.py index ff80beb..b1b8039 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -706,6 +706,33 @@ class TestEngines(object): r = app.get('/index.html?name=World') assert r.status_int == 200 assert "

Hello, World!

" in r.body + + def test_jinja(self): + if 'jinja' not in builtin_renderers: + return + class RootController(object): + @expose('jinja:jinja.html') + def index(self, name='Jonathan'): + return dict(name=name) + + @expose('jinja:jinja_bad.html') + def badtemplate(self): + return dict() + + app = TestApp(Pecan(RootController(), template_path=self.template_path)) + r = app.get('/') + assert r.status_int == 200 + assert "

Hello, Jonathan!

" in r.body + + error_msg = None + try: + r = app.get('/badtemplate.html') + except Exception, e: + for error_f in error_formatters: + error_msg = error_f(e) + if error_msg: + break + assert error_msg is not None def test_mako(self): if 'mako' not in builtin_renderers: @@ -724,7 +751,6 @@ class TestEngines(object): assert r.status_int == 200 assert "

Hello, Jonathan!

" in r.body - app = TestApp(Pecan(RootController(), template_path=self.template_path)) r = app.get('/index.html?name=World') assert r.status_int == 200 assert "

Hello, World!

" in r.body