diff options
| author | Paul Everitt <paul@agendaless.com> | 2008-07-16 16:55:42 +0000 |
|---|---|---|
| committer | Paul Everitt <paul@agendaless.com> | 2008-07-16 16:55:42 +0000 |
| commit | 231bc67350bd0269efce3203b83b76c7aa8d4eb1 (patch) | |
| tree | 3d908b33b995c7ce98b9e18a12bded7387440924 | |
| parent | 22eed6aa7e8938ec30908aface102d42541dd3b3 (diff) | |
| download | pyramid-231bc67350bd0269efce3203b83b76c7aa8d4eb1.tar.gz pyramid-231bc67350bd0269efce3203b83b76c7aa8d4eb1.tar.bz2 pyramid-231bc67350bd0269efce3203b83b76c7aa8d4eb1.zip | |
| -rw-r--r-- | repoze/bfg/template.py | 52 | ||||
| -rw-r--r-- | repoze/bfg/tests/fixtures/minimal.xsl | 6 | ||||
| -rw-r--r-- | repoze/bfg/tests/test_xslt.py | 123 |
3 files changed, 181 insertions, 0 deletions
diff --git a/repoze/bfg/template.py b/repoze/bfg/template.py index efb9f2c55..dd0778a43 100644 --- a/repoze/bfg/template.py +++ b/repoze/bfg/template.py @@ -26,6 +26,38 @@ class Z3CPTTemplateFactory(object): response = Response(result) return response +class XSLTemplateFactory(object): + classProvides(ITemplateFactory) + implements(IView) + + def __init__(self, path): + self.path = path + + def __call__(self, *arg, **kw): + node = kw.get("node") + processor = get_processor(self.path) + result = str(processor(node)) + response = Response(result) + return response + +# Manage XSLT processors on a per-thread basis +import threading +from lxml import etree +xslt_pool = threading.local() +def get_processor(xslt_fn): + try: + return xslt_pool.processors[xslt_fn] + except AttributeError: + xslt_pool.processors = {} + except KeyError: + pass + + # Make a processor and add it to the pool + source = etree.ElementTree(file=xslt_fn) + proc = etree.XSLT(source) + xslt_pool.processors[xslt_fn] = proc + return proc + def package_path(package): return os.path.abspath(os.path.dirname(package.__file__)) @@ -56,3 +88,23 @@ def render_template(path, **kw): registerTemplate(template, path) return template(**kw) + +def render_transform(path, **kw): + # Render using XSLT + + if not os.path.isabs(path): + package_globals = sys._getframe(1).f_globals + package_name = package_globals['__name__'] + package = sys.modules[package_name] + prefix = package_path(package) + path = os.path.join(prefix, path) + + template = queryUtility(IView, path) + node = kw.get("node") + if template is None: + if not os.path.exists(path): + raise ValueError('Missing template file: %s' % path) + template = XSLTemplateFactory(path) + registerTemplate(template, path) + + return template(**kw) diff --git a/repoze/bfg/tests/fixtures/minimal.xsl b/repoze/bfg/tests/fixtures/minimal.xsl new file mode 100644 index 000000000..56cebc643 --- /dev/null +++ b/repoze/bfg/tests/fixtures/minimal.xsl @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> + <xsl:template match="/"> + <div/> + </xsl:template> +</xsl:stylesheet> diff --git a/repoze/bfg/tests/test_xslt.py b/repoze/bfg/tests/test_xslt.py new file mode 100644 index 000000000..448d49ddc --- /dev/null +++ b/repoze/bfg/tests/test_xslt.py @@ -0,0 +1,123 @@ +import unittest + +from zope.component.testing import PlacelessSetup + +class Base(PlacelessSetup): + def setUp(self): + PlacelessSetup.setUp(self) + + def tearDown(self): + PlacelessSetup.tearDown(self) + + def _zcmlConfigure(self): + import repoze.bfg + import zope.configuration.xmlconfig + zope.configuration.xmlconfig.file('configure.zcml', package=repoze.bfg) + + def _getTemplatePath(self, name): + import os + here = os.path.abspath(os.path.dirname(__file__)) + return os.path.join(here, 'fixtures', name) + +class XSLTemplateFactoryTests(unittest.TestCase, Base): + def setUp(self): + Base.setUp(self) + + def tearDown(self): + Base.tearDown(self) + + def _getTargetClass(self): + from repoze.bfg.template import XSLTemplateFactory + return XSLTemplateFactory + + def _makeOne(self, *arg, **kw): + klass = self._getTargetClass() + return klass(*arg, **kw) + + def test_instance_conforms_to_IView(self): + from zope.interface.verify import verifyObject + from repoze.bfg.interfaces import IView + path = self._getTemplatePath('minimal.xsl') + verifyObject(IView, self._makeOne(path)) + + def test_class_conforms_to_IView(self): + from zope.interface.verify import verifyClass + from repoze.bfg.interfaces import IView + verifyClass(IView, self._getTargetClass()) + + def test_class_conforms_to_ITemplateFactory(self): + from zope.interface.verify import verifyObject + from repoze.bfg.interfaces import ITemplateFactory + verifyObject(ITemplateFactory, self._getTargetClass()) + + def test_call(self): + self._zcmlConfigure() + minimal = self._getTemplatePath('minimal.xsl') + instance = self._makeOne(minimal) + from lxml import etree + info = etree.Element("info") + result = instance(node=info) + from webob import Response + self.failUnless(isinstance(result, Response)) + resultstr = """<?xml version="1.0"?>\n<div/>\n""" + self.assertEqual(result.app_iter, [resultstr]) + self.assertEqual(result.status, '200 OK') + self.assertEqual(len(result.headerlist), 2) + +class RenderTemplateTests(unittest.TestCase, Base): + def setUp(self): + Base.setUp(self) + + def tearDown(self): + Base.tearDown(self) + + def _getFUT(self): + from repoze.bfg.template import render_transform + return render_transform + + def test_nonabs_unregistered(self): + self._zcmlConfigure() + from zope.component import queryUtility + from repoze.bfg.interfaces import IView + minimal = self._getTemplatePath('minimal.xsl') + self.assertEqual(queryUtility(IView, minimal), None) + render = self._getFUT() + from lxml import etree + info = etree.Element("info") + result = render(minimal, node=info) + from webob import Response + self.failUnless(isinstance(result, Response)) + resultstr = """<?xml version="1.0"?>\n<div/>\n""" + self.assertEqual(result.app_iter, [resultstr]) + self.assertEqual(result.status, '200 OK') + self.assertEqual(len(result.headerlist), 2) + from repoze.bfg.template import XSLTemplateFactory + self.failUnless(isinstance(queryUtility(IView, minimal), + XSLTemplateFactory)) + + def test_nonabs_registered(self): + self._zcmlConfigure() + from zope.component import getGlobalSiteManager + from zope.component import queryUtility + from repoze.bfg.template import XSLTemplateFactory + from repoze.bfg.interfaces import IView + minimal = self._getTemplatePath('minimal.xsl') + utility = XSLTemplateFactory(minimal) + gsm = getGlobalSiteManager() + gsm.registerUtility(utility, IView, name=minimal) + render = self._getFUT() + from lxml import etree + info = etree.Element("info") + result = render(minimal, node=info) + from webob import Response + self.failUnless(isinstance(result, Response)) + resultstr = """<?xml version="1.0"?>\n<div/>\n""" + self.assertEqual(result.app_iter, [resultstr]) + self.assertEqual(result.status, '200 OK') + self.assertEqual(len(result.headerlist), 2) + self.assertEqual(queryUtility(IView, minimal), utility) + +class DummyView: + context = 'context' + request = 'request' + |
