diff options
| -rw-r--r-- | CHANGES.txt | 34 | ||||
| -rw-r--r-- | docs/api/testing.rst | 10 | ||||
| -rw-r--r-- | docs/index.rst | 2 | ||||
| -rw-r--r-- | docs/narr/unittesting.rst | 13 | ||||
| -rw-r--r-- | repoze/bfg/chameleon_genshi.py | 80 | ||||
| -rw-r--r-- | repoze/bfg/chameleon_zpt.py | 86 | ||||
| -rw-r--r-- | repoze/bfg/interfaces.py | 46 | ||||
| -rw-r--r-- | repoze/bfg/templating.py | 30 | ||||
| -rw-r--r-- | repoze/bfg/testing.py | 275 | ||||
| -rw-r--r-- | repoze/bfg/tests/test_chameleon_genshi.py | 112 | ||||
| -rw-r--r-- | repoze/bfg/tests/test_chameleon_zpt.py | 116 | ||||
| -rw-r--r-- | repoze/bfg/tests/test_testing.py | 297 | ||||
| -rw-r--r-- | repoze/bfg/tests/test_xslt.py | 54 | ||||
| -rw-r--r-- | repoze/bfg/traversal.py | 2 | ||||
| -rw-r--r-- | repoze/bfg/xslt.py | 27 |
15 files changed, 1025 insertions, 159 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 5f224e5bb..9c0a204e4 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,37 @@ +Next Release + + Features + + - Added a ``repoze.bfg.testing`` module to attempt to make it + slightly easier to write unittest-based automated tests of BFG + applications. Information about this class is in the + documentation. + + - The default template renderer now supports testing better by + looking for ``ITestingTemplateRenderer`` using a relative + pathname. This is exposed indirectly through the API named + ``registerTemplate`` in ``repoze.bfg.testing``. + + Deprecations + + - The names ``repoze.bfg.interfaces.ITemplate`` , + ``repoze.bfg.interfaces.ITemplateFactory`` and + ``repoze.bfg.interfaces.INodeTemplate`` have been deprecated. + These should now be imported as + ``repoze.bfg.interfaces.ITemplateRenderer`` and + ``repoze.bfg.interfaces.ITemplateRendererFactory``, and + ``INodeTemplateRenderer`` respectively. + + - The name ``repoze.bfg.chameleon_zpt.ZPTTemplateFactory`` is + deprecated. Use ``repoze.bfg.chameleon_zpt.ZPTTemplateRenderer``. + + - The name ``repoze.bfg.chameleon_genshi.GenshiTemplateFactory`` is + deprecated. Use + ``repoze.bfg.chameleon_genshi.GenshiTemplateRenderer``. + + - The name ``repoze.bfg.xslt.XSLTemplateFactory`` is deprecated. + Use ``repoze.bfg.xslt.XSLTemplateRenderer``. + 0.4.3 (11/2/2008) Bug Fixes diff --git a/docs/api/testing.rst b/docs/api/testing.rst new file mode 100644 index 000000000..da0a128d9 --- /dev/null +++ b/docs/api/testing.rst @@ -0,0 +1,10 @@ +.. _testing_module: + +:mod:`repoze.bfg.testing` +========================== + +.. automodule:: repoze.bfg.testing + + .. autoclass:: BFGTestCase + :members: + diff --git a/docs/index.rst b/docs/index.rst index e89c18494..0c8fd295e 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -35,6 +35,7 @@ Narrative documentation in chapter form explaining how to use narr/security narr/events narr/environment + narr/unittesting changes glossary @@ -72,6 +73,7 @@ Per-module :mod:`repoze.bfg` API documentation. api/router api/security api/template + api/testing api/traversal api/location api/urldispatch diff --git a/docs/narr/unittesting.rst b/docs/narr/unittesting.rst new file mode 100644 index 000000000..0ef04083f --- /dev/null +++ b/docs/narr/unittesting.rst @@ -0,0 +1,13 @@ +.. _unittesting_chapter: + +Unit Testing +============ + +:mod:`repoze.bfg` provides helper facilities for writing +``unittest.TestCase`` -derived tests. A base class for these types of +tests as well as functions that help test BFG applications +specifically exist. See the :ref:`testing_module` chapter for the +API. + +XXX + diff --git a/repoze/bfg/chameleon_genshi.py b/repoze/bfg/chameleon_genshi.py index fbcc519e6..f3541ba4b 100644 --- a/repoze/bfg/chameleon_genshi.py +++ b/repoze/bfg/chameleon_genshi.py @@ -3,22 +3,22 @@ import os from webob import Response from zope.component import queryUtility -from zope.component.interfaces import ComponentLookupError -from zope.component import getSiteManager -from zope.interface import classProvides from zope.interface import implements +from zope.interface import classProvides +from zope.deprecation import deprecated -from repoze.bfg.path import caller_path -from repoze.bfg.interfaces import ITemplateFactory -from repoze.bfg.interfaces import ITemplate from repoze.bfg.interfaces import ISettings +from repoze.bfg.interfaces import ITemplateRenderer +from repoze.bfg.interfaces import ITemplateRendererFactory + +from repoze.bfg.templating import renderer_from_cache from chameleon.genshi.template import GenshiTemplateFile -class GenshiTemplateFactory(object): - classProvides(ITemplateFactory) - implements(ITemplate) +class GenshiTemplateRenderer(object): + classProvides(ITemplateRendererFactory) + implements(ITemplateRenderer) def __init__(self, path, auto_reload=False): try: @@ -35,48 +35,54 @@ class GenshiTemplateFactory(object): else: raise + def implementation(self): + return self.template + def __call__(self, **kw): - result = self.template.render(**kw) - return result - -def _get_template(path, **kw): - # XXX use pkg_resources - template = queryUtility(ITemplate, path) - - if template is None: - if not os.path.exists(path): - raise ValueError('Missing template file: %s' % path) - settings = queryUtility(ISettings) - auto_reload = settings and settings.reload_templates - template = GenshiTemplateFactory(path, auto_reload) - try: - sm = getSiteManager() - except ComponentLookupError: - pass - else: - sm.registerUtility(template, ITemplate, name=path) - - return template + return self.template(**kw) + +GenshiTemplateFactory = GenshiTemplateRenderer +deprecated('GenshiTemplateFactory', + ('repoze.bfg.chameleon_genshi.GenshiTemplateFactory should now be ' + 'imported as repoze.bfg.chameleon_genshi.GenshiTemplateRenderer')) + +def _auto_reload(): + settings = queryUtility(ISettings) + auto_reload = settings and settings.reload_templates + return auto_reload def get_template(path): """ Return a ``chameleon.genshi`` template object at the package-relative path (may also be absolute)""" - path = caller_path(path) - return _get_template(path).template + auto_reload = _auto_reload() + renderer = renderer_from_cache(path, GenshiTemplateRenderer, + auto_reload=auto_reload) + return renderer.implementation() + +def get_renderer(path): + """ Return a ``chameleon.genshi`` template renderer at the + package-relative path (may also be absolute)""" + auto_reload = _auto_reload() + renderer = renderer_from_cache(path, GenshiTemplateRenderer, + auto_reload=auto_reload) + return renderer def render_template(path, **kw): """ Render a ``chameleon.genshi`` 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(**kw) + auto_reload = _auto_reload() + renderer = renderer_from_cache(path, GenshiTemplateRenderer, + auto_reload=auto_reload) + return renderer(**kw) def render_template_to_response(path, **kw): """ Render a ``chameleon.genshi`` 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) + auto_reload = _auto_reload() + renderer = renderer_from_cache(path, GenshiTemplateRenderer, + auto_reload=auto_reload) + result = renderer(**kw) return Response(result) diff --git a/repoze/bfg/chameleon_zpt.py b/repoze/bfg/chameleon_zpt.py index 80669c009..c7d1d6949 100644 --- a/repoze/bfg/chameleon_zpt.py +++ b/repoze/bfg/chameleon_zpt.py @@ -3,22 +3,22 @@ import os from webob import Response from zope.component import queryUtility -from zope.component.interfaces import ComponentLookupError -from zope.component import getSiteManager from zope.interface import classProvides from zope.interface import implements +from zope.deprecation import deprecated -from repoze.bfg.path import caller_path -from repoze.bfg.interfaces import ITemplateFactory -from repoze.bfg.interfaces import ITemplate +from repoze.bfg.interfaces import ITemplateRenderer +from repoze.bfg.interfaces import ITemplateRendererFactory from repoze.bfg.interfaces import ISettings +from repoze.bfg.templating import renderer_from_cache + from chameleon.zpt.template import PageTemplateFile -class ZPTTemplateFactory(object): - classProvides(ITemplateFactory) - implements(ITemplate) +class ZPTTemplateRenderer(object): + classProvides(ITemplateRendererFactory) + implements(ITemplateRenderer) def __init__(self, path, auto_reload=False): try: @@ -34,48 +34,56 @@ class ZPTTemplateFactory(object): else: raise + def implementation(self): + return self.template + def __call__(self, **kw): - result = self.template.render(**kw) - return result - -def _get_template(path, **kw): - # XXX use pkg_resources - template = queryUtility(ITemplate, path) - - if template is None: - if not os.path.exists(path): - raise ValueError('Missing template file: %s' % path) - settings = queryUtility(ISettings) - auto_reload = settings and settings.reload_templates - template = ZPTTemplateFactory(path, auto_reload) - try: - sm = getSiteManager() - except ComponentLookupError: - pass - else: - sm.registerUtility(template, ITemplate, name=path) - - return template + return self.template(**kw) + +ZPTTemplateFactory = ZPTTemplateRenderer +deprecated('ZPTTemplateFactory', + ('repoze.bfg.chameleon_zpt.ZPTTemplateFactory should now be ' + 'imported as repoze.bfg.chameleon_zpt.ZPTTemplateRenderer')) + +def _auto_reload(): + settings = queryUtility(ISettings) + auto_reload = settings and settings.reload_templates + return auto_reload + +def get_renderer(path): + """ Return a callable ``ITemplateRenderer`` object representing a + ``chameleon.zpt`` template at the package-relative path (may also + be absolute). """ + auto_reload = _auto_reload() + renderer = renderer_from_cache(path, ZPTTemplateRenderer, + auto_reload=auto_reload) + return renderer def get_template(path): - """ Return a ``chameleon.zpt`` template object at the - package-relative path (may also be absolute)""" - path = caller_path(path) - return _get_template(path).template + """ Return a ``chameleon.zpt`` template at the package-relative + path (may also be absolute). """ + auto_reload = _auto_reload() + renderer = renderer_from_cache(path, ZPTTemplateRenderer, + auto_reload=auto_reload) + return renderer.implementation() def render_template(path, **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.""" - path = caller_path(path) - template = get_template(path) - return template(**kw) + auto_reload = _auto_reload() + renderer = renderer_from_cache(path, ZPTTemplateRenderer, + auto_reload=auto_reload) + return renderer(**kw) def render_template_to_response(path, **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 Response object.""" - path = caller_path(path) - result = render_template(path, **kw) + top-level names and return a Response object with the body as the + template result. """ + auto_reload = _auto_reload() + renderer = renderer_from_cache(path, ZPTTemplateRenderer, + auto_reload=auto_reload) + result = renderer(**kw) return Response(result) diff --git a/repoze/bfg/interfaces.py b/repoze/bfg/interfaces.py index bbff9bca7..71ef619c2 100644 --- a/repoze/bfg/interfaces.py +++ b/repoze/bfg/interfaces.py @@ -1,5 +1,6 @@ from zope.interface import Interface from zope.interface import Attribute +from zope.deprecation import deprecated from zope.component.interfaces import IObjectEvent @@ -26,20 +27,47 @@ class ITraverser(Interface): class ITraverserFactory(Interface): def __call__(context): - """ Return an object that implements IPublishTraverser """ + """ Return an object that implements ITraverser """ -class ITemplateFactory(Interface): - def __call__(path, auto_reload=False): - """ Return an an ITemplate given a filesystem path """ +class ITemplateRenderer(Interface): + def implementation(): + """ Return the object that the underlying templating system + uses to render the template; it is typically a callable that + accepts arbitrary keyword arguments and returns a string or + unicode object """ + + def __call__(**kw): + """ Call a the template implementation with the keywords + passed in as arguments and return the result (a string or + unicode object) """ -class ITemplate(Interface): +class ITestingTemplateRenderer(Interface): def __call__(**kw): - """ Return a string result given a template path """ + """ Accept keywords and process for test comparison purposes + (usually set all keywords as attributes of self); return value + is a string """ -class INodeTemplate(Interface): +class ITemplateRendererFactory(Interface): + def __call__(path, auto_reload=False): + """ Return an object that implements ``ITemplateRenderer`` """ + +class INodeTemplateRenderer(Interface): def __call__(node, **kw): - """ Return a string result given a template path """ - + """ Return a string result given a node and a template path """ + +ITemplate = ITemplateRenderer +deprecated('ITemplate', + ('repoze.bfg.interfaces.ITemplate should now be imported ' + 'as repoze.bfg.interfaces.ITemplateRenderer')) +INodeTemplate = INodeTemplateRenderer +deprecated('INodeTemplate', + ('repoze.bfg.interfaces.INodeTemplate should now be imported ' + 'as repoze.bfg.interfaces.INodeTemplateRenderer')) +ITemplateFactory = ITemplateRendererFactory +deprecated('ITemplateFactory', + ('repoze.bfg.interfaces.ITemplateFactory should now be imported ' + 'as repoze.bfg.interfaces.ITemplateRendererFactory')) + class ISecurityPolicy(Interface): """ A utility that provides a mechanism to check authorization using authentication data """ diff --git a/repoze/bfg/templating.py b/repoze/bfg/templating.py new file mode 100644 index 000000000..225a36358 --- /dev/null +++ b/repoze/bfg/templating.py @@ -0,0 +1,30 @@ +from zope.component import queryUtility +from repoze.bfg.interfaces import ITemplateRenderer +from repoze.bfg.interfaces import ITestingTemplateRenderer +from zope.component.interfaces import ComponentLookupError +from zope.component import getSiteManager +from repoze.bfg.path import caller_path +import os + +def renderer_from_cache(path, factory, level=3, **kw): + # XXX use pkg_resources + abspath = caller_path(path, level=level) + renderer = queryUtility(ITemplateRenderer, abspath) + + if renderer is None: + # service unit tests by trying the relative path + renderer = queryUtility(ITestingTemplateRenderer, path) + + if renderer is None: + if not os.path.exists(abspath): + raise ValueError('Missing template file: %s' % abspath) + renderer = factory(abspath, **kw) + try: + sm = getSiteManager() + except ComponentLookupError: + pass + else: + sm.registerUtility(renderer, ITemplateRenderer, name=abspath) + + return renderer + diff --git a/repoze/bfg/testing.py b/repoze/bfg/testing.py new file mode 100644 index 000000000..2ada3d20e --- /dev/null +++ b/repoze/bfg/testing.py @@ -0,0 +1,275 @@ +import unittest +from zope.component.testing import PlacelessSetup +from zope.interface import Interface + +class BFGTestCase(unittest.TestCase, PlacelessSetup): + """ A class which inherits from both ``unittest.TestCase`` and + ``zope.component.testing.PlacelessSetup`` that provides a + convenience API for writing BFG-specific tests. This class can be + subclassed within test modules and those subclasses will be found + by test loaders. Since this test case inherits from + ``PlacelessSetup`` the Zope component architecture registry is set + up and torn down between each test, which provides isolation + between tests.""" + + def setUp(self): + PlacelessSetup.setUp(self) + + def tearDown(self): + PlacelessSetup.tearDown(self) + + def registerSecurityPolicy(self, userid=None, groupids=(), permissive=True): + """ Registers a ``repoze.bfg`` security policy using the + userid ``userid`` and the group ids ``groupids``. If + ``permissive`` is true, a 'permissive' security policy is + registered; this policy allows all access. If ``permissive`` + is false, a nonpermissive security policy is registered; this + policy denies all access. To register your own (possibly more + granular) security policy, see the ``registerSecurityPolicy`` + *function* in the testing package. This function is most + useful when dealing with code that uses the + ``repoze.bfg.security``APIs named ``has_permission``, + ``authenticated_userid``, effective_principals, and + ``principals_allowed_by_permission``.""" + if permissive: + policy = DummyAllowingSecurityPolicy(userid, groupids) + else: + policy = DummyDenyingSecurityPolicy(userid, groupids) + return registerSecurityPolicy(policy) + + def registerModels(self, models): + """ Registers a dictionary of models. This is most useful for + dealing with code that wants to call the + ``repoze.bfg.traversal.find_model`` API. This API is called + with a path as one of its arguments. If the dictionary you + register when calling this method contains that path as a key + (e.g. '/foo/bar' or 'foo'), the corresponding value will be + returned to ``find_model`` (and thus to your code).""" + traverser = make_traverser_factory(models) + registerTraverserFactory(traverser) + return models + + def registerTemplate(self, name): + """ Registers a 'dummy' template renderer implementation and + returns it. This is most useful when dealing with code that + wants to call ``repoze.bfg.chameleon_zpt.render_template*``or + ``repoze.bfg.chameleon_genshi.render_template*``. If you call + this method with the exact template path string that a call to + one of the ``render_template`` functions uses, the dummy + template will stand in for the real implementation. The dummy + template object will set attributes on itself corresponding to + the non-path keyword arguments provided to the ``render`` + function. You can then compare these values against what you + expect. """ + return registerTemplateRenderer(name) + + def registerEventListener(self, event_iface=Interface): + """ Registers an event listener (aka 'subscriber') listening + for events of the type ``event_iface`` and returns a list + which is appended to by the subscriber. When an event is + dispatched that matches ``event_iface``, that event will be + appended to the list. You can then compare the values in the + list to expected event notifications. This method is useful + when dealing with code that wants to call + ``zope.component.event.dispatch``.""" + L = [] + def subscriber(event): + L.append(event) + registerSubscriber(subscriber, event_iface) + return L + + def registerView(self, name, result='', view=None): + """ Registers a ``repoze.bfg`` view function under the name + ``name``. The view will return a webob Response object with + the ``result`` value as its body attribute. To gain more + control, if you pass in a non-None ``view``, this view + function will be used instead of an automatically generated + view function (and ``result`` is not used). This method is + useful when dealing with code that wants to call, + e.g. ``repoze.bfg.view.render_view_to_response``.""" + if view is None: + view = make_view(result) + registerView(view, name) + return view + + def registerViewPermission(self, name, result=True, viewpermission=None): + """ Registers a ``repoze.bfg`` 'view permission' object under + the name ``name``. The view permission return a result + denoted by the ``result`` argument. If ``result`` is True, a + ``repoze.bfg.security.Allowed`` object is returned; else a + ``repoze.bfg.security.Denied`` object is returned. To gain + more control, if you pass in a non-None ``viewpermission``, + this view permission object will be used instead of an + automatically generated view permission (and ``result`` is not + used). This method is useful when dealing with code that + wants to call, e.g. ``repoze.bfg.view.view_execution_permitted``. + Note that view permissions are not checked unless a security + policy is in effect (see ``registerSecurityPolicy``).""" + from repoze.bfg.security import Allowed + from repoze.bfg.security import Denied + if result is True: + result = Allowed('message') + else: + result = Denied('message') + if viewpermission is None: + viewpermission = make_view_permission(result) + return registerViewPermission(viewpermission, name) + + def registerAdapter(self, impl, for_, provides, name=''): + """ A shortcut for calling the Zope Component Architecture's + global site manager's ``registerAdapter`` function. The + argument ordering matches that function's exactly. Registers a + ZCA adapter.""" + return registerAdapter(impl, for_, provides, name) + + def registerUtility(self, impl, iface, name=''): + """ A shortcut for calling the Zope Component Architecture's + global site manager's ``registerUtility`` function. The + argument ordering matches that function's exactly. Registers + a ZCA utility.""" + return registerUtility(impl, iface, name) + + def makeModel(self, name=None, parent=None): + """ Returns a 'dummy' model object, with the model's + ``__name__`` attribute set to the value of ``name``, and the + model's ``__parent__`` attribute set to the value of + ``parent``. A dummy model has a ``__setitem__`` method and a + ``__getitem__`` method. The ``__setitem__`` method can be + called with a key/value pair; the value will be decorated with + a ``__parent__`` attribute pointing at the dummy object and a + ``__name__`` attribute that is the value of the key. + A dummy model has no other attributes or methods.""" + return DummyModel(name, parent) + +def registerUtility(impl, iface, name=''): + import zope.component + gsm = zope.component.getGlobalSiteManager() + gsm.registerUtility(impl, iface, name=name) + return impl + +def registerAdapter(impl, for_=Interface, provides=Interface, name=''): + import zope.component + gsm = zope.component.getGlobalSiteManager() + if not isinstance(for_, (tuple, list)): + for_ = (for_,) + gsm.registerAdapter(impl, for_, provides, name=name) + return impl + +def registerSubscriber(subscriber, iface=Interface): + import zope.component + gsm = zope.component.getGlobalSiteManager() + if not isinstance(iface, (tuple, list)): + iface = (iface,) + gsm.registerHandler(subscriber, iface) + return subscriber + +def registerTemplateRenderer(path, renderer=None, iface=None): + if iface is None: + from repoze.bfg.interfaces import ITestingTemplateRenderer + iface = ITestingTemplateRenderer + if renderer is None: + renderer = DummyTemplateRenderer() + return registerUtility(renderer, iface, path) + +def registerSecurityPolicy(policy): + from repoze.bfg.interfaces import ISecurityPolicy + return registerUtility(policy, ISecurityPolicy) + +def registerTraverserFactory(traverser, for_=Interface): + from repoze.bfg.interfaces import ITraverserFactory + return registerAdapter(traverser, for_, ITraverserFactory) + +def registerView(view, name, for_=(Interface, Interface)): + from repoze.bfg.interfaces import IView + return registerAdapter(view, for_, IView, name) + +def registerViewPermission(viewpermission, name, for_=(Interface, Interface)): + from repoze.bfg.interfaces import IViewPermission + return registerAdapter(viewpermission, for_, IViewPermission, name) + +class _DummySecurityPolicy: + def __init__(self, userid=None, groupids=()): + self.userid = userid + self.groupids = groupids + + def authenticated_userid(self, request): + return self.userid + + def effective_principals(self, request): + from repoze.bfg.security import Everyone + from repoze.bfg.security import Authenticated + effective_principals = [Everyone] + if self.userid: + effective_principals.append(Authenticated) + effective_principals.append(self.userid) + effective_principals.extend(self.groupids) + return effective_principals + +class DummyAllowingSecurityPolicy(_DummySecurityPolicy): + def permits(self, context, request, permission): + return True + + def principals_allowed_by_permission(self, context, permission): + return self.effective_principals(None) + +class DummyDenyingSecurityPolicy(_DummySecurityPolicy): + def permits(self, context, request, permission): + return False + + def principals_allowed_by_permission(self, context, permission): + return [] + +def make_traverser_factory(root): + class DummyTraverserFactory: + def __init__(self, context): + self.context = context + + def __call__(self, environ): + ob = root[environ['PATH_INFO']] + return ob, '', [] + + return DummyTraverserFactory + +class DummyTemplateRenderer: + def implementation(self): + return None + + def __call__(self, **kw): + self.__dict__.update(kw) + return '' + +def make_view(result): + def dummy_view(context, request): + from webob import Response + return Response(result) + return dummy_view + +def make_view_permission(result): + class DummyViewPermission: + def __init__(self, context, request): + self.context = context + self.request = request + + def __call__(self, secpol): + return result + + return DummyViewPermission + +class DummyModel: + def __init__(self, name=None, parent=None): + self.__name__ = name + self.__parent__ = parent + self.subs = {} + + def __setitem__(self, name, val): + val.__name__ = name + val.__parent__ = self + self.subs[name] = val + + def __getitem__(self, name): + ob = self.subs[name] + return ob + + + + diff --git a/repoze/bfg/tests/test_chameleon_genshi.py b/repoze/bfg/tests/test_chameleon_genshi.py index 0f0fc88a1..5a31ca6fa 100644 --- a/repoze/bfg/tests/test_chameleon_genshi.py +++ b/repoze/bfg/tests/test_chameleon_genshi.py @@ -19,7 +19,7 @@ class Base(PlacelessSetup): here = os.path.abspath(os.path.dirname(__file__)) return os.path.join(here, 'fixtures', name) -class GenshiTemplateFactoryTests(unittest.TestCase, Base): +class GenshiTemplateRendererTests(unittest.TestCase, Base): def setUp(self): Base.setUp(self) @@ -27,8 +27,8 @@ class GenshiTemplateFactoryTests(unittest.TestCase, Base): Base.tearDown(self) def _getTargetClass(self): - from repoze.bfg.chameleon_genshi import GenshiTemplateFactory - return GenshiTemplateFactory + from repoze.bfg.chameleon_genshi import GenshiTemplateRenderer + return GenshiTemplateRenderer def _makeOne(self, *arg, **kw): klass = self._getTargetClass() @@ -36,14 +36,14 @@ class GenshiTemplateFactoryTests(unittest.TestCase, Base): def test_instance_implements_ITemplate(self): from zope.interface.verify import verifyObject - from repoze.bfg.interfaces import ITemplate + from repoze.bfg.interfaces import ITemplateRenderer path = self._getTemplatePath('minimal.genshi') - verifyObject(ITemplate, self._makeOne(path)) + verifyObject(ITemplateRenderer, self._makeOne(path)) def test_class_implements_ITemplate(self): from zope.interface.verify import verifyClass - from repoze.bfg.interfaces import ITemplate - verifyClass(ITemplate, self._getTargetClass()) + from repoze.bfg.interfaces import ITemplateRenderer + verifyClass(ITemplateRenderer, self._getTargetClass()) def test_call(self): self._zcmlConfigure() @@ -53,6 +53,14 @@ class GenshiTemplateFactoryTests(unittest.TestCase, Base): self.failUnless(isinstance(result, str)) self.assertEqual(result, '<div>\n</div>\n') + def test_implementation(self): + self._zcmlConfigure() + minimal = self._getTemplatePath('minimal.genshi') + instance = self._makeOne(minimal) + result = instance.implementation()() + self.failUnless(isinstance(result, str)) + self.assertEqual(result, '<div>\n</div>\n') + class RenderTemplateTests(unittest.TestCase, Base): def setUp(self): Base.setUp(self) @@ -92,6 +100,61 @@ class RenderTemplateToResponseTests(unittest.TestCase, Base): self.assertEqual(result.status, '200 OK') self.assertEqual(len(result.headerlist), 2) +class GetRendererTests(unittest.TestCase, Base): + def setUp(self): + Base.setUp(self) + + def tearDown(self): + Base.tearDown(self) + + def _getFUT(self): + from repoze.bfg.chameleon_genshi import get_renderer + return get_renderer + + def test_nonabs_registered(self): + from zope.component import getGlobalSiteManager + from zope.component import queryUtility + from repoze.bfg.chameleon_genshi import GenshiTemplateRenderer + from repoze.bfg.interfaces import ITemplateRenderer + minimal = self._getTemplatePath('minimal.genshi') + utility = GenshiTemplateRenderer(minimal) + gsm = getGlobalSiteManager() + gsm.registerUtility(utility, ITemplateRenderer, name=minimal) + get = self._getFUT() + result = get(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.chameleon_genshi import GenshiTemplateRenderer + from repoze.bfg.interfaces import ITemplateRenderer + minimal = self._getTemplatePath('minimal.genshi') + self.assertEqual(queryUtility(ITemplateRenderer, minimal), None) + utility = GenshiTemplateRenderer(minimal) + gsm = getGlobalSiteManager() + gsm.registerUtility(utility, ITemplateRenderer, name=minimal) + get = self._getFUT() + result = get(minimal) + self.assertEqual(result, utility) + self.assertEqual(queryUtility(ITemplateRenderer, minimal), utility) + + def test_testing(self): + from zope.component import getGlobalSiteManager + from repoze.bfg.interfaces import ITestingTemplateRenderer + class Dummy: + template = object() + def implementation(self): + return self.template + gsm = getGlobalSiteManager() + utility = Dummy() + gsm.registerUtility(utility, ITestingTemplateRenderer, name='foo') + get = self._getFUT() + result = get('foo') + self.failUnless(result is utility) + + class GetTemplateTests(unittest.TestCase, Base): def setUp(self): Base.setUp(self) @@ -106,29 +169,42 @@ class GetTemplateTests(unittest.TestCase, Base): def test_nonabs_registered(self): from zope.component import getGlobalSiteManager from zope.component import queryUtility - from repoze.bfg.chameleon_genshi import GenshiTemplateFactory - from repoze.bfg.interfaces import ITemplate + from repoze.bfg.chameleon_genshi import GenshiTemplateRenderer + from repoze.bfg.interfaces import ITemplateRenderer minimal = self._getTemplatePath('minimal.genshi') - utility = GenshiTemplateFactory(minimal) + utility = GenshiTemplateRenderer(minimal) gsm = getGlobalSiteManager() - gsm.registerUtility(utility, ITemplate, name=minimal) + gsm.registerUtility(utility, ITemplateRenderer, name=minimal) get = self._getFUT() result = get(minimal) self.assertEqual(result.filename, minimal) - self.assertEqual(queryUtility(ITemplate, minimal), 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.chameleon_genshi import GenshiTemplateFactory - from repoze.bfg.interfaces import ITemplate + from repoze.bfg.chameleon_genshi import GenshiTemplateRenderer + from repoze.bfg.interfaces import ITemplateRenderer minimal = self._getTemplatePath('minimal.genshi') - self.assertEqual(queryUtility(ITemplate, minimal), None) - utility = GenshiTemplateFactory(minimal) + self.assertEqual(queryUtility(ITemplateRenderer, minimal), None) + utility = GenshiTemplateRenderer(minimal) gsm = getGlobalSiteManager() - gsm.registerUtility(utility, ITemplate, name=minimal) + gsm.registerUtility(utility, ITemplateRenderer, name=minimal) get = self._getFUT() result = get(minimal) self.assertEqual(result.filename, minimal) - self.assertEqual(queryUtility(ITemplate, minimal), utility) + self.assertEqual(queryUtility(ITemplateRenderer, minimal), utility) + def test_testing(self): + from zope.component import getGlobalSiteManager + from repoze.bfg.interfaces import ITestingTemplateRenderer + class Dummy: + template = object() + def implementation(self): + return self.template + gsm = getGlobalSiteManager() + utility = Dummy() + gsm.registerUtility(utility, ITestingTemplateRenderer, name='foo') + get = self._getFUT() + result = get('foo') + self.failUnless(result is utility.template) diff --git a/repoze/bfg/tests/test_chameleon_zpt.py b/repoze/bfg/tests/test_chameleon_zpt.py index 3b977bcbf..3ec956217 100644 --- a/repoze/bfg/tests/test_chameleon_zpt.py +++ b/repoze/bfg/tests/test_chameleon_zpt.py @@ -19,7 +19,7 @@ class Base(PlacelessSetup): here = os.path.abspath(os.path.dirname(__file__)) return os.path.join(here, 'fixtures', name) -class ZPTTemplateFactoryTests(unittest.TestCase, Base): +class ZPTTemplateRendererTests(unittest.TestCase, Base): def setUp(self): Base.setUp(self) @@ -27,8 +27,8 @@ class ZPTTemplateFactoryTests(unittest.TestCase, Base): Base.tearDown(self) def _getTargetClass(self): - from repoze.bfg.chameleon_zpt import ZPTTemplateFactory - return ZPTTemplateFactory + from repoze.bfg.chameleon_zpt import ZPTTemplateRenderer + return ZPTTemplateRenderer def _makeOne(self, *arg, **kw): klass = self._getTargetClass() @@ -36,14 +36,14 @@ class ZPTTemplateFactoryTests(unittest.TestCase, Base): def test_instance_implements_ITemplate(self): from zope.interface.verify import verifyObject - from repoze.bfg.interfaces import ITemplate + from repoze.bfg.interfaces import ITemplateRenderer path = self._getTemplatePath('minimal.pt') - verifyObject(ITemplate, self._makeOne(path)) + verifyObject(ITemplateRenderer, self._makeOne(path)) def test_class_implements_ITemplate(self): from zope.interface.verify import verifyClass - from repoze.bfg.interfaces import ITemplate - verifyClass(ITemplate, self._getTargetClass()) + from repoze.bfg.interfaces import ITemplateRenderer + verifyClass(ITemplateRenderer, self._getTargetClass()) def test_call(self): self._zcmlConfigure() @@ -53,6 +53,15 @@ class ZPTTemplateFactoryTests(unittest.TestCase, Base): self.failUnless(isinstance(result, str)) self.assertEqual(result, '<div>\n</div>\n') + def test_implementation(self): + self._zcmlConfigure() + minimal = self._getTemplatePath('minimal.pt') + instance = self._makeOne(minimal) + result = instance.implementation()() + self.failUnless(isinstance(result, str)) + self.assertEqual(result, '<div>\n</div>\n') + + class RenderTemplateTests(unittest.TestCase, Base): def setUp(self): Base.setUp(self) @@ -94,6 +103,60 @@ class RenderTemplateToResponseTests(unittest.TestCase, Base): self.assertEqual(result.status, '200 OK') self.assertEqual(len(result.headerlist), 2) +class GetRendererTests(unittest.TestCase, Base): + def setUp(self): + Base.setUp(self) + + def tearDown(self): + Base.tearDown(self) + + def _getFUT(self): + from repoze.bfg.chameleon_zpt import get_renderer + return get_renderer + + def test_nonabs_registered(self): + from zope.component import getGlobalSiteManager + from zope.component import queryUtility + from repoze.bfg.chameleon_zpt import ZPTTemplateRenderer + from repoze.bfg.interfaces import ITemplateRenderer + minimal = self._getTemplatePath('minimal.pt') + utility = ZPTTemplateRenderer(minimal) + gsm = getGlobalSiteManager() + gsm.registerUtility(utility, ITemplateRenderer, name=minimal) + get = self._getFUT() + result = get(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.chameleon_zpt import ZPTTemplateRenderer + from repoze.bfg.interfaces import ITemplateRenderer + minimal = self._getTemplatePath('minimal.pt') + self.assertEqual(queryUtility(ITemplateRenderer, minimal), None) + utility = ZPTTemplateRenderer(minimal) + gsm = getGlobalSiteManager() + gsm.registerUtility(utility, ITemplateRenderer, name=minimal) + get = self._getFUT() + result = get(minimal) + self.assertEqual(result, utility) + self.assertEqual(queryUtility(ITemplateRenderer, minimal), utility) + + def test_testing(self): + from zope.component import getGlobalSiteManager + from repoze.bfg.interfaces import ITestingTemplateRenderer + class Dummy: + template = object() + def implementation(self): + return self.template + gsm = getGlobalSiteManager() + utility = Dummy() + gsm.registerUtility(utility, ITestingTemplateRenderer, name='foo') + get = self._getFUT() + result = get('foo') + self.failUnless(result is utility) + class GetTemplateTests(unittest.TestCase, Base): def setUp(self): Base.setUp(self) @@ -109,31 +172,48 @@ class GetTemplateTests(unittest.TestCase, Base): self._zcmlConfigure() from zope.component import getGlobalSiteManager from zope.component import queryUtility - from repoze.bfg.chameleon_zpt import ZPTTemplateFactory - from repoze.bfg.interfaces import ITemplate + from repoze.bfg.chameleon_zpt import ZPTTemplateRenderer + from repoze.bfg.interfaces import ITemplateRenderer minimal = self._getTemplatePath('minimal.pt') - utility = ZPTTemplateFactory(minimal) + utility = ZPTTemplateRenderer(minimal) gsm = getGlobalSiteManager() - gsm.registerUtility(utility, ITemplate, name=minimal) + gsm.registerUtility(utility, ITemplateRenderer, name=minimal) get = self._getFUT() result = get(minimal) self.assertEqual(result.filename, minimal) - self.assertEqual(queryUtility(ITemplate, minimal), utility) + self.assertEqual(queryUtility(ITemplateRenderer, minimal), utility) def test_nonabs_unregistered(self): self._zcmlConfigure() from zope.component import getGlobalSiteManager from zope.component import queryUtility - from repoze.bfg.chameleon_zpt import ZPTTemplateFactory - from repoze.bfg.interfaces import ITemplate + from repoze.bfg.chameleon_zpt import ZPTTemplateRenderer + from repoze.bfg.interfaces import ITemplateRenderer minimal = self._getTemplatePath('minimal.pt') - self.assertEqual(queryUtility(ITemplate, minimal), None) - utility = ZPTTemplateFactory(minimal) + self.assertEqual(queryUtility(ITemplateRenderer, minimal), None) + utility = ZPTTemplateRenderer(minimal) gsm = getGlobalSiteManager() - gsm.registerUtility(utility, ITemplate, name=minimal) + gsm.registerUtility(utility, ITemplateRenderer, name=minimal) get = self._getFUT() result = get(minimal) self.assertEqual(result.filename, minimal) - self.assertEqual(queryUtility(ITemplate, minimal), utility) + self.assertEqual(queryUtility(ITemplateRenderer, minimal), utility) + + def test_testing(self): + from zope.component import getGlobalSiteManager + from repoze.bfg.interfaces import ITestingTemplateRenderer + class Dummy: + template = object() + def implementation(self): + return self.template + gsm = getGlobalSiteManager() + utility = Dummy() + gsm.registerUtility(utility, ITestingTemplateRenderer, name='foo') + get = self._getFUT() + result = get('foo') + self.failUnless(result is utility.template) + + + diff --git a/repoze/bfg/tests/test_testing.py b/repoze/bfg/tests/test_testing.py new file mode 100644 index 000000000..23fbb7cc7 --- /dev/null +++ b/repoze/bfg/tests/test_testing.py @@ -0,0 +1,297 @@ +from zope.component.testing import PlacelessSetup +import unittest + +class TestBFGTestCase(unittest.TestCase, PlacelessSetup): + def setUp(self): + PlacelessSetup.setUp(self) + + def tearDown(self): + PlacelessSetup.tearDown(self) + + def _getTargetClass(self): + from repoze.bfg.testing import BFGTestCase + return BFGTestCase + + def _makeOne(self): + return self._getTargetClass()(methodName='__doc__') + + def test_registerSecurityPolicy_permissive(self): + case = self._makeOne() + case.registerSecurityPolicy('user', ('group1', 'group2'), + permissive=True) + from repoze.bfg.interfaces import ISecurityPolicy + from zope.component import getUtility + ut = getUtility(ISecurityPolicy) + from repoze.bfg.testing import DummyAllowingSecurityPolicy + self.failUnless(isinstance(ut, DummyAllowingSecurityPolicy)) + self.assertEqual(ut.userid, 'user') + self.assertEqual(ut.groupids, ('group1', 'group2')) + + def test_registerSecurityPolicy_nonpermissive(self): + case = self._makeOne() + case.registerSecurityPolicy('user', ('group1', 'group2'), + permissive=False) + from repoze.bfg.interfaces import ISecurityPolicy + from zope.component import getUtility + ut = getUtility(ISecurityPolicy) + from repoze.bfg.testing import DummyDenyingSecurityPolicy + self.failUnless(isinstance(ut, DummyDenyingSecurityPolicy)) + self.assertEqual(ut.userid, 'user') + self.assertEqual(ut.groupids, ('group1', 'group2')) + + def test_registerModels(self): + ob1 = object() + ob2 = object() + models = {'/ob1':ob1, '/ob2':ob2} + case = self._makeOne() + case.registerModels(models) + from zope.component import getAdapter + from repoze.bfg.interfaces import ITraverserFactory + adapter = getAdapter(None, ITraverserFactory) + self.assertEqual(adapter({'PATH_INFO':'/ob1'}), (ob1, '', [])) + self.assertEqual(adapter({'PATH_INFO':'/ob2'}), (ob2, '', [])) + self.assertRaises(KeyError, adapter, {'PATH_INFO':'/ob3'}) + from repoze.bfg.traversal import find_model + self.assertEqual(find_model(None, '/ob1'), ob1) + + def test_registerTemplate(self): + case = self._makeOne() + template = case.registerTemplate('templates/foo') + from repoze.bfg.testing import DummyTemplateRenderer + self.failUnless(isinstance(template, DummyTemplateRenderer)) + from repoze.bfg.chameleon_zpt import render_template_to_response + response = render_template_to_response('templates/foo', foo=1, bar=2) + self.assertEqual(template.foo, 1) + self.assertEqual(template.bar, 2) + self.assertEqual(response.body, '') + + def test_registerEventListener_single(self): + case = self._makeOne() + from zope.interface import implements + from zope.interface import Interface + class IEvent(Interface): + pass + class Event: + implements(IEvent) + L = case.registerEventListener(IEvent) + from zope.component.event import dispatch + event = Event() + dispatch(event) + self.assertEqual(len(L), 1) + self.assertEqual(L[0], event) + dispatch(object()) + self.assertEqual(len(L), 1) + + def test_registerEventListener_defaults(self): + case = self._makeOne() + L = case.registerEventListener() + from zope.component.event import dispatch + event = object() + dispatch(event) + self.assertEqual(len(L), 2) + self.assertEqual(L[1], event) + dispatch(object()) + self.assertEqual(len(L), 3) + + def test_registerView_defaults(self): + case = self._makeOne() + view = case.registerView('moo.html') + import types + self.failUnless(isinstance(view, types.FunctionType)) + from repoze.bfg.view import render_view_to_response + response = render_view_to_response(None, None, 'moo.html') + self.assertEqual(view(None, None).body, response.body) + + def test_registerView_withresult(self): + case = self._makeOne() + view = case.registerView('moo.html', 'yo') + import types + self.failUnless(isinstance(view, types.FunctionType)) + from repoze.bfg.view import render_view_to_response + response = render_view_to_response(None, None, 'moo.html') + self.assertEqual(response.body, 'yo') + + def test_registerView_custom(self): + case = self._makeOne() + def view(context, request): + from webob import Response + return Response('123') + view = case.registerView('moo.html', view=view) + import types + self.failUnless(isinstance(view, types.FunctionType)) + from repoze.bfg.view import render_view_to_response + response = render_view_to_response(None, None, 'moo.html') + self.assertEqual(response.body, '123') + + def test_registerViewPermission_defaults(self): + case = self._makeOne() + view = case.registerViewPermission('moo.html') + from repoze.bfg.view import view_execution_permitted + case.registerSecurityPolicy() + result = view_execution_permitted(None, None, 'moo.html') + self.failUnless(result) + self.assertEqual(result.msg, 'message') + + def test_registerViewPermission_denying(self): + case = self._makeOne() + view = case.registerViewPermission('moo.html', result=False) + from repoze.bfg.view import view_execution_permitted + case.registerSecurityPolicy() + result = view_execution_permitted(None, None, 'moo.html') + self.failIf(result) + self.assertEqual(result.msg, 'message') + + def test_registerViewPermission_custom(self): + class ViewPermission: + def __init__(self, context, request): + self.context = context + self.request = request + + def __call__(self, secpol): + return True + + case = self._makeOne() + view = case.registerViewPermission('moo.html', + viewpermission=ViewPermission) + from repoze.bfg.view import view_execution_permitted + case.registerSecurityPolicy() + result = view_execution_permitted(None, None, 'moo.html') + self.failUnless(result is True) + + def test_registerAdapter(self): + from zope.interface import implements + from zope.interface import Interface + from zope.component import getMultiAdapter + class provides(Interface): + pass + class Provider: + implements(provides) + def __init__(self, context, request): + self.context = context + self.request = request + class for_(Interface): + pass + class For_: + implements(for_) + for1 = For_() + for2 = For_() + case = self._makeOne() + case.registerAdapter(Provider, (for_, for_), provides, name='foo') + adapter = getMultiAdapter((for1, for2), provides, name='foo') + self.failUnless(isinstance(adapter, Provider)) + self.assertEqual(adapter.context, for1) + self.assertEqual(adapter.request, for2) + + def test_registerUtility(self): + from zope.interface import implements + from zope.interface import Interface + from zope.component import getUtility + class iface(Interface): + pass + class impl: + implements(iface) + def __call__(self): + return 'foo' + case = self._makeOne() + utility = impl() + case.registerUtility(utility, iface, name='mudge') + self.assertEqual(getUtility(iface, name='mudge')(), 'foo') + + def test_makeModel(self): + case = self._makeOne() + parent = object() + model = case.makeModel('name', parent) + self.assertEqual(model.__name__, 'name') + self.assertEqual(model.__parent__, parent) + +class TestDummyAllowingSecurityPolicy(unittest.TestCase): + def _getTargetClass(self): + from repoze.bfg.testing import DummyAllowingSecurityPolicy + return DummyAllowingSecurityPolicy + + def _makeOne(self, userid=None, groupids=()): + klass = self._getTargetClass() + return klass(userid, groupids) + + def test_authenticated_userid(self): + policy = self._makeOne('user') + self.assertEqual(policy.authenticated_userid(None), 'user') + + def test_effective_principals_userid(self): + policy = self._makeOne('user', ('group1',)) + from repoze.bfg.security import Everyone + from repoze.bfg.security import Authenticated + self.assertEqual(policy.effective_principals(None), + [Everyone, Authenticated, 'user', 'group1']) + + def test_effective_principals_nouserid(self): + policy = self._makeOne() + from repoze.bfg.security import Everyone + self.assertEqual(policy.effective_principals(None), [Everyone]) + + def test_permits(self): + policy = self._makeOne() + self.assertEqual(policy.permits(None, None, None), True) + + def test_principals_allowed_by_permission(self): + policy = self._makeOne('user', ('group1',)) + from repoze.bfg.security import Everyone + from repoze.bfg.security import Authenticated + self.assertEqual(policy.principals_allowed_by_permission(None, None), + [Everyone, Authenticated, 'user', 'group1']) + + +class TestDummyDenyingSecurityPolicy(unittest.TestCase): + def _getTargetClass(self): + from repoze.bfg.testing import DummyDenyingSecurityPolicy + return DummyDenyingSecurityPolicy + + def _makeOne(self, userid=None, groupids=()): + klass = self._getTargetClass() + return klass(userid, groupids) + + def test_authenticated_userid(self): + policy = self._makeOne('user') + self.assertEqual(policy.authenticated_userid(None), 'user') + + def test_effective_principals_userid(self): + policy = self._makeOne('user', ('group1',)) + from repoze.bfg.security import Everyone + from repoze.bfg.security import Authenticated + self.assertEqual(policy.effective_principals(None), + [Everyone, Authenticated, 'user', 'group1']) + + def test_effective_principals_nouserid(self): + policy = self._makeOne() + from repoze.bfg.security import Everyone + self.assertEqual(policy.effective_principals(None), [Everyone]) + + def test_permits(self): + policy = self._makeOne() + self.assertEqual(policy.permits(None, None, None), False) + + def test_principals_allowed_by_permission(self): + policy = self._makeOne('user', ('group1',)) + self.assertEqual(policy.principals_allowed_by_permission(None, None), + []) + +class TestDummyModel(unittest.TestCase): + def _getTargetClass(self): + from repoze.bfg.testing import DummyModel + return DummyModel + + def _makeOne(self, name=None, parent=None): + klass = self._getTargetClass() + return klass(name, parent) + + def test__setitem__and__getitem__(self): + class Dummy: + pass + dummy = Dummy() + model = self._makeOne() + model['abc'] = dummy + self.assertEqual(dummy.__name__, 'abc') + self.assertEqual(dummy.__parent__, model) + self.assertEqual(model['abc'], dummy) + self.assertRaises(KeyError, model.__getitem__, 'none') + diff --git a/repoze/bfg/tests/test_xslt.py b/repoze/bfg/tests/test_xslt.py index 0a858e08b..66e268331 100644 --- a/repoze/bfg/tests/test_xslt.py +++ b/repoze/bfg/tests/test_xslt.py @@ -19,7 +19,7 @@ class Base(PlacelessSetup): here = os.path.abspath(os.path.dirname(__file__)) return os.path.join(here, 'fixtures', name) -class XSLTemplateFactoryTests(unittest.TestCase, Base): +class XSLTemplateRendererTests(unittest.TestCase, Base): def setUp(self): Base.setUp(self) @@ -27,8 +27,8 @@ class XSLTemplateFactoryTests(unittest.TestCase, Base): Base.tearDown(self) def _getTargetClass(self): - from repoze.bfg.xslt import XSLTemplateFactory - return XSLTemplateFactory + from repoze.bfg.xslt import XSLTemplateRenderer + return XSLTemplateRenderer def _makeOne(self, *arg, **kw): klass = self._getTargetClass() @@ -36,14 +36,14 @@ class XSLTemplateFactoryTests(unittest.TestCase, Base): def test_instance_implements_INodeTemplate(self): from zope.interface.verify import verifyObject - from repoze.bfg.interfaces import INodeTemplate + from repoze.bfg.interfaces import INodeTemplateRenderer path = self._getTemplatePath('minimal.xsl') - verifyObject(INodeTemplate, self._makeOne(path)) + verifyObject(INodeTemplateRenderer, self._makeOne(path)) def test_class_implements_INodeTemplate(self): from zope.interface.verify import verifyClass - from repoze.bfg.interfaces import INodeTemplate - verifyClass(INodeTemplate, self._getTargetClass()) + from repoze.bfg.interfaces import INodeTemplateRenderer + verifyClass(INodeTemplateRenderer, self._getTargetClass()) def test_call(self): self._zcmlConfigure() @@ -70,9 +70,9 @@ class RenderTransformToResponseTests(unittest.TestCase, Base): def test_nonabs_unregistered(self): self._zcmlConfigure() from zope.component import queryUtility - from repoze.bfg.interfaces import INodeTemplate + from repoze.bfg.interfaces import INodeTemplateRenderer minimal = self._getTemplatePath('minimal.xsl') - self.assertEqual(queryUtility(INodeTemplate, minimal), None) + self.assertEqual(queryUtility(INodeTemplateRenderer, minimal), None) render = self._getFUT() from lxml import etree info = etree.Element("info") @@ -83,20 +83,20 @@ class RenderTransformToResponseTests(unittest.TestCase, Base): self.assertEqual(result.app_iter, [resultstr]) self.assertEqual(result.status, '200 OK') self.assertEqual(len(result.headerlist), 2) - from repoze.bfg.xslt import XSLTemplateFactory - self.failUnless(isinstance(queryUtility(INodeTemplate, minimal), - XSLTemplateFactory)) + from repoze.bfg.xslt import XSLTemplateRenderer + self.failUnless(isinstance(queryUtility(INodeTemplateRenderer, minimal), + XSLTemplateRenderer)) def test_nonabs_registered(self): self._zcmlConfigure() from zope.component import getGlobalSiteManager from zope.component import queryUtility - from repoze.bfg.xslt import XSLTemplateFactory - from repoze.bfg.interfaces import INodeTemplate + from repoze.bfg.xslt import XSLTemplateRenderer + from repoze.bfg.interfaces import INodeTemplateRenderer minimal = self._getTemplatePath('minimal.xsl') - utility = XSLTemplateFactory(minimal) + utility = XSLTemplateRenderer(minimal) gsm = getGlobalSiteManager() - gsm.registerUtility(utility, INodeTemplate, name=minimal) + gsm.registerUtility(utility, INodeTemplateRenderer, name=minimal) render = self._getFUT() from lxml import etree info = etree.Element("info") @@ -107,7 +107,7 @@ class RenderTransformToResponseTests(unittest.TestCase, Base): self.assertEqual(result.app_iter, [resultstr]) self.assertEqual(result.status, '200 OK') self.assertEqual(len(result.headerlist), 2) - self.assertEqual(queryUtility(INodeTemplate, minimal), utility) + self.assertEqual(queryUtility(INodeTemplateRenderer, minimal), utility) class RenderTransformTests(unittest.TestCase, Base): def setUp(self): @@ -123,9 +123,9 @@ class RenderTransformTests(unittest.TestCase, Base): def test_nonabs_unregistered(self): self._zcmlConfigure() from zope.component import queryUtility - from repoze.bfg.interfaces import INodeTemplate + from repoze.bfg.interfaces import INodeTemplateRenderer minimal = self._getTemplatePath('minimal.xsl') - self.assertEqual(queryUtility(INodeTemplate, minimal), None) + self.assertEqual(queryUtility(INodeTemplateRenderer, minimal), None) render = self._getFUT() from lxml import etree info = etree.Element("info") @@ -133,20 +133,20 @@ class RenderTransformTests(unittest.TestCase, Base): self.failUnless(isinstance(result, str)) resultstr = """<?xml version="1.0"?>\n<div/>\n""" self.assertEqual(result, resultstr) - from repoze.bfg.xslt import XSLTemplateFactory - self.failUnless(isinstance(queryUtility(INodeTemplate, minimal), - XSLTemplateFactory)) + from repoze.bfg.xslt import XSLTemplateRenderer + self.failUnless(isinstance(queryUtility(INodeTemplateRenderer, minimal), + XSLTemplateRenderer)) def test_nonabs_registered(self): self._zcmlConfigure() from zope.component import getGlobalSiteManager from zope.component import queryUtility - from repoze.bfg.xslt import XSLTemplateFactory - from repoze.bfg.interfaces import INodeTemplate + from repoze.bfg.xslt import XSLTemplateRenderer + from repoze.bfg.interfaces import INodeTemplateRenderer minimal = self._getTemplatePath('minimal.xsl') - utility = XSLTemplateFactory(minimal) + utility = XSLTemplateRenderer(minimal) gsm = getGlobalSiteManager() - gsm.registerUtility(utility, INodeTemplate, name=minimal) + gsm.registerUtility(utility, INodeTemplateRenderer, name=minimal) render = self._getFUT() from lxml import etree info = etree.Element("info") @@ -154,5 +154,5 @@ class RenderTransformTests(unittest.TestCase, Base): self.failUnless(isinstance(result, str)) resultstr = """<?xml version="1.0"?>\n<div/>\n""" self.assertEqual(result, resultstr) - self.assertEqual(queryUtility(INodeTemplate, minimal), utility) + self.assertEqual(queryUtility(INodeTemplateRenderer, minimal), utility) diff --git a/repoze/bfg/traversal.py b/repoze/bfg/traversal.py index f5d45cd55..f7647879b 100644 --- a/repoze/bfg/traversal.py +++ b/repoze/bfg/traversal.py @@ -1,6 +1,6 @@ import urllib import urlparse - + from zope.interface import classProvides from zope.interface import implements from repoze.bfg.location import locate diff --git a/repoze/bfg/xslt.py b/repoze/bfg/xslt.py index 949bde6da..660a18130 100644 --- a/repoze/bfg/xslt.py +++ b/repoze/bfg/xslt.py @@ -5,14 +5,15 @@ from webob import Response from zope.component import queryUtility from zope.component import getSiteManager from zope.component.interfaces import ComponentLookupError +from zope.deprecation import deprecated from zope.interface import classProvides from zope.interface import implements from repoze.bfg.path import caller_path -from repoze.bfg.interfaces import INodeTemplate -from repoze.bfg.interfaces import ITemplateFactory +from repoze.bfg.interfaces import INodeTemplateRenderer +from repoze.bfg.interfaces import ITemplateRendererFactory def get_transform(path, node): """ Return a callable transform object. When called, the @@ -23,18 +24,18 @@ def get_transform(path, node): # Render using XSLT path = caller_path(path) - template = queryUtility(INodeTemplate, path) - if template is None: + renderer = queryUtility(INodeTemplateRenderer, path) + if renderer is None: if not os.path.exists(path): raise ValueError('Missing template file: %s' % path) - template = XSLTemplateFactory(path) + renderer = XSLTemplateRenderer(path) try: sm = getSiteManager() except ComponentLookupError: pass else: - sm.registerUtility(template, INodeTemplate, name=path) - return template + sm.registerUtility(renderer, INodeTemplateRenderer, name=path) + return renderer def render_transform(path, node, **kw): """ Render a XSL template at the package-relative path (may also @@ -52,9 +53,9 @@ def render_transform_to_response(path, node, **kw): result = render_transform(path, node, **kw) return Response(result) -class XSLTemplateFactory(object): - classProvides(ITemplateFactory) - implements(INodeTemplate) +class XSLTemplateRenderer(object): + classProvides(ITemplateRendererFactory) + implements(INodeTemplateRenderer) def __init__(self, path, auto_reload=False): self.path = path @@ -65,6 +66,12 @@ class XSLTemplateFactory(object): result = str(processor(node, **kw)) return result +XSLTemplateFactory = XSLTemplateRenderer +deprecated('ZPTTemplateFactory', + ('repoze.bfg.xslt.XSLTemplateFactory should now be ' + 'imported as repoze.bfg.xslt.XSLTTemplateRenderer')) + + # Manage XSLT processors on a per-thread basis import threading from lxml import etree |
