summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2009-11-19 11:26:23 +0000
committerChris McDonough <chrism@agendaless.com>2009-11-19 11:26:23 +0000
commita32d2a29df8948694efc78e2d30e7059f80deff7 (patch)
treefdb69b2d594429fef84f6f65c6abbe0ccad08c10
parenteac7c470021b647d63c2e2af8acd6cebd738f2a4 (diff)
downloadpyramid-a32d2a29df8948694efc78e2d30e7059f80deff7.tar.gz
pyramid-a32d2a29df8948694efc78e2d30e7059f80deff7.tar.bz2
pyramid-a32d2a29df8948694efc78e2d30e7059f80deff7.zip
- The ``repoze.bfg.view.rendered_response`` function has been moved to
``repoze.bfg.configuration.rendered_response``. - The ``repoze.bfg.view.decorate_view`` function has been moved to ``repoze.bfg.configuration.decorate_view``. - The ``repoze.bfg.view.MultiView`` class has been moved to ``repoze.bfg.configuration.MultiView``. - Fix argument ordering bug in r.b.configuration.Configurator.resource.
-rw-r--r--CHANGES.txt12
-rw-r--r--repoze/bfg/configuration.py145
-rw-r--r--repoze/bfg/router.py2
-rw-r--r--repoze/bfg/tests/test_configuration.py460
-rw-r--r--repoze/bfg/tests/test_router.py7
-rw-r--r--repoze/bfg/tests/test_view.py442
-rw-r--r--repoze/bfg/view.py136
7 files changed, 599 insertions, 605 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index a60e2aaa0..2de872afe 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -25,6 +25,18 @@ Internals
Its job has been subsumed by the ``repoze.bfg.settings.Settings``
class constructor.
+- The ``repoze.bfg.view.requestonly`` function has been moved to
+ ``repoze.bfg.configuration.requestonly``.
+
+- The ``repoze.bfg.view.rendered_response`` function has been moved to
+ ``repoze.bfg.configuration.rendered_response``.
+
+- The ``repoze.bfg.view.decorate_view`` function has been moved to
+ ``repoze.bfg.configuration.decorate_view``.
+
+- The ``repoze.bfg.view.MultiView`` class has been moved to
+ ``repoze.bfg.configuration.MultiView``.
+
Backwards Incompatibilites
--------------------------
diff --git a/repoze/bfg/configuration.py b/repoze/bfg/configuration.py
index 447cb5963..0c64d7411 100644
--- a/repoze/bfg/configuration.py
+++ b/repoze/bfg/configuration.py
@@ -4,6 +4,8 @@ import sys
import threading
import inspect
+from webob import Response
+
import zope.component
from zope.component.event import dispatch
@@ -12,10 +14,12 @@ from zope.configuration import xmlconfig
from zope.component import getGlobalSiteManager
from zope.component import getSiteManager
+from zope.component import queryUtility
from zope.interface import Interface
from zope.interface import implementedBy
from zope.interface.interfaces import IInterface
+from zope.interface import implements
from repoze.bfg.interfaces import IAuthenticationPolicy
from repoze.bfg.interfaces import IAuthorizationPolicy
@@ -27,6 +31,7 @@ from repoze.bfg.interfaces import INotFoundView
from repoze.bfg.interfaces import IPackageOverrides
from repoze.bfg.interfaces import IRendererFactory
from repoze.bfg.interfaces import IRequest
+from repoze.bfg.interfaces import IResponseFactory
from repoze.bfg.interfaces import IRootFactory
from repoze.bfg.interfaces import IRouteRequest
from repoze.bfg.interfaces import IRoutesMapper
@@ -54,11 +59,7 @@ from repoze.bfg.threadlocal import manager
from repoze.bfg.traversal import find_interface
from repoze.bfg.traversal import DefaultRootFactory
from repoze.bfg.urldispatch import RoutesMapper
-from repoze.bfg.view import MultiView
-from repoze.bfg.view import decorate_view
-from repoze.bfg.view import rendered_response
from repoze.bfg.view import render_view_to_response
-from repoze.bfg.view import requestonly
from repoze.bfg.view import static as static_view
import martian
@@ -508,8 +509,7 @@ class Configurator(object):
iface = ITemplateRendererFactory
self.reg.registerUtility(factory, iface, name=name, info=_info)
- def resource(self, to_override, override_with, _override=None,
- _info=u''):
+ def resource(self, to_override, override_with, _info=u'', _override=None,):
if to_override == override_with:
raise ConfigurationError('You cannot override a resource with '
'itself')
@@ -716,3 +716,136 @@ class BFGViewGrokker(martian.InstanceGrokker):
config.view(view=obj, _info=info, **settings)
return bool(config)
+class MultiView(object):
+ implements(IMultiView)
+
+ def __init__(self, name):
+ self.name = name
+ self.views = []
+
+ def add(self, view, score):
+ self.views.append((score, view))
+ self.views.sort()
+
+ def match(self, context, request):
+ for score, view in self.views:
+ if not hasattr(view, '__predicated__'):
+ return view
+ if view.__predicated__(context, request):
+ return view
+ raise NotFound(self.name)
+
+ def __permitted__(self, context, request):
+ view = self.match(context, request)
+ if hasattr(view, '__permitted__'):
+ return view.__permitted__(context, request)
+ return True
+
+ def __call_permissive__(self, context, request):
+ view = self.match(context, request)
+ view = getattr(view, '__call_permissive__', view)
+ return view(context, request)
+
+ def __call__(self, context, request):
+ for score, view in self.views:
+ try:
+ return view(context, request)
+ except NotFound:
+ continue
+ raise NotFound(self.name)
+
+def decorate_view(wrapped_view, original_view):
+ if wrapped_view is original_view:
+ return False
+ wrapped_view.__module__ = original_view.__module__
+ wrapped_view.__doc__ = original_view.__doc__
+ try:
+ wrapped_view.__name__ = original_view.__name__
+ except AttributeError:
+ wrapped_view.__name__ = repr(original_view)
+ try:
+ wrapped_view.__permitted__ = original_view.__permitted__
+ except AttributeError:
+ pass
+ try:
+ wrapped_view.__call_permissive__ = original_view.__call_permissive__
+ except AttributeError:
+ pass
+ try:
+ wrapped_view.__predicated__ = original_view.__predicated__
+ except AttributeError:
+ pass
+ return True
+
+def rendered_response(renderer, response, view, context,request,
+ renderer_name):
+ if ( hasattr(response, 'app_iter') and hasattr(response, 'headerlist')
+ and hasattr(response, 'status') ):
+ return response
+ result = renderer(response, {'view':view, 'renderer_name':renderer_name,
+ 'context':context, 'request':request})
+ response_factory = queryUtility(IResponseFactory, default=Response)
+ response = response_factory(result)
+ if request is not None: # in tests, it may be None
+ attrs = request.__dict__
+ content_type = attrs.get('response_content_type', None)
+ if content_type is not None:
+ response.content_type = content_type
+ headerlist = attrs.get('response_headerlist', None)
+ if headerlist is not None:
+ for k, v in headerlist:
+ response.headers.add(k, v)
+ status = attrs.get('response_status', None)
+ if status is not None:
+ response.status = status
+ charset = attrs.get('response_charset', None)
+ if charset is not None:
+ response.charset = charset
+ cache_for = attrs.get('response_cache_for', None)
+ if cache_for is not None:
+ response.cache_expires = cache_for
+ return response
+
+def requestonly(class_or_callable, attr=None):
+ """ Return true of the class or callable accepts only a request argument,
+ as opposed to something that accepts context, request """
+ if attr is None:
+ attr = '__call__'
+ if inspect.isfunction(class_or_callable):
+ fn = class_or_callable
+ elif inspect.isclass(class_or_callable):
+ try:
+ fn = class_or_callable.__init__
+ except AttributeError:
+ return False
+ else:
+ try:
+ fn = getattr(class_or_callable, attr)
+ except AttributeError:
+ return False
+
+ try:
+ argspec = inspect.getargspec(fn)
+ except TypeError:
+ return False
+
+ args = argspec[0]
+ defaults = argspec[3]
+
+ if hasattr(fn, 'im_func'):
+ # it's an instance method
+ if not args:
+ return False
+ args = args[1:]
+ if not args:
+ return False
+
+ if len(args) == 1:
+ return True
+
+ elif args[0] == 'request':
+ if len(args) - len(defaults) == 1:
+ return True
+
+ return False
+
diff --git a/repoze/bfg/router.py b/repoze/bfg/router.py
index 7edf40620..a46232330 100644
--- a/repoze/bfg/router.py
+++ b/repoze/bfg/router.py
@@ -190,7 +190,7 @@ def make_app(root_factory, package=None, filename='configure.zcml',
``settings`` keyword parameter.
"""
if Configurator is None:
- from repoze.bfg.configuration import Configurator
+ from repoze.bfg.configuration import Configurator # pragma: no cover
settings = settings or options
config = Configurator()
config.declarative(root_factory, package=package,
diff --git a/repoze/bfg/tests/test_configuration.py b/repoze/bfg/tests/test_configuration.py
index a1f60a91f..d2a9ca75f 100644
--- a/repoze/bfg/tests/test_configuration.py
+++ b/repoze/bfg/tests/test_configuration.py
@@ -1154,7 +1154,6 @@ class ConfiguratorTests(unittest.TestCase):
self.assertEqual(result(None, request).body, 'Hello!')
def test_default_config_fixtureapp_default_filename_withpackage(self):
- manager = DummyRegistryManager()
from repoze.bfg.tests import fixtureapp
rootfactory = DummyRootFactory(None)
registry = self._callDefaultConfiguration(rootfactory, fixtureapp)
@@ -1220,7 +1219,6 @@ class ConfiguratorTests(unittest.TestCase):
self.assertEqual(settings.mysetting, True)
def test_declarative_registrations(self):
- manager = DummyRegistryManager()
settings = {'reload_templates':True,
'debug_authorization':True}
from repoze.bfg.tests import fixtureapp
@@ -1313,19 +1311,450 @@ class TestBFGViewGrokker(unittest.TestCase):
result = grokker.grok('name', obj)
self.assertEqual(result, False)
-class DummyRequest:
- pass
+class Test_rendered_response(unittest.TestCase):
+ def setUp(self):
+ cleanUp()
+
+ def tearDown(self):
+ cleanUp()
+
+ def _callFUT(self, renderer, response, view=None,
+ context=None, request=None, renderer_name=None):
+ from repoze.bfg.configuration import rendered_response
+ if request is None:
+ request = DummyRequest()
+ return rendered_response(renderer, response, view,
+ context, request, renderer_name)
+
+ def _makeRenderer(self):
+ def renderer(*arg):
+ return 'Hello!'
+ return renderer
+
+ def test_is_response(self):
+ renderer = self._makeRenderer()
+ response = DummyResponse()
+ result = self._callFUT(renderer, response)
+ self.assertEqual(result, response)
+
+ def test_calls_renderer(self):
+ renderer = self._makeRenderer()
+ response = {'a':'1'}
+ result = self._callFUT(renderer, response)
+ self.assertEqual(result.body, 'Hello!')
+
+ def test_with_content_type(self):
+ renderer = self._makeRenderer()
+ response = {'a':'1'}
+ request = DummyRequest()
+ attrs = {'response_content_type':'text/nonsense'}
+ request.__dict__.update(attrs)
+ result = self._callFUT(renderer, response, request=request)
+ self.assertEqual(result.content_type, 'text/nonsense')
+
+ def test_with_headerlist(self):
+ renderer = self._makeRenderer()
+ response = {'a':'1'}
+ request = DummyRequest()
+ attrs = {'response_headerlist':[('a', '1'), ('b', '2')]}
+ request.__dict__.update(attrs)
+ result = self._callFUT(renderer, response, request=request)
+ self.assertEqual(result.headerlist,
+ [('Content-Type', 'text/html; charset=UTF-8'),
+ ('Content-Length', '6'),
+ ('a', '1'),
+ ('b', '2')])
+
+ def test_with_status(self):
+ renderer = self._makeRenderer()
+ response = {'a':'1'}
+ request = DummyRequest()
+ attrs = {'response_status':'406 You Lose'}
+ request.__dict__.update(attrs)
+ result = self._callFUT(renderer, response, request=request)
+ self.assertEqual(result.status, '406 You Lose')
+
+ def test_with_charset(self):
+ renderer = self._makeRenderer()
+ response = {'a':'1'}
+ request = DummyRequest()
+ attrs = {'response_charset':'UTF-16'}
+ request.__dict__.update(attrs)
+ result = self._callFUT(renderer, response, request=request)
+ self.assertEqual(result.charset, 'UTF-16')
+
+ def test_with_cache_for(self):
+ renderer = self._makeRenderer()
+ response = {'a':'1'}
+ request = DummyRequest()
+ attrs = {'response_cache_for':100}
+ request.__dict__.update(attrs)
+ result = self._callFUT(renderer, response, request=request)
+ self.assertEqual(result.cache_control.max_age, 100)
+
+class Test_decorate_view(unittest.TestCase):
+ def _callFUT(self, wrapped, original):
+ from repoze.bfg.configuration import decorate_view
+ return decorate_view(wrapped, original)
+
+ def test_it_same(self):
+ def view(context, request):
+ """ """
+ result = self._callFUT(view, view)
+ self.assertEqual(result, False)
+
+ def test_it_different(self):
+ class DummyView1:
+ """ 1 """
+ __name__ = '1'
+ __module__ = '1'
+ def __call__(self, context, request):
+ """ """
+ def __call_permissive__(self, context, reuqest):
+ """ """
+ def __predicated__(self, context, reuqest):
+ """ """
+ def __permitted__(self, context, request):
+ """ """
+ class DummyView2:
+ """ 2 """
+ __name__ = '2'
+ __module__ = '2'
+ def __call__(self, context, request):
+ """ """
+ def __call_permissive__(self, context, reuqest):
+ """ """
+ def __predicated__(self, context, reuqest):
+ """ """
+ def __permitted__(self, context, request):
+ """ """
+ view1 = DummyView1()
+ view2 = DummyView2()
+ result = self._callFUT(view1, view2)
+ self.assertEqual(result, True)
+ self.failUnless(view1.__doc__ is view2.__doc__)
+ self.failUnless(view1.__module__ is view2.__module__)
+ self.failUnless(view1.__name__ is view2.__name__)
+ self.failUnless(view1.__call_permissive__.im_func is
+ view2.__call_permissive__.im_func)
+ self.failUnless(view1.__permitted__.im_func is
+ view2.__permitted__.im_func)
+ self.failUnless(view1.__predicated__.im_func is
+ view2.__predicated__.im_func)
+
+
+class TestMultiView(unittest.TestCase):
+ def _getTargetClass(self):
+ from repoze.bfg.configuration import MultiView
+ return MultiView
+
+ def _makeOne(self, name='name'):
+ return self._getTargetClass()(name)
+
+ def test_class_implements_ISecuredView(self):
+ from zope.interface.verify import verifyClass
+ from repoze.bfg.interfaces import ISecuredView
+ verifyClass(ISecuredView, self._getTargetClass())
+
+ def test_instance_implements_ISecuredView(self):
+ from zope.interface.verify import verifyObject
+ from repoze.bfg.interfaces import ISecuredView
+ verifyObject(ISecuredView, self._makeOne())
+
+ def test_add(self):
+ mv = self._makeOne()
+ mv.add('view', 100)
+ self.assertEqual(mv.views, [(100, 'view')])
+ mv.add('view2', 99)
+ self.assertEqual(mv.views, [(99, 'view2'), (100, 'view')])
+
+ def test_match_not_found(self):
+ from repoze.bfg.exceptions import NotFound
+ mv = self._makeOne()
+ context = DummyContext()
+ request = DummyRequest()
+ self.assertRaises(NotFound, mv.match, context, request)
+
+ def test_match_predicate_fails(self):
+ from repoze.bfg.exceptions import NotFound
+ mv = self._makeOne()
+ def view(context, request):
+ """ """
+ view.__predicated__ = lambda *arg: False
+ mv.views = [(100, view)]
+ context = DummyContext()
+ request = DummyRequest()
+ self.assertRaises(NotFound, mv.match, context, request)
+
+ def test_match_predicate_succeeds(self):
+ mv = self._makeOne()
+ def view(context, request):
+ """ """
+ view.__predicated__ = lambda *arg: True
+ mv.views = [(100, view)]
+ context = DummyContext()
+ request = DummyRequest()
+ result = mv.match(context, request)
+ self.assertEqual(result, view)
-class DummyRegistryManager:
- def push(self, registry):
- from repoze.bfg.threadlocal import manager
- manager.push(registry)
- self.pushed = True
+ def test_permitted_no_views(self):
+ from repoze.bfg.exceptions import NotFound
+ mv = self._makeOne()
+ context = DummyContext()
+ request = DummyRequest()
+ self.assertRaises(NotFound, mv.__permitted__, context, request)
- def pop(self):
- from repoze.bfg.threadlocal import manager
- manager.pop()
- self.popped = True
+ def test_permitted_no_match_with__permitted__(self):
+ mv = self._makeOne()
+ def view(context, request):
+ """ """
+ mv.views = [(100, view)]
+ context = DummyContext()
+ request = DummyRequest()
+ self.assertEqual(mv.__permitted__(None, None), True)
+
+ def test_permitted(self):
+ from zope.component import getSiteManager
+ mv = self._makeOne()
+ def view(context, request):
+ """ """
+ def permitted(context, request):
+ return False
+ view.__permitted__ = permitted
+ mv.views = [(100, view)]
+ context = DummyContext()
+ request = DummyRequest()
+ sm = getSiteManager()
+ result = mv.__permitted__(context, request)
+ self.assertEqual(result, False)
+
+ def test__call__not_found(self):
+ from repoze.bfg.exceptions import NotFound
+ mv = self._makeOne()
+ context = DummyContext()
+ request = DummyRequest()
+ self.assertRaises(NotFound, mv, context, request)
+
+ def test___call__intermediate_not_found(self):
+ from repoze.bfg.exceptions import NotFound
+ mv = self._makeOne()
+ context = DummyContext()
+ request = DummyRequest()
+ request.view_name = ''
+ expected_response = DummyResponse()
+ def view1(context, request):
+ raise NotFound
+ def view2(context, request):
+ return expected_response
+ mv.views = [(100, view1), (99, view2)]
+ response = mv(context, request)
+ self.assertEqual(response, expected_response)
+
+ def test___call__(self):
+ mv = self._makeOne()
+ context = DummyContext()
+ request = DummyRequest()
+ request.view_name = ''
+ expected_response = DummyResponse()
+ def view(context, request):
+ return expected_response
+ mv.views = [(100, view)]
+ response = mv(context, request)
+ self.assertEqual(response, expected_response)
+
+ def test__call_permissive__not_found(self):
+ from repoze.bfg.exceptions import NotFound
+ mv = self._makeOne()
+ context = DummyContext()
+ request = DummyRequest()
+ self.assertRaises(NotFound, mv, context, request)
+
+ def test___call_permissive_has_call_permissive(self):
+ mv = self._makeOne()
+ context = DummyContext()
+ request = DummyRequest()
+ request.view_name = ''
+ expected_response = DummyResponse()
+ def view(context, request):
+ """ """
+ def permissive(context, request):
+ return expected_response
+ view.__call_permissive__ = permissive
+ mv.views = [(100, view)]
+ response = mv.__call_permissive__(context, request)
+ self.assertEqual(response, expected_response)
+
+ def test___call_permissive_has_no_call_permissive(self):
+ mv = self._makeOne()
+ context = DummyContext()
+ request = DummyRequest()
+ request.view_name = ''
+ expected_response = DummyResponse()
+ def view(context, request):
+ return expected_response
+ mv.views = [(100, view)]
+ response = mv.__call_permissive__(context, request)
+ self.assertEqual(response, expected_response)
+
+class TestRequestOnly(unittest.TestCase):
+ def _callFUT(self, arg):
+ from repoze.bfg.configuration import requestonly
+ return requestonly(arg)
+
+ def test_newstyle_class_no_init(self):
+ class foo(object):
+ """ """
+ self.assertFalse(self._callFUT(foo))
+
+ def test_newstyle_class_init_toomanyargs(self):
+ class foo(object):
+ def __init__(self, context, request):
+ """ """
+ self.assertFalse(self._callFUT(foo))
+
+ def test_newstyle_class_init_onearg_named_request(self):
+ class foo(object):
+ def __init__(self, request):
+ """ """
+ self.assertTrue(self._callFUT(foo))
+
+ def test_newstyle_class_init_onearg_named_somethingelse(self):
+ class foo(object):
+ def __init__(self, req):
+ """ """
+ self.assertTrue(self._callFUT(foo))
+
+ def test_newstyle_class_init_defaultargs_firstname_not_request(self):
+ class foo(object):
+ def __init__(self, context, request=None):
+ """ """
+ self.assertFalse(self._callFUT(foo))
+
+ def test_newstyle_class_init_defaultargs_firstname_request(self):
+ class foo(object):
+ def __init__(self, request, foo=1, bar=2):
+ """ """
+ self.assertTrue(self._callFUT(foo))
+
+ def test_newstyle_class_init_noargs(self):
+ class foo(object):
+ def __init__():
+ """ """
+ self.assertFalse(self._callFUT(foo))
+
+ def test_oldstyle_class_no_init(self):
+ class foo:
+ """ """
+ self.assertFalse(self._callFUT(foo))
+
+ def test_oldstyle_class_init_toomanyargs(self):
+ class foo:
+ def __init__(self, context, request):
+ """ """
+ self.assertFalse(self._callFUT(foo))
+
+ def test_oldstyle_class_init_onearg_named_request(self):
+ class foo:
+ def __init__(self, request):
+ """ """
+ self.assertTrue(self._callFUT(foo))
+
+ def test_oldstyle_class_init_onearg_named_somethingelse(self):
+ class foo:
+ def __init__(self, req):
+ """ """
+ self.assertTrue(self._callFUT(foo))
+
+ def test_oldstyle_class_init_defaultargs_firstname_not_request(self):
+ class foo:
+ def __init__(self, context, request=None):
+ """ """
+ self.assertFalse(self._callFUT(foo))
+
+ def test_oldstyle_class_init_defaultargs_firstname_request(self):
+ class foo:
+ def __init__(self, request, foo=1, bar=2):
+ """ """
+ self.assertTrue(self._callFUT(foo), True)
+
+ def test_oldstyle_class_init_noargs(self):
+ class foo:
+ def __init__():
+ """ """
+ self.assertFalse(self._callFUT(foo))
+
+ def test_function_toomanyargs(self):
+ def foo(context, request):
+ """ """
+ self.assertFalse(self._callFUT(foo))
+
+ def test_function_onearg_named_request(self):
+ def foo(request):
+ """ """
+ self.assertTrue(self._callFUT(foo))
+
+ def test_function_onearg_named_somethingelse(self):
+ def foo(req):
+ """ """
+ self.assertTrue(self._callFUT(foo))
+
+ def test_function_defaultargs_firstname_not_request(self):
+ def foo(context, request=None):
+ """ """
+ self.assertFalse(self._callFUT(foo))
+
+ def test_function_defaultargs_firstname_request(self):
+ def foo(request, foo=1, bar=2):
+ """ """
+ self.assertTrue(self._callFUT(foo))
+
+ def test_function_noargs(self):
+ def foo():
+ """ """
+ self.assertFalse(self._callFUT(foo))
+
+ def test_instance_toomanyargs(self):
+ class Foo:
+ def __call__(self, context, request):
+ """ """
+ foo = Foo()
+ self.assertFalse(self._callFUT(foo))
+
+ def test_instance_defaultargs_onearg_named_request(self):
+ class Foo:
+ def __call__(self, request):
+ """ """
+ foo = Foo()
+ self.assertTrue(self._callFUT(foo))
+
+ def test_instance_defaultargs_onearg_named_somethingelse(self):
+ class Foo:
+ def __call__(self, req):
+ """ """
+ foo = Foo()
+ self.assertTrue(self._callFUT(foo))
+
+ def test_instance_defaultargs_firstname_not_request(self):
+ class Foo:
+ def __call__(self, context, request=None):
+ """ """
+ foo = Foo()
+ self.assertFalse(self._callFUT(foo))
+
+ def test_instance_defaultargs_firstname_request(self):
+ class Foo:
+ def __call__(self, request, foo=1, bar=2):
+ """ """
+ foo = Foo()
+ self.assertTrue(self._callFUT(foo), True)
+
+ def test_instance_nocall(self):
+ class Foo: pass
+ foo = Foo()
+ self.assertFalse(self._callFUT(foo))
+
+class DummyRequest:
+ pass
class DummyRootFactory:
def __init__(self, root):
@@ -1359,3 +1788,8 @@ class IDummy(Interface):
class IOther(Interface):
pass
+
+class DummyResponse:
+ status = '200 OK'
+ headerlist = ()
+ app_iter = ()
diff --git a/repoze/bfg/tests/test_router.py b/repoze/bfg/tests/test_router.py
index f3fe6dd70..e747a26e6 100644
--- a/repoze/bfg/tests/test_router.py
+++ b/repoze/bfg/tests/test_router.py
@@ -612,13 +612,6 @@ class DummyLogger:
warn = info
debug = info
-class DummyRegistryManager:
- def push(self, registry):
- self.pushed = True
-
- def pop(self):
- self.popped = True
-
class DummyConfigurator(object):
def make_wsgi_app(self):
return self
diff --git a/repoze/bfg/tests/test_view.py b/repoze/bfg/tests/test_view.py
index e06f6225f..c293394c1 100644
--- a/repoze/bfg/tests/test_view.py
+++ b/repoze/bfg/tests/test_view.py
@@ -526,86 +526,6 @@ class AppendSlashNotFoundView(unittest.TestCase):
self.assertEqual(response.status, '302 Found')
self.assertEqual(response.location, '/abc/')
-class Test_rendered_response(unittest.TestCase):
- def setUp(self):
- cleanUp()
-
- def tearDown(self):
- cleanUp()
-
- def _callFUT(self, renderer, response, view=None,
- context=None, request=None, renderer_name=None):
- from repoze.bfg.view import rendered_response
- if request is None:
- request = DummyRequest()
- return rendered_response(renderer, response, view,
- context, request, renderer_name)
-
- def _makeRenderer(self):
- def renderer(*arg):
- return 'Hello!'
- return renderer
-
- def test_is_response(self):
- renderer = self._makeRenderer()
- response = DummyResponse()
- result = self._callFUT(renderer, response)
- self.assertEqual(result, response)
-
- def test_calls_renderer(self):
- renderer = self._makeRenderer()
- response = {'a':'1'}
- result = self._callFUT(renderer, response)
- self.assertEqual(result.body, 'Hello!')
-
- def test_with_content_type(self):
- renderer = self._makeRenderer()
- response = {'a':'1'}
- request = DummyRequest()
- attrs = {'response_content_type':'text/nonsense'}
- request.__dict__.update(attrs)
- result = self._callFUT(renderer, response, request=request)
- self.assertEqual(result.content_type, 'text/nonsense')
-
- def test_with_headerlist(self):
- renderer = self._makeRenderer()
- response = {'a':'1'}
- request = DummyRequest()
- attrs = {'response_headerlist':[('a', '1'), ('b', '2')]}
- request.__dict__.update(attrs)
- result = self._callFUT(renderer, response, request=request)
- self.assertEqual(result.headerlist,
- [('Content-Type', 'text/html; charset=UTF-8'),
- ('Content-Length', '6'),
- ('a', '1'),
- ('b', '2')])
-
- def test_with_status(self):
- renderer = self._makeRenderer()
- response = {'a':'1'}
- request = DummyRequest()
- attrs = {'response_status':'406 You Lose'}
- request.__dict__.update(attrs)
- result = self._callFUT(renderer, response, request=request)
- self.assertEqual(result.status, '406 You Lose')
-
- def test_with_charset(self):
- renderer = self._makeRenderer()
- response = {'a':'1'}
- request = DummyRequest()
- attrs = {'response_charset':'UTF-16'}
- request.__dict__.update(attrs)
- result = self._callFUT(renderer, response, request=request)
- self.assertEqual(result.charset, 'UTF-16')
-
- def test_with_cache_for(self):
- renderer = self._makeRenderer()
- response = {'a':'1'}
- request = DummyRequest()
- attrs = {'response_cache_for':100}
- request.__dict__.update(attrs)
- result = self._callFUT(renderer, response, request=request)
- self.assertEqual(result.cache_control.max_age, 100)
class TestDeriveView(unittest.TestCase):
def setUp(self):
@@ -921,368 +841,6 @@ class TestDeriveView(unittest.TestCase):
inner_view, viewname='inner', wrapper_viewname='owrap')
result = self.assertRaises(ValueError, wrapped, None, request)
-class TestDecorateView(unittest.TestCase):
- def _callFUT(self, wrapped, original):
- from repoze.bfg.view import decorate_view
- return decorate_view(wrapped, original)
-
- def test_it_same(self):
- def view(context, request):
- """ """
- result = self._callFUT(view, view)
- self.assertEqual(result, False)
-
- def test_it_different(self):
- class DummyView1:
- """ 1 """
- __name__ = '1'
- __module__ = '1'
- def __call__(self, context, request):
- """ """
- def __call_permissive__(self, context, reuqest):
- """ """
- def __predicated__(self, context, reuqest):
- """ """
- def __permitted__(self, context, request):
- """ """
- class DummyView2:
- """ 2 """
- __name__ = '2'
- __module__ = '2'
- def __call__(self, context, request):
- """ """
- def __call_permissive__(self, context, reuqest):
- """ """
- def __predicated__(self, context, reuqest):
- """ """
- def __permitted__(self, context, request):
- """ """
- view1 = DummyView1()
- view2 = DummyView2()
- result = self._callFUT(view1, view2)
- self.assertEqual(result, True)
- self.failUnless(view1.__doc__ is view2.__doc__)
- self.failUnless(view1.__module__ is view2.__module__)
- self.failUnless(view1.__name__ is view2.__name__)
- self.failUnless(view1.__call_permissive__.im_func is
- view2.__call_permissive__.im_func)
- self.failUnless(view1.__permitted__.im_func is
- view2.__permitted__.im_func)
- self.failUnless(view1.__predicated__.im_func is
- view2.__predicated__.im_func)
-
-class TestMultiView(unittest.TestCase):
- def _getTargetClass(self):
- from repoze.bfg.view import MultiView
- return MultiView
-
- def _makeOne(self, name='name'):
- return self._getTargetClass()(name)
-
- def test_class_implements_ISecuredView(self):
- from zope.interface.verify import verifyClass
- from repoze.bfg.interfaces import ISecuredView
- verifyClass(ISecuredView, self._getTargetClass())
-
- def test_instance_implements_ISecuredView(self):
- from zope.interface.verify import verifyObject
- from repoze.bfg.interfaces import ISecuredView
- verifyObject(ISecuredView, self._makeOne())
-
- def test_add(self):
- mv = self._makeOne()
- mv.add('view', 100)
- self.assertEqual(mv.views, [(100, 'view')])
- mv.add('view2', 99)
- self.assertEqual(mv.views, [(99, 'view2'), (100, 'view')])
-
- def test_match_not_found(self):
- from repoze.bfg.exceptions import NotFound
- mv = self._makeOne()
- context = DummyContext()
- request = DummyRequest()
- self.assertRaises(NotFound, mv.match, context, request)
-
- def test_match_predicate_fails(self):
- from repoze.bfg.exceptions import NotFound
- mv = self._makeOne()
- def view(context, request):
- """ """
- view.__predicated__ = lambda *arg: False
- mv.views = [(100, view)]
- context = DummyContext()
- request = DummyRequest()
- self.assertRaises(NotFound, mv.match, context, request)
-
- def test_match_predicate_succeeds(self):
- mv = self._makeOne()
- def view(context, request):
- """ """
- view.__predicated__ = lambda *arg: True
- mv.views = [(100, view)]
- context = DummyContext()
- request = DummyRequest()
- result = mv.match(context, request)
- self.assertEqual(result, view)
-
- def test_permitted_no_views(self):
- from repoze.bfg.exceptions import NotFound
- mv = self._makeOne()
- context = DummyContext()
- request = DummyRequest()
- self.assertRaises(NotFound, mv.__permitted__, context, request)
-
- def test_permitted_no_match_with__permitted__(self):
- mv = self._makeOne()
- def view(context, request):
- """ """
- mv.views = [(100, view)]
- context = DummyContext()
- request = DummyRequest()
- self.assertEqual(mv.__permitted__(None, None), True)
-
- def test_permitted(self):
- from zope.component import getSiteManager
- mv = self._makeOne()
- def view(context, request):
- """ """
- def permitted(context, request):
- return False
- view.__permitted__ = permitted
- mv.views = [(100, view)]
- context = DummyContext()
- request = DummyRequest()
- sm = getSiteManager()
- result = mv.__permitted__(context, request)
- self.assertEqual(result, False)
-
- def test__call__not_found(self):
- from repoze.bfg.exceptions import NotFound
- mv = self._makeOne()
- context = DummyContext()
- request = DummyRequest()
- self.assertRaises(NotFound, mv, context, request)
-
- def test___call__intermediate_not_found(self):
- from repoze.bfg.exceptions import NotFound
- mv = self._makeOne()
- context = DummyContext()
- request = DummyRequest()
- request.view_name = ''
- expected_response = DummyResponse()
- def view1(context, request):
- raise NotFound
- def view2(context, request):
- return expected_response
- mv.views = [(100, view1), (99, view2)]
- response = mv(context, request)
- self.assertEqual(response, expected_response)
-
- def test___call__(self):
- mv = self._makeOne()
- context = DummyContext()
- request = DummyRequest()
- request.view_name = ''
- expected_response = DummyResponse()
- def view(context, request):
- return expected_response
- mv.views = [(100, view)]
- response = mv(context, request)
- self.assertEqual(response, expected_response)
-
- def test__call_permissive__not_found(self):
- from repoze.bfg.exceptions import NotFound
- mv = self._makeOne()
- context = DummyContext()
- request = DummyRequest()
- self.assertRaises(NotFound, mv, context, request)
-
- def test___call_permissive_has_call_permissive(self):
- mv = self._makeOne()
- context = DummyContext()
- request = DummyRequest()
- request.view_name = ''
- expected_response = DummyResponse()
- def view(context, request):
- """ """
- def permissive(context, request):
- return expected_response
- view.__call_permissive__ = permissive
- mv.views = [(100, view)]
- response = mv.__call_permissive__(context, request)
- self.assertEqual(response, expected_response)
-
- def test___call_permissive_has_no_call_permissive(self):
- mv = self._makeOne()
- context = DummyContext()
- request = DummyRequest()
- request.view_name = ''
- expected_response = DummyResponse()
- def view(context, request):
- return expected_response
- mv.views = [(100, view)]
- response = mv.__call_permissive__(context, request)
- self.assertEqual(response, expected_response)
-
-class TestRequestOnly(unittest.TestCase):
- def _callFUT(self, arg):
- from repoze.bfg.view import requestonly
- return requestonly(arg)
-
- def test_newstyle_class_no_init(self):
- class foo(object):
- """ """
- self.assertFalse(self._callFUT(foo))
-
- def test_newstyle_class_init_toomanyargs(self):
- class foo(object):
- def __init__(self, context, request):
- """ """
- self.assertFalse(self._callFUT(foo))
-
- def test_newstyle_class_init_onearg_named_request(self):
- class foo(object):
- def __init__(self, request):
- """ """
- self.assertTrue(self._callFUT(foo))
-
- def test_newstyle_class_init_onearg_named_somethingelse(self):
- class foo(object):
- def __init__(self, req):
- """ """
- self.assertTrue(self._callFUT(foo))
-
- def test_newstyle_class_init_defaultargs_firstname_not_request(self):
- class foo(object):
- def __init__(self, context, request=None):
- """ """
- self.assertFalse(self._callFUT(foo))
-
- def test_newstyle_class_init_defaultargs_firstname_request(self):
- class foo(object):
- def __init__(self, request, foo=1, bar=2):
- """ """
- self.assertTrue(self._callFUT(foo))
-
- def test_newstyle_class_init_noargs(self):
- class foo(object):
- def __init__():
- """ """
- self.assertFalse(self._callFUT(foo))
-
- def test_oldstyle_class_no_init(self):
- class foo:
- """ """
- self.assertFalse(self._callFUT(foo))
-
- def test_oldstyle_class_init_toomanyargs(self):
- class foo:
- def __init__(self, context, request):
- """ """
- self.assertFalse(self._callFUT(foo))
-
- def test_oldstyle_class_init_onearg_named_request(self):
- class foo:
- def __init__(self, request):
- """ """
- self.assertTrue(self._callFUT(foo))
-
- def test_oldstyle_class_init_onearg_named_somethingelse(self):
- class foo:
- def __init__(self, req):
- """ """
- self.assertTrue(self._callFUT(foo))
-
- def test_oldstyle_class_init_defaultargs_firstname_not_request(self):
- class foo:
- def __init__(self, context, request=None):
- """ """
- self.assertFalse(self._callFUT(foo))
-
- def test_oldstyle_class_init_defaultargs_firstname_request(self):
- class foo:
- def __init__(self, request, foo=1, bar=2):
- """ """
- self.assertTrue(self._callFUT(foo), True)
-
- def test_oldstyle_class_init_noargs(self):
- class foo:
- def __init__():
- """ """
- self.assertFalse(self._callFUT(foo))
-
- def test_function_toomanyargs(self):
- def foo(context, request):
- """ """
- self.assertFalse(self._callFUT(foo))
-
- def test_function_onearg_named_request(self):
- def foo(request):
- """ """
- self.assertTrue(self._callFUT(foo))
-
- def test_function_onearg_named_somethingelse(self):
- def foo(req):
- """ """
- self.assertTrue(self._callFUT(foo))
-
- def test_function_defaultargs_firstname_not_request(self):
- def foo(context, request=None):
- """ """
- self.assertFalse(self._callFUT(foo))
-
- def test_function_defaultargs_firstname_request(self):
- def foo(request, foo=1, bar=2):
- """ """
- self.assertTrue(self._callFUT(foo))
-
- def test_function_noargs(self):
- def foo():
- """ """
- self.assertFalse(self._callFUT(foo))
-
- def test_instance_toomanyargs(self):
- class Foo:
- def __call__(self, context, request):
- """ """
- foo = Foo()
- self.assertFalse(self._callFUT(foo))
-
- def test_instance_defaultargs_onearg_named_request(self):
- class Foo:
- def __call__(self, request):
- """ """
- foo = Foo()
- self.assertTrue(self._callFUT(foo))
-
- def test_instance_defaultargs_onearg_named_somethingelse(self):
- class Foo:
- def __call__(self, req):
- """ """
- foo = Foo()
- self.assertTrue(self._callFUT(foo))
-
- def test_instance_defaultargs_firstname_not_request(self):
- class Foo:
- def __call__(self, context, request=None):
- """ """
- foo = Foo()
- self.assertFalse(self._callFUT(foo))
-
- def test_instance_defaultargs_firstname_request(self):
- class Foo:
- def __call__(self, request, foo=1, bar=2):
- """ """
- foo = Foo()
- self.assertTrue(self._callFUT(foo), True)
-
- def test_instance_nocall(self):
- class Foo: pass
- foo = Foo()
- self.assertFalse(self._callFUT(foo))
-
-
-
class DummyContext:
pass
diff --git a/repoze/bfg/view.py b/repoze/bfg/view.py
index 43ad809c1..8ef8f3bb6 100644
--- a/repoze/bfg/view.py
+++ b/repoze/bfg/view.py
@@ -2,7 +2,6 @@ import cgi
import mimetypes
import os
import sys
-import inspect
# See http://bugs.python.org/issue5853 which is a recursion bug
# that seems to effect Python 2.6, Python 2.6.1, and 2.6.2 (a fix
@@ -23,15 +22,12 @@ from zope.component import getSiteManager
from zope.component import providedBy
from zope.component import queryUtility
from zope.deprecation import deprecated
-from zope.interface import implements
from zope.interface.advice import getFrameInfo
-from repoze.bfg.interfaces import IMultiView
from repoze.bfg.interfaces import IResponseFactory
from repoze.bfg.interfaces import IRoutesMapper
from repoze.bfg.interfaces import IView
-from repoze.bfg.exceptions import NotFound
from repoze.bfg.path import caller_package
from repoze.bfg.resource import resource_spec
from repoze.bfg.static import PackageURLParser
@@ -513,135 +509,3 @@ def derive_view(original_view, permission=None, predicates=(), attr=None,
wrapper_viewname=wrapper_viewname,
viewname=viewname)
-def requestonly(class_or_callable, attr=None):
- """ Return true of the class or callable accepts only a request argument,
- as opposed to something that accepts context, request """
- if attr is None:
- attr = '__call__'
- if inspect.isfunction(class_or_callable):
- fn = class_or_callable
- elif inspect.isclass(class_or_callable):
- try:
- fn = class_or_callable.__init__
- except AttributeError:
- return False
- else:
- try:
- fn = getattr(class_or_callable, attr)
- except AttributeError:
- return False
-
- try:
- argspec = inspect.getargspec(fn)
- except TypeError:
- return False
-
- args = argspec[0]
- defaults = argspec[3]
-
- if hasattr(fn, 'im_func'):
- # it's an instance method
- if not args:
- return False
- args = args[1:]
- if not args:
- return False
-
- if len(args) == 1:
- return True
-
- elif args[0] == 'request':
- if len(args) - len(defaults) == 1:
- return True
-
- return False
-
-class MultiView(object):
- implements(IMultiView)
-
- def __init__(self, name):
- self.name = name
- self.views = []
-
- def add(self, view, score):
- self.views.append((score, view))
- self.views.sort()
-
- def match(self, context, request):
- for score, view in self.views:
- if not hasattr(view, '__predicated__'):
- return view
- if view.__predicated__(context, request):
- return view
- raise NotFound(self.name)
-
- def __permitted__(self, context, request):
- view = self.match(context, request)
- if hasattr(view, '__permitted__'):
- return view.__permitted__(context, request)
- return True
-
- def __call_permissive__(self, context, request):
- view = self.match(context, request)
- view = getattr(view, '__call_permissive__', view)
- return view(context, request)
-
- def __call__(self, context, request):
- for score, view in self.views:
- try:
- return view(context, request)
- except NotFound:
- continue
- raise NotFound(self.name)
-
-def decorate_view(wrapped_view, original_view):
- if wrapped_view is original_view:
- return False
- wrapped_view.__module__ = original_view.__module__
- wrapped_view.__doc__ = original_view.__doc__
- try:
- wrapped_view.__name__ = original_view.__name__
- except AttributeError:
- wrapped_view.__name__ = repr(original_view)
- try:
- wrapped_view.__permitted__ = original_view.__permitted__
- except AttributeError:
- pass
- try:
- wrapped_view.__call_permissive__ = original_view.__call_permissive__
- except AttributeError:
- pass
- try:
- wrapped_view.__predicated__ = original_view.__predicated__
- except AttributeError:
- pass
- return True
-
-def rendered_response(renderer, response, view, context,request,
- renderer_name):
- if ( hasattr(response, 'app_iter') and hasattr(response, 'headerlist')
- and hasattr(response, 'status') ):
- return response
- result = renderer(response, {'view':view, 'renderer_name':renderer_name,
- 'context':context, 'request':request})
- response_factory = queryUtility(IResponseFactory, default=Response)
- response = response_factory(result)
- if request is not None: # in tests, it may be None
- attrs = request.__dict__
- content_type = attrs.get('response_content_type', None)
- if content_type is not None:
- response.content_type = content_type
- headerlist = attrs.get('response_headerlist', None)
- if headerlist is not None:
- for k, v in headerlist:
- response.headers.add(k, v)
- status = attrs.get('response_status', None)
- if status is not None:
- response.status = status
- charset = attrs.get('response_charset', None)
- if charset is not None:
- response.charset = charset
- cache_for = attrs.get('response_cache_for', None)
- if cache_for is not None:
- response.cache_expires = cache_for
- return response