summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.txt34
-rw-r--r--docs/api/testing.rst10
-rw-r--r--docs/index.rst2
-rw-r--r--docs/narr/unittesting.rst13
-rw-r--r--repoze/bfg/chameleon_genshi.py80
-rw-r--r--repoze/bfg/chameleon_zpt.py86
-rw-r--r--repoze/bfg/interfaces.py46
-rw-r--r--repoze/bfg/templating.py30
-rw-r--r--repoze/bfg/testing.py275
-rw-r--r--repoze/bfg/tests/test_chameleon_genshi.py112
-rw-r--r--repoze/bfg/tests/test_chameleon_zpt.py116
-rw-r--r--repoze/bfg/tests/test_testing.py297
-rw-r--r--repoze/bfg/tests/test_xslt.py54
-rw-r--r--repoze/bfg/traversal.py2
-rw-r--r--repoze/bfg/xslt.py27
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