summaryrefslogtreecommitdiff
path: root/repoze/bfg/tests
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2009-01-27 21:57:11 +0000
committerChris McDonough <chrism@agendaless.com>2009-01-27 21:57:11 +0000
commite62e479e338e428f6cfd3b07790545982b7cb94f (patch)
treec9784577f791d4a8ea5b80a9fce211ce86009712 /repoze/bfg/tests
parent2301cf61977102b85279ea7c04797f76012202e5 (diff)
downloadpyramid-e62e479e338e428f6cfd3b07790545982b7cb94f.tar.gz
pyramid-e62e479e338e428f6cfd3b07790545982b7cb94f.tar.bz2
pyramid-e62e479e338e428f6cfd3b07790545982b7cb94f.zip
Features
-------- - The ``repoze.bfg.url.model_url`` API now works against contexts derived from Routes URL dispatch (``Routes.util.url_for`` is called under the hood). - "Virtual root" support for traversal-based applications has been added. Virtual root support is useful when you'd like to host some model in a :mod:`repoze.bfg` model graph as an application under a URL pathname that does not include the model path itself. For more information, see the (new) "Virtual Hosting" chapter in the documentation. - A ``repoze.bfg.traversal.virtual_root`` API has been added. When called, it returns the virtual root object (or the physical root object if no virtual root has been specified). Implementation Changes ---------------------- - ``repoze.bfg.traversal.RoutesModelTraverser`` has been moved to ``repoze.bfg.urldispatch``. - ``model_url`` URL generation is now performed via an adapter lookup based on the context and the request. - ZCML which registers two adapters for the ``IContextURL`` interface has been added to the configure.zcml in ``repoze.bfg.includes``.
Diffstat (limited to 'repoze/bfg/tests')
-rw-r--r--repoze/bfg/tests/test_integration.py2
-rw-r--r--repoze/bfg/tests/test_traversal.py231
-rw-r--r--repoze/bfg/tests/test_url.py158
-rw-r--r--repoze/bfg/tests/test_urldispatch.py126
4 files changed, 324 insertions, 193 deletions
diff --git a/repoze/bfg/tests/test_integration.py b/repoze/bfg/tests/test_integration.py
index 4c5777738..b6e5e1c0c 100644
--- a/repoze/bfg/tests/test_integration.py
+++ b/repoze/bfg/tests/test_integration.py
@@ -153,7 +153,7 @@ class TestGrokkedApp(unittest.TestCase):
actions = context.actions
import cPickle
self.assertRaises(cPickle.PicklingError, cPickle.dumps, actions, -1)
- self.assertEqual(len(actions), 5)
+ self.assertEqual(len(actions), 7)
class DummyContext:
pass
diff --git a/repoze/bfg/tests/test_traversal.py b/repoze/bfg/tests/test_traversal.py
index f21cf7d8d..48b968458 100644
--- a/repoze/bfg/tests/test_traversal.py
+++ b/repoze/bfg/tests/test_traversal.py
@@ -212,81 +212,6 @@ class ModelGraphTraverserTests(unittest.TestCase):
environ = self._getEnviron(PATH_INFO='/%s' % segment)
self.assertRaises(TypeError, policy, environ)
-class RoutesModelTraverserTests(unittest.TestCase):
- def _getTargetClass(self):
- from repoze.bfg.traversal import RoutesModelTraverser
- return RoutesModelTraverser
-
- def _makeOne(self, model):
- klass = self._getTargetClass()
- return klass(model)
-
- def test_class_conforms_to_ITraverser(self):
- from zope.interface.verify import verifyClass
- from repoze.bfg.interfaces import ITraverser
- verifyClass(ITraverser, self._getTargetClass())
-
- def test_instance_conforms_to_ITraverser(self):
- from zope.interface.verify import verifyObject
- from repoze.bfg.interfaces import ITraverser
- verifyObject(ITraverser, self._makeOne(None))
-
- def test_call_with_only_controller_bwcompat(self):
- model = DummyContext()
- model.controller = 'controller'
- traverser = self._makeOne(model)
- result = traverser({})
- self.assertEqual(result[0], model)
- self.assertEqual(result[1], 'controller')
- self.assertEqual(result[2], [])
-
- def test_call_with_only_view_name_bwcompat(self):
- model = DummyContext()
- model.view_name = 'view_name'
- traverser = self._makeOne(model)
- result = traverser({})
- self.assertEqual(result[0], model)
- self.assertEqual(result[1], 'view_name')
- self.assertEqual(result[2], [])
-
- def test_call_with_subpath_bwcompat(self):
- model = DummyContext()
- model.view_name = 'view_name'
- model.subpath = '/a/b/c'
- traverser = self._makeOne(model)
- result = traverser({})
- self.assertEqual(result[0], model)
- self.assertEqual(result[1], 'view_name')
- self.assertEqual(result[2], ['a', 'b', 'c'])
-
- def test_call_with_no_view_name_or_controller_bwcompat(self):
- model = DummyContext()
- traverser = self._makeOne(model)
- result = traverser({})
- self.assertEqual(result[0], model)
- self.assertEqual(result[1], '')
- self.assertEqual(result[2], [])
-
- def test_call_with_only_view_name(self):
- model = DummyContext()
- traverser = self._makeOne(model)
- routing_args = ((), {'view_name':'view_name'})
- environ = {'wsgiorg.routing_args': routing_args}
- result = traverser(environ)
- self.assertEqual(result[0], model)
- self.assertEqual(result[1], 'view_name')
- self.assertEqual(result[2], [])
-
- def test_call_with_view_name_and_subpath(self):
- model = DummyContext()
- traverser = self._makeOne(model)
- routing_args = ((), {'view_name':'view_name', 'subpath':'/a/b/c'})
- environ = {'wsgiorg.routing_args': routing_args}
- result = traverser(environ)
- self.assertEqual(result[0], model)
- self.assertEqual(result[1], 'view_name')
- self.assertEqual(result[2], ['a', 'b','c'])
-
class FindInterfaceTests(unittest.TestCase):
def _callFUT(self, context, iface):
from repoze.bfg.traversal import find_interface
@@ -439,6 +364,152 @@ class ModelPathTests(unittest.TestCase):
result = self._callFUT(other)
self.assertEqual(result, '/other')
+class TraversalContextURLTests(unittest.TestCase):
+ def _makeOne(self, context, url):
+ return self._getTargetClass()(context, url)
+
+ def _getTargetClass(self):
+ from repoze.bfg.traversal import TraversalContextURL
+ return TraversalContextURL
+
+ def _registerTraverserFactory(self, traverser):
+ import zope.component
+ gsm = zope.component.getGlobalSiteManager()
+ from repoze.bfg.interfaces import ITraverserFactory
+ from zope.interface import Interface
+ gsm.registerAdapter(traverser, (Interface,), ITraverserFactory)
+
+ def test_class_conforms_to_IContextURL(self):
+ from zope.interface.verify import verifyClass
+ from repoze.bfg.interfaces import IContextURL
+ verifyClass(IContextURL, self._getTargetClass())
+
+ def test_instance_conforms_to_IContextURL(self):
+ from zope.interface.verify import verifyObject
+ from repoze.bfg.interfaces import IContextURL
+ context = DummyContext()
+ request = DummyRequest()
+ verifyObject(IContextURL, self._makeOne(context, request))
+
+ def test_call_withlineage(self):
+ baz = DummyContext()
+ bar = DummyContext(baz)
+ foo = DummyContext(bar)
+ root = DummyContext(foo)
+ root.__parent__ = None
+ root.__name__ = None
+ foo.__parent__ = root
+ foo.__name__ = 'foo '
+ bar.__parent__ = foo
+ bar.__name__ = 'bar'
+ baz.__parent__ = bar
+ baz.__name__ = 'baz'
+ request = DummyRequest()
+ context_url = self._makeOne(baz, request)
+ result = context_url()
+ self.assertEqual(result, 'http://example.com:5432/foo%20/bar/baz/')
+
+ def test_call_nolineage(self):
+ context = DummyContext()
+ context.__name__ = ''
+ context.__parent__ = None
+ request = DummyRequest()
+ context_url = self._makeOne(context, request)
+ result = context_url()
+ self.assertEqual(result, 'http://example.com:5432/')
+
+ def test_call_unicode_mixed_with_bytes_in_model_names(self):
+ root = DummyContext()
+ root.__parent__ = None
+ root.__name__ = None
+ one = DummyContext()
+ one.__parent__ = root
+ one.__name__ = unicode('La Pe\xc3\xb1a', 'utf-8')
+ two = DummyContext()
+ two.__parent__ = one
+ two.__name__ = 'La Pe\xc3\xb1a'
+ request = DummyRequest()
+ context_url = self._makeOne(two, request)
+ result = context_url()
+ self.assertEqual(result,
+ 'http://example.com:5432/La%20Pe%C3%B1a/La%20Pe%C3%B1a/')
+
+ def test_call_with_vroot_path(self):
+ from repoze.bfg.interfaces import VH_ROOT_KEY
+ root = DummyContext()
+ root.__parent__ = None
+ root.__name__ = None
+ one = DummyContext()
+ one.__parent__ = root
+ one.__name__ = 'one'
+ two = DummyContext()
+ two.__parent__ = one
+ two.__name__ = 'two'
+ request = DummyRequest({VH_ROOT_KEY:'/one'})
+ context_url = self._makeOne(two, request)
+ result = context_url()
+ self.assertEqual(result, 'http://example.com:5432/two/')
+
+ request = DummyRequest({VH_ROOT_KEY:'/one/two'})
+ context_url = self._makeOne(two, request)
+ result = context_url()
+ self.assertEqual(result, 'http://example.com:5432/')
+
+ def test_virtual_root_no_vroot_path(self):
+ root = DummyContext()
+ root.__name__ = None
+ root.__parent__ = None
+ one = DummyContext()
+ one.__name__ = 'one'
+ one.__parent__ = root
+ request = DummyRequest()
+ context_url = self._makeOne(one, request)
+ self.assertEqual(context_url.virtual_root(), root)
+
+ def test_virtual_root_no_vroot_path_with_root_on_request(self):
+ context = DummyContext()
+ context.__parent__ = None
+ request = DummyRequest()
+ request.root = DummyContext()
+ context_url = self._makeOne(context, request)
+ self.assertEqual(context_url.virtual_root(), request.root)
+
+ def test_virtual_root_with_vroot_path(self):
+ from repoze.bfg.interfaces import VH_ROOT_KEY
+ context = DummyContext()
+ context.__parent__ = None
+ traversed_to = DummyContext()
+ environ = {VH_ROOT_KEY:'/one'}
+ request = DummyRequest(environ)
+ traverser = make_traverser(traversed_to, '', [])
+ self._registerTraverserFactory(traverser)
+ context_url = self._makeOne(context, request)
+ self.assertEqual(context_url.virtual_root(), traversed_to)
+ self.assertEqual(context.environ['PATH_INFO'], '/one')
+
+class TestVirtualRoot(unittest.TestCase):
+ def setUp(self):
+ cleanUp()
+
+ def tearDown(self):
+ cleanUp()
+
+ def _callFUT(self, model, request):
+ from repoze.bfg.traversal import virtual_root
+ return virtual_root(model, request)
+
+ def test_it(self):
+ from zope.component import getGlobalSiteManager
+ from repoze.bfg.interfaces import IContextURL
+ from zope.interface import Interface
+ gsm = getGlobalSiteManager()
+ gsm.registerAdapter(DummyContextURL, (Interface,Interface),
+ IContextURL)
+ context = DummyContext()
+ request = DummyRequest()
+ result = self._callFUT(context, request)
+ self.assertEqual(result, '123')
+
def make_traverser(*args):
class DummyTraverser(object):
def __init__(self, context):
@@ -460,4 +531,14 @@ class DummyContext(object):
class DummyRequest:
application_url = 'http://example.com:5432' # app_url never ends with slash
+ def __init__(self, environ=None):
+ if environ is None:
+ environ = {}
+ self.environ = environ
+
+class DummyContextURL:
+ def __init__(self, context, request):
+ pass
+ def virtual_root(self):
+ return '123'
diff --git a/repoze/bfg/tests/test_url.py b/repoze/bfg/tests/test_url.py
index a1aa84890..5f8cd34f4 100644
--- a/repoze/bfg/tests/test_url.py
+++ b/repoze/bfg/tests/test_url.py
@@ -1,150 +1,76 @@
import unittest
-class DefaultURLGeneratorTests(unittest.TestCase):
- def _makeOne(self):
- return self._getTargetClass()()
-
- def _getTargetClass(self):
- from repoze.bfg.url import DefaultURLGenerator
- return DefaultURLGenerator
-
- def test_class_conforms_to_IURLGenerator(self):
- from zope.interface.verify import verifyClass
- from repoze.bfg.interfaces import IURLGenerator
- verifyClass(IURLGenerator, self._getTargetClass())
-
- def test_instance_conforms_to_IURLGenerator(self):
- from zope.interface.verify import verifyObject
- from repoze.bfg.interfaces import IURLGenerator
- context = DummyContext()
- verifyObject(IURLGenerator, self._makeOne())
-
- def test_model_url_withlineage(self):
- baz = DummyContext()
- bar = DummyContext(baz)
- foo = DummyContext(bar)
- root = DummyContext(foo)
- root.__parent__ = None
- root.__name__ = None
- foo.__parent__ = root
- foo.__name__ = 'foo '
- bar.__parent__ = foo
- bar.__name__ = 'bar'
- baz.__parent__ = bar
- baz.__name__ = 'baz'
- request = DummyRequest()
- gen = self._makeOne()
- result = gen.model_url(baz, request)
- self.assertEqual(result, 'http://example.com:5432/foo%20/bar/baz/')
-
- def test_model_url_nolineage(self):
- context = DummyContext()
- context.__name__ = ''
- context.__parent__ = None
- request = DummyRequest()
- gen = self._makeOne()
- result = gen.model_url(context, request)
- self.assertEqual(result, 'http://example.com:5432/')
+from zope.testing.cleanup import cleanUp
class ModelURLTests(unittest.TestCase):
+ def setUp(self):
+ cleanUp()
+
+ def tearDown(self):
+ cleanUp()
+
def _callFUT(self, model, request, *elements, **kw):
+ self._registerContextURL()
from repoze.bfg.url import model_url
return model_url(model, request, *elements, **kw)
- def test_extra_args(self):
- baz = DummyContext()
- bar = DummyContext(baz)
- foo = DummyContext(bar)
- root = DummyContext(foo)
- root.__parent__ = None
- root.__name__ = None
- foo.__parent__ = root
- foo.__name__ = 'foo '
- bar.__parent__ = foo
- bar.__name__ = 'bar'
- baz.__parent__ = bar
- baz.__name__ = 'baz'
- request = DummyRequest()
- result = self._callFUT(baz, request, 'this/theotherthing', 'that')
- self.assertEqual(
- result,
- 'http://example.com:5432/foo%20/bar/baz/this/theotherthing/that')
-
- def test_root_default_app_url(self):
+ def _registerContextURL(self):
+ from repoze.bfg.interfaces import IContextURL
+ from zope.interface import Interface
+ from zope.component import getGlobalSiteManager
+ class DummyContextURL(object):
+ def __init__(self, context, request):
+ pass
+ def __call__(self):
+ return 'http://example.com/context/'
+ gsm = getGlobalSiteManager()
+ gsm.registerAdapter(DummyContextURL, (Interface, Interface),
+ IContextURL)
+
+ def test_root_default(self):
root = DummyContext()
- root.__parent__ = None
- root.__name__ = None
request = DummyRequest()
result = self._callFUT(root, request)
- self.assertEqual(result, 'http://example.com:5432/')
-
- def test_nonroot_default_app_url(self):
- root = DummyContext()
- root.__parent__ = None
- root.__name__ = None
- other = DummyContext()
- other.__parent__ = root
- other.__name__ = 'nonroot object'
- request = DummyRequest()
- result = self._callFUT(other, request)
- self.assertEqual(result, 'http://example.com:5432/nonroot%20object/')
+ self.assertEqual(result, 'http://example.com/context/')
- def test_unicode_mixed_with_bytes_in_model_names(self):
- root = DummyContext()
- root.__parent__ = None
- root.__name__ = None
- one = DummyContext()
- one.__parent__ = root
- one.__name__ = unicode('La Pe\xc3\xb1a', 'utf-8')
- two = DummyContext()
- two.__parent__ = one
- two.__name__ = 'La Pe\xc3\xb1a'
+ def test_extra_args(self):
+ context = DummyContext()
request = DummyRequest()
- result = self._callFUT(two, request)
- self.assertEqual(result,
- 'http://example.com:5432/La%20Pe%C3%B1a/La%20Pe%C3%B1a/')
+ result = self._callFUT(context, request, 'this/theotherthing', 'that')
+ self.assertEqual(
+ result,
+ 'http://example.com/context/this/theotherthing/that')
def test_unicode_in_element_names(self):
uc = unicode('La Pe\xc3\xb1a', 'utf-8')
- root = DummyContext()
- root.__parent__ = None
- root.__name__ = None
- one = DummyContext()
- one.__parent__ = root
- one.__name__ = uc
+ context = DummyContext()
request = DummyRequest()
- result = self._callFUT(one, request, uc)
+ result = self._callFUT(context, request, uc)
self.assertEqual(result,
- 'http://example.com:5432/La%20Pe%C3%B1a/La%20Pe%C3%B1a')
+ 'http://example.com/context/La%20Pe%C3%B1a')
def test_element_names_url_quoted(self):
- root = DummyContext()
- root.__parent__ = None
- root.__name__ = None
+ context = DummyContext()
request = DummyRequest()
- result = self._callFUT(root, request, 'a b c')
- self.assertEqual(result, 'http://example.com:5432/a%20b%20c')
+ result = self._callFUT(context, request, 'a b c')
+ self.assertEqual(result, 'http://example.com/context/a%20b%20c')
def test_with_query_dict(self):
- root = DummyContext()
- root.__parent__ = None
- root.__name__ = None
+ context = DummyContext()
request = DummyRequest()
uc = unicode('La Pe\xc3\xb1a', 'utf-8')
- result = self._callFUT(root, request, 'a', query={'a':uc})
+ result = self._callFUT(context, request, 'a', query={'a':uc})
self.assertEqual(result,
- 'http://example.com:5432/a?a=La+Pe%C3%B1a')
+ 'http://example.com/context/a?a=La+Pe%C3%B1a')
def test_with_query_seq(self):
- root = DummyContext()
- root.__parent__ = None
- root.__name__ = None
+ context = DummyContext()
request = DummyRequest()
uc = unicode('La Pe\xc3\xb1a', 'utf-8')
- result = self._callFUT(root, request, 'a', query=[('a', 'hi there'),
- ('b', uc)])
+ result = self._callFUT(context, request, 'a', query=[('a', 'hi there'),
+ ('b', uc)])
self.assertEqual(result,
- 'http://example.com:5432/a?a=hi+there&b=La+Pe%C3%B1a')
+ 'http://example.com/context/a?a=hi+there&b=La+Pe%C3%B1a')
class UrlEncodeTests(unittest.TestCase):
def _callFUT(self, query, doseq=False):
diff --git a/repoze/bfg/tests/test_urldispatch.py b/repoze/bfg/tests/test_urldispatch.py
index 71ac78698..0fc828161 100644
--- a/repoze/bfg/tests/test_urldispatch.py
+++ b/repoze/bfg/tests/test_urldispatch.py
@@ -221,6 +221,130 @@ def make_get_root(result):
return result
return dummy_get_root
+class RoutesModelTraverserTests(unittest.TestCase):
+ def _getTargetClass(self):
+ from repoze.bfg.urldispatch import RoutesModelTraverser
+ return RoutesModelTraverser
-
+ def _makeOne(self, model):
+ klass = self._getTargetClass()
+ return klass(model)
+
+ def test_class_conforms_to_ITraverser(self):
+ from zope.interface.verify import verifyClass
+ from repoze.bfg.interfaces import ITraverser
+ verifyClass(ITraverser, self._getTargetClass())
+
+ def test_instance_conforms_to_ITraverser(self):
+ from zope.interface.verify import verifyObject
+ from repoze.bfg.interfaces import ITraverser
+ verifyObject(ITraverser, self._makeOne(None))
+
+ def test_call_with_only_controller_bwcompat(self):
+ model = DummyContext()
+ model.controller = 'controller'
+ traverser = self._makeOne(model)
+ result = traverser({})
+ self.assertEqual(result[0], model)
+ self.assertEqual(result[1], 'controller')
+ self.assertEqual(result[2], [])
+
+ def test_call_with_only_view_name_bwcompat(self):
+ model = DummyContext()
+ model.view_name = 'view_name'
+ traverser = self._makeOne(model)
+ result = traverser({})
+ self.assertEqual(result[0], model)
+ self.assertEqual(result[1], 'view_name')
+ self.assertEqual(result[2], [])
+
+ def test_call_with_subpath_bwcompat(self):
+ model = DummyContext()
+ model.view_name = 'view_name'
+ model.subpath = '/a/b/c'
+ traverser = self._makeOne(model)
+ result = traverser({})
+ self.assertEqual(result[0], model)
+ self.assertEqual(result[1], 'view_name')
+ self.assertEqual(result[2], ['a', 'b', 'c'])
+
+ def test_call_with_no_view_name_or_controller_bwcompat(self):
+ model = DummyContext()
+ traverser = self._makeOne(model)
+ result = traverser({})
+ self.assertEqual(result[0], model)
+ self.assertEqual(result[1], '')
+ self.assertEqual(result[2], [])
+
+ def test_call_with_only_view_name(self):
+ model = DummyContext()
+ traverser = self._makeOne(model)
+ routing_args = ((), {'view_name':'view_name'})
+ environ = {'wsgiorg.routing_args': routing_args}
+ result = traverser(environ)
+ self.assertEqual(result[0], model)
+ self.assertEqual(result[1], 'view_name')
+ self.assertEqual(result[2], [])
+ def test_call_with_view_name_and_subpath(self):
+ model = DummyContext()
+ traverser = self._makeOne(model)
+ routing_args = ((), {'view_name':'view_name', 'subpath':'/a/b/c'})
+ environ = {'wsgiorg.routing_args': routing_args}
+ result = traverser(environ)
+ self.assertEqual(result[0], model)
+ self.assertEqual(result[1], 'view_name')
+ self.assertEqual(result[2], ['a', 'b','c'])
+
+class RoutesContextURLTests(unittest.TestCase):
+ def _getTargetClass(self):
+ from repoze.bfg.urldispatch import RoutesContextURL
+ return RoutesContextURL
+
+ def _makeOne(self, context, request):
+ return self._getTargetClass()(context, request)
+
+ def test_class_conforms_to_IContextURL(self):
+ from zope.interface.verify import verifyClass
+ from repoze.bfg.interfaces import IContextURL
+ verifyClass(IContextURL, self._getTargetClass())
+
+ def test_instance_conforms_to_IContextURL(self):
+ from zope.interface.verify import verifyObject
+ from repoze.bfg.interfaces import IContextURL
+ verifyObject(IContextURL, self._makeOne(None, None))
+
+ def test_get_virtual_root(self):
+ context_url = self._makeOne(1,2)
+ self.assertEqual(context_url.virtual_root(), 1)
+
+ def test_call(self):
+ from routes import Mapper
+ mapper = Mapper(controller_scan=None, directory=None,
+ explicit=True, always_scan=False)
+ args = {'a':'1', 'b':'2', 'c':'3'}
+ mapper.connect(':a/:b/:c')
+ mapper.create_regs([])
+ environ = {'SERVER_NAME':'example.com', 'wsgi.url_scheme':'http',
+ 'SERVER_PORT':'80', 'wsgiorg.routing_args':((), args)}
+ mapper.environ = environ
+ from routes import request_config
+ config = request_config()
+ config.environ = environ
+ config.mapper = mapper
+ config.mapper_dict = args
+ config.host = 'www.example.com'
+ config.protocol = 'https'
+ config.redirect = None
+ request = DummyRequest()
+ request.environ = environ
+ context_url = self._makeOne(None, request)
+ result = context_url()
+ self.assertEqual(result, '/1/2/3')
+
+class DummyContext(object):
+ """ """
+
+class DummyRequest(object):
+ """ """
+