Josip Delic <delij...@gmail.com> added the comment:
sorry for the late response. i moved from freiburg to hamburg.
i looked a little bit closer at the implementation in chameleon_zpt.py. I've
changed my code to work like it. I've added a first version of my changes,
waiting for feedback ;-)
__________________________________
Repoze Bugs <b...@bugs.repoze.org>
<http://bugs.repoze.org/issue97>
__________________________________
Index: repoze/bfg/jinja2/tests/templates_more/hellomacro.jinja2
===================================================================
--- repoze/bfg/jinja2/tests/templates_more/hellomacro.jinja2 (Revision 0)
+++ repoze/bfg/jinja2/tests/templates_more/hellomacro.jinja2 (Revision 0)
@@ -0,0 +1,5 @@
+{% import 'hellomacro.macro_jinja2' as macro %}
+{{ macro.foo('delijati') }}
+
+{% import 'hellomacromore.macro_jinja2' as macro2 %}
+{{ macro2.foo('jatideli') }}
Index: repoze/bfg/jinja2/tests/templates_more/hellomacromore.macro_jinja2
===================================================================
--- repoze/bfg/jinja2/tests/templates_more/hellomacromore.macro_jinja2 (Revision 0)
+++ repoze/bfg/jinja2/tests/templates_more/hellomacromore.macro_jinja2 (Revision 0)
@@ -0,0 +1,5 @@
+{% macro foo(name) -%}
+ Hello {{ name }}
+{%- endmacro %}
+
+
Index: repoze/bfg/jinja2/tests/test_bindings.py
===================================================================
--- repoze/bfg/jinja2/tests/test_bindings.py (Revision 6678)
+++ repoze/bfg/jinja2/tests/test_bindings.py (Arbeitskopie)
@@ -1,146 +1,204 @@
-import os.path
import unittest
-from repoze.bfg import testing
-class TestAutoReload(unittest.TestCase):
+from repoze.bfg.testing import cleanUp
+
+class Base(object):
def setUp(self):
- testing.cleanUp()
+ cleanUp()
def tearDown(self):
- testing.cleanUp()
-
- def _callFUT(self):
- from repoze.bfg.jinja2.bindings import _auto_reload
- return _auto_reload()
+ cleanUp()
- def test_true(self):
- from repoze.bfg.interfaces import ISettings
- class Settings:
- reload_templates = True
- settings = Settings()
- testing.registerUtility(settings, ISettings)
- self.assertEqual(self._callFUT(), True)
+ def _getTemplatePath(self, name):
+ import os
+ here = os.path.abspath(os.path.dirname(__file__))
+ return os.path.join(here, 'templates', name)
- def test_false(self):
- from repoze.bfg.interfaces import ISettings
- class Settings:
- reload_templates = True
- settings = Settings()
- testing.registerUtility(settings, ISettings)
- self.assertEqual(self._callFUT(), True)
+class JINJA2TemplateRenderer(Base, unittest.TestCase):
+ def _getTargetClass(self):
+ from repoze.bfg.jinja2.bindings import JINJA2TemplateRenderer
+ return JINJA2TemplateRenderer
- def test_unregistered(self):
- self.assertEqual(self._callFUT(), False)
+ def _makeOne(self, *arg, **kw):
+ klass = self._getTargetClass()
+ return klass(*arg, **kw)
-class TestLoadTemplate(unittest.TestCase):
- def _callFUT(self, path):
- from repoze.bfg.jinja2.bindings import load_template
- return load_template(path)
+ def test_instance_implements_ITemplate(self):
+ from zope.interface.verify import verifyObject
+ from repoze.bfg.interfaces import ITemplateRenderer
+ path = self._getTemplatePath('helloworld.jinja2')
+ verifyObject(ITemplateRenderer, self._makeOne(path))
+
+ def test_class_implements_ITemplate(self):
+ from zope.interface.verify import verifyClass
+ from repoze.bfg.interfaces import ITemplateRenderer
+ verifyClass(ITemplateRenderer, self._getTargetClass())
+
+ def test_call(self):
+ minimal = self._getTemplatePath('helloworld.jinja2')
+ instance = self._makeOne(minimal)
+ result = instance({}, {})
+ self.failUnless(isinstance(result, unicode))
+ self.assertEqual(result, u'\nHello f\xf6\xf6')
+
+ def test_call_with_nondict_value(self):
+ minimal = self._getTemplatePath('helloworld.jinja2')
+ instance = self._makeOne(minimal)
+ self.assertRaises(ValueError, instance, None, {})
+
+ def test_implementation(self):
+ minimal = self._getTemplatePath('helloworld.jinja2')
+ instance = self._makeOne(minimal)
+ result = instance.implementation().render()
+ self.failUnless(isinstance(result, unicode))
+ self.assertEqual(result, u'\nHello f\xf6\xf6')
- def test_load_template(self):
- template = self._callFUT('templates/helloworld.jinja2')
- self.assertEqual(template[0],
- u"{% set a, b = 'foo', 'f\xf6\xf6' %}\nHello {{ b }}\n")
- self.assert_(
- template[1].endswith('tests/templates/helloworld.jinja2')
- )
- uptodate = template[2]
- self.assertEqual(uptodate(), True)
- def test_load_template_deleted_template_uptodate(self):
- name = 'templates/to_delete.jinja2'
- path = os.path.join(os.path.dirname(__file__), name)
- f = open(path, 'w')
- f.write('')
- f.close()
- template = self._callFUT(name)
- uptodate = template[2]
- self.assertEqual(uptodate(), True)
- os.unlink(path)
- self.assertEqual(uptodate(), False)
- self.assertEqual(self._callFUT(name), None)
+class RenderTemplateTests(Base, unittest.TestCase):
+ def _callFUT(self, name, **kw):
+ from repoze.bfg.jinja2.bindings import render_template
+ return render_template(name, **kw)
- def test_load_template_nonexistent_template(self):
- from repoze.bfg.jinja2.bindings import load_template
- name = 'templates/nonexistent.jinja2'
- path = os.path.join(os.path.dirname(__file__), name)
- self.assertEqual(load_template(name), None)
-
-class TestBfgLoader(unittest.TestCase):
- def _getTargetClass(self):
- from repoze.bfg.jinja2.bindings import BfgLoader
- return BfgLoader
+ def test_it(self):
+ rendering = self._callFUT('templates/helloworld.jinja2')
+ self.assertEqual(rendering, u'\nHello f\xf6\xf6')
- def _makeOne(self, load_func):
- return self._getTargetClass()(load_func)
- def test_get_source_autoreload_None_default(self):
- def load_func(path):
- return u'123'
- loader = self._makeOne(load_func)
- class Environment:
- auto_reload = False
- environ = Environment()
- result = loader.get_source(environ, 'whatever')
- self.assertEqual(loader.auto_reload, False)
- self.assertEqual(result, (u'123', None, None))
- self.assertEqual(environ.auto_reload, False)
+class RenderTemplateToResponseTests(Base, unittest.TestCase):
+ def _callFUT(self, name, **kw):
+ from repoze.bfg.jinja2.bindings import render_template_to_response
+ return render_template_to_response(name, **kw)
- def test_get_source_autoreload_None_withisettings(self):
- def load_func(path):
- return u'123'
- loader = self._makeOne(load_func)
- class Environment:
- auto_reload = False
- environ = Environment()
- from repoze.bfg.interfaces import ISettings
- class Settings:
- reload_templates = True
- settings = Settings()
- testing.registerUtility(settings, ISettings)
- result = loader.get_source(environ, 'whatever')
- self.assertEqual(loader.auto_reload, True)
- self.assertEqual(result, (u'123', None, None))
- self.assertEqual(environ.auto_reload, True)
+ def test_it(self):
+ minimal = self._getTemplatePath('helloworld.jinja2')
+ result = self._callFUT(minimal)
+ from webob import Response
+ self.failUnless(isinstance(result, Response))
+ self.assertEqual(result.app_iter,
+ ['\nHello f\xc3\xb6\xc3\xb6'])
+ self.assertEqual(result.status, '200 OK')
+ self.assertEqual(len(result.headerlist), 2)
- def test_get_source_autoreload_true(self):
- def load_func(path):
- return u'123'
- loader = self._makeOne(load_func)
- loader.auto_reload = True
- class Environment:
- auto_reload = False
- environ = Environment()
- result = loader.get_source(environ, 'whatever')
- self.assertEqual(result, (u'123', None, None))
- self.assertEqual(environ.auto_reload, True)
+ def test_iresponsefactory_override(self):
+ from zope.component import getGlobalSiteManager
+ gsm = getGlobalSiteManager()
+ from webob import Response
+ class Response2(Response):
+ pass
+ from repoze.bfg.interfaces import IResponseFactory
+ gsm.registerUtility(Response2, IResponseFactory)
+ minimal = self._getTemplatePath('helloworld.jinja2')
+ result = self._callFUT(minimal)
+ self.failUnless(isinstance(result, Response2))
-class TestGetTemplate(unittest.TestCase):
- def _callFUT(self, path):
+class GetRendererTests(Base, unittest.TestCase):
+ def _callFUT(self, name):
+ from repoze.bfg.jinja2.bindings import get_renderer
+ return get_renderer(name)
+
+ def test_nonabs_registered(self):
+ from zope.component import getGlobalSiteManager
+ from zope.component import queryUtility
+ from repoze.bfg.jinja2.bindings import JINJA2TemplateRenderer
+ from repoze.bfg.interfaces import ITemplateRenderer
+ minimal = self._getTemplatePath('helloworld.jinja2')
+ utility = JINJA2TemplateRenderer(minimal)
+ gsm = getGlobalSiteManager()
+ gsm.registerUtility(utility, ITemplateRenderer, name=minimal)
+ result = self._callFUT(minimal)
+ self.assertEqual(result, utility)
+ self.assertEqual(queryUtility(ITemplateRenderer, minimal), utility)
+
+ def test_nonabs_unregistered(self):
+ from zope.component import getGlobalSiteManager
+ from zope.component import queryUtility
+ from repoze.bfg.jinja2.bindings import JINJA2TemplateRenderer
+ from repoze.bfg.interfaces import ITemplateRenderer
+ minimal = self._getTemplatePath('helloworld.jinja2')
+ self.assertEqual(queryUtility(ITemplateRenderer, minimal), None)
+ utility = JINJA2TemplateRenderer(minimal)
+ gsm = getGlobalSiteManager()
+ gsm.registerUtility(utility, ITemplateRenderer, name=minimal)
+ result = self._callFUT(minimal)
+ self.assertEqual(result, utility)
+ self.assertEqual(queryUtility(ITemplateRenderer, minimal), utility)
+
+ def test_explicit_registration(self):
+ from zope.component import getGlobalSiteManager
+ from repoze.bfg.interfaces import ITemplateRenderer
+ class Dummy:
+ template = object()
+ gsm = getGlobalSiteManager()
+ utility = Dummy()
+ gsm.registerUtility(utility, ITemplateRenderer, name='foo')
+ result = self._callFUT('foo')
+ self.failUnless(result is utility)
+
+class GetTemplateTests(Base, unittest.TestCase):
+ def _callFUT(self, name):
from repoze.bfg.jinja2.bindings import get_template
- return get_template(path)
+ return get_template(name)
+
+ def test_nonabs_registered(self):
+ from zope.component import getGlobalSiteManager
+ from zope.component import queryUtility
+ from repoze.bfg.jinja2.bindings import JINJA2TemplateRenderer
+ from repoze.bfg.interfaces import ITemplateRenderer
+ minimal = self._getTemplatePath('helloworld.jinja2')
+ utility = JINJA2TemplateRenderer(minimal)
+ gsm = getGlobalSiteManager()
+ gsm.registerUtility(utility, ITemplateRenderer, name=minimal)
+ result = self._callFUT(minimal)
+ self.assertEqual(result.filename, minimal)
+ self.assertEqual(queryUtility(ITemplateRenderer, minimal), utility)
- def test_it(self):
- template = self._callFUT('templates/helloworld.jinja2')
- self.assertEqual(template.module.a, 'foo')
- self.assertEqual(template.module.b, u'f\xf6\xf6')
+ def test_nonabs_unregistered(self):
+ from zope.component import getGlobalSiteManager
+ from zope.component import queryUtility
+ from repoze.bfg.jinja2.bindings import JINJA2TemplateRenderer
+ from repoze.bfg.interfaces import ITemplateRenderer
+ minimal = self._getTemplatePath('helloworld.jinja2')
+ self.assertEqual(queryUtility(ITemplateRenderer, minimal), None)
+ utility = JINJA2TemplateRenderer(minimal)
+ gsm = getGlobalSiteManager()
+ gsm.registerUtility(utility, ITemplateRenderer, name=minimal)
+ result = self._callFUT(minimal)
+ self.assertEqual(result.filename, minimal)
+ self.assertEqual(queryUtility(ITemplateRenderer, minimal), utility)
-class TestRenderTemplate(unittest.TestCase):
+ def test_explicit_registration(self):
+ from zope.component import getGlobalSiteManager
+ from repoze.bfg.interfaces import ITemplateRenderer
+ class Dummy:
+ template = object()
+ def implementation(self):
+ return self.template
+ gsm = getGlobalSiteManager()
+ utility = Dummy()
+ gsm.registerUtility(utility, ITemplateRenderer, name='foo')
+ result = self._callFUT('foo')
+ self.failUnless(result is utility.template)
+
+class TestRenderMacroTemplate(unittest.TestCase):
def _callFUT(self, path):
from repoze.bfg.jinja2.bindings import render_template
return render_template(path)
-
+
def test_it(self):
- rendering = self._callFUT('templates/helloworld.jinja2')
- self.assertEqual(rendering, u'\nHello f\xf6\xf6')
-
-class TestRenderTemplateToResponse(unittest.TestCase):
+ rendering = self._callFUT('templates/hellomacro.jinja2')
+ self.assertEqual(rendering, u'\nHello delijati\n')
+
+class TestRenderMacroTemplateMore(unittest.TestCase):
def _callFUT(self, path):
- from repoze.bfg.jinja2.bindings import render_template_to_response
- return render_template_to_response(path)
+ from repoze.bfg.jinja2.bindings import render_template
+ return render_template(path)
def test_it(self):
- response = self._callFUT('templates/helloworld.jinja2')
- self.assertEqual(response.app_iter[0],
- u'\nHello f\xf6\xf6'.encode('utf-8'))
+ rendering = self._callFUT('templates_more/hellomacro.jinja2')
+ self.assertEqual(rendering, u'\nHello delijati\n\n\nHello jatideli')
+
+
+
+
+
Index: repoze/bfg/jinja2/tests/templates/hellomacro.jinja2
===================================================================
--- repoze/bfg/jinja2/tests/templates/hellomacro.jinja2 (Revision 0)
+++ repoze/bfg/jinja2/tests/templates/hellomacro.jinja2 (Revision 0)
@@ -0,0 +1,3 @@
+{% import 'hellomacro.macro_jinja2' as macro %}
+{{ macro.foo('delijati') }}
+
Index: repoze/bfg/jinja2/tests/templates/hellomacro.macro_jinja2
===================================================================
--- repoze/bfg/jinja2/tests/templates/hellomacro.macro_jinja2 (Revision 0)
+++ repoze/bfg/jinja2/tests/templates/hellomacro.macro_jinja2 (Revision 0)
@@ -0,0 +1,5 @@
+{% macro foo(name) -%}
+ Hello {{ name }}
+{%- endmacro %}
+
+
Index: repoze/bfg/jinja2/bindings.py
===================================================================
--- repoze/bfg/jinja2/bindings.py (Revision 6678)
+++ repoze/bfg/jinja2/bindings.py (Arbeitskopie)
@@ -1,30 +1,31 @@
-from os.path import getmtime
-
from webob import Response
from zope.component import queryUtility
+from zope.interface import implements
-from repoze.bfg.interfaces import ISettings
-from repoze.bfg.path import caller_path
+from repoze.bfg.interfaces import IResponseFactory
+from repoze.bfg.interfaces import ITemplateRenderer
+from repoze.bfg.renderers import template_renderer_factory
+from repoze.bfg.settings import get_settings
+
from jinja2.loaders import FunctionLoader
-from jinja2 import Environment
+from jinja2 import Environment, ChoiceLoader, FileSystemLoader
+import os
-def _auto_reload():
- settings = queryUtility(ISettings)
- auto_reload = (settings and settings.reload_templates) or False
- return auto_reload
-
+def renderer_factory(path, level=4):
+ return template_renderer_factory(path, JINJA2TemplateRenderer, level=4)
+
def load_template(path):
- path = caller_path(path)
+ #path = caller_path(path)
try:
data = open(path, 'rb').read()
- mtime = getmtime(path)
+ mtime = os.path.getmtime(path)
except (OSError, IOError):
return None
def uptodate():
try:
- return getmtime(path) == mtime
+ return os.path.getmtime(path) == mtime
except (OSError, IOError):
return False
return unicode(data, 'utf-8'), path, uptodate
@@ -34,33 +35,74 @@
Extends jinja2.loaders.FunctionLoader with configurable auto-reloading.
"""
auto_reload = None
+
def get_source(self, environment, template):
if self.auto_reload is None:
- self.auto_reload = _auto_reload()
+ settings = get_settings()
+ self.auto_reload = settings and settings['reload_templates']
environment.auto_reload = self.auto_reload
return super(BfgLoader, self).get_source(environment, template)
-
-env = Environment(loader=BfgLoader(load_template))
+class JINJA2TemplateRenderer(object):
+ implements(ITemplateRenderer)
+
+ loader_array = []
+ env = None
+ path = ""
+
+ def __init__(self, path):
+ self.loader_array.append(BfgLoader(load_template))
+ settings = get_settings()
+ auto_reload = settings and settings['reload_templates']
+ self.path = path
+ self.env = Environment(loader=ChoiceLoader(self.loader_array))
+
+ def implementation(self):
+ fsla = [loa for loa in self.env.loader.loaders if isinstance(loa, FileSystemLoader)]
+ if len(fsla) == 0:
+ self.env.loader.loaders.append(FileSystemLoader(os.path.dirname(self.path)))
+ else:
+ # searchpath is an array
+ fsl = [loa for loa in fsla if os.path.dirname(self.path) not in loa.searchpath ]
+ if len(fsl) == len(fsla):
+ self.env.loader.loaders.append(FileSystemLoader(os.path.dirname(self.path)))
+
+ return self.env.get_template(self.path)
+
+ def __call__(self, value, system):
+ try:
+ system.update(value)
+ except (TypeError, ValueError):
+ raise ValueError('renderer was passed non-dictionary as value')
+ result = self.implementation().render(**system)
+ return result
+
+def get_renderer(path):
+ """ Return a callable ``ITemplateRenderer`` object representing a
+ ``chameleon.zpt`` template at the package-relative path (may also
+ be absolute). """
+ return renderer_factory(path)
+
def get_template(path):
- """ Return a z3c.pt template object at the package-relative path
- (may also be absolute) """
- path = caller_path(path)
- return env.get_template(path)
+ """ Return a ``chameleon.zpt`` template at the package-relative
+ path (may also be absolute). """
+ renderer = renderer_factory(path)
+ return renderer.implementation()
def render_template(path, **kw):
- """ Render a z3c.pt (ZPT) template at the package-relative path
- (may also be absolute) using the kwargs in ``*kw`` as top-level
- names and return a string. """
- path = caller_path(path)
- template = get_template(path)
- return template.render(**kw)
+ """ Render a ``chameleon.zpt`` template at the package-relative
+ path (may also be absolute) using the kwargs in ``*kw`` as
+ top-level names and return a string."""
+ renderer = renderer_factory(path)
+ return renderer(kw, {})
def render_template_to_response(path, **kw):
- """ Render a z3c.pt (ZPT) template at the package-relative path
- (may also be absolute) using the kwargs in ``*kw`` as top-level
- names and return a Response object. """
- path = caller_path(path)
- result = render_template(path, **kw)
- return Response(result)
+ """ Render a ``chameleon.zpt`` template at the package-relative
+ path (may also be absolute) using the kwargs in ``*kw`` as
+ top-level names and return a Response object with the body as the
+ template result. """
+ renderer = renderer_factory(path)
+ result = renderer(kw, {})
+ response_factory = queryUtility(IResponseFactory, default=Response)
+ return response_factory(result)
Index: CHANGES.txt
===================================================================
--- CHANGES.txt (Revision 6678)
+++ CHANGES.txt (Arbeitskopie)
@@ -3,7 +3,8 @@
Next release
------------
-
+- added macro support, now it also add the template folder
+- changed implementation to work like in chamelon_zpt.py
- Respect ``reload_templates`` option in BFG.
0.3 (2009-05-03)
_______________________________________________
Repoze-dev mailing list
Repoze-dev@lists.repoze.org
http://lists.repoze.org/listinfo/repoze-dev