summaryrefslogtreecommitdiff
path: root/tests/test_traversal.py
diff options
context:
space:
mode:
authorMichael Merickel <michael@merickel.org>2018-10-14 21:11:41 -0500
committerMichael Merickel <michael@merickel.org>2018-10-14 21:11:41 -0500
commit3670c2cdb732d378ba6d38e72e7cd875ff726aa9 (patch)
tree5213452a778c992d42602efe7d3b3655a349abd5 /tests/test_traversal.py
parent2b024920847481592b1a13d4006d2a9fa8881d72 (diff)
downloadpyramid-3670c2cdb732d378ba6d38e72e7cd875ff726aa9.tar.gz
pyramid-3670c2cdb732d378ba6d38e72e7cd875ff726aa9.tar.bz2
pyramid-3670c2cdb732d378ba6d38e72e7cd875ff726aa9.zip
move tests out of the package
Diffstat (limited to 'tests/test_traversal.py')
-rw-r--r--tests/test_traversal.py1221
1 files changed, 1221 insertions, 0 deletions
diff --git a/tests/test_traversal.py b/tests/test_traversal.py
new file mode 100644
index 000000000..437fe46df
--- /dev/null
+++ b/tests/test_traversal.py
@@ -0,0 +1,1221 @@
+# -*- coding: utf-8 -*-
+import unittest
+
+from pyramid.testing import cleanUp
+
+from pyramid.compat import (
+ text_,
+ native_,
+ text_type,
+ url_quote,
+ PY2,
+ )
+
+class TraversalPathTests(unittest.TestCase):
+ def _callFUT(self, path):
+ from pyramid.traversal import traversal_path
+ return traversal_path(path)
+
+ def test_utf8(self):
+ la = b'La Pe\xc3\xb1a'
+ encoded = url_quote(la)
+ decoded = text_(la, 'utf-8')
+ path = '/'.join([encoded, encoded])
+ result = self._callFUT(path)
+ self.assertEqual(result, (decoded, decoded))
+
+ def test_utf16(self):
+ from pyramid.exceptions import URLDecodeError
+ la = text_(b'La Pe\xc3\xb1a', 'utf-8').encode('utf-16')
+ encoded = url_quote(la)
+ path = '/'.join([encoded, encoded])
+ self.assertRaises(URLDecodeError, self._callFUT, path)
+
+ def test_unicode_highorder_chars(self):
+ path = text_('/%E6%B5%81%E8%A1%8C%E8%B6%8B%E5%8A%BF')
+ self.assertEqual(self._callFUT(path),
+ (text_('\u6d41\u884c\u8d8b\u52bf', 'unicode_escape'),))
+
+ def test_element_urllquoted(self):
+ self.assertEqual(self._callFUT('/foo/space%20thing/bar'),
+ (text_('foo'), text_('space thing'), text_('bar')))
+
+ def test_unicode_undecodeable_to_ascii(self):
+ path = text_(b'/La Pe\xc3\xb1a', 'utf-8')
+ self.assertRaises(UnicodeEncodeError, self._callFUT, path)
+
+class TraversalPathInfoTests(unittest.TestCase):
+ def _callFUT(self, path):
+ from pyramid.traversal import traversal_path_info
+ return traversal_path_info(path)
+
+ def test_path_startswith_endswith(self):
+ self.assertEqual(self._callFUT('/foo/'), (text_('foo'),))
+
+ def test_empty_elements(self):
+ self.assertEqual(self._callFUT('foo///'), (text_('foo'),))
+
+ def test_onedot(self):
+ self.assertEqual(self._callFUT('foo/./bar'),
+ (text_('foo'), text_('bar')))
+
+ def test_twodots(self):
+ self.assertEqual(self._callFUT('foo/../bar'), (text_('bar'),))
+
+ def test_twodots_at_start(self):
+ self.assertEqual(self._callFUT('../../bar'), (text_('bar'),))
+
+ def test_segments_are_unicode(self):
+ result = self._callFUT('/foo/bar')
+ self.assertEqual(type(result[0]), text_type)
+ self.assertEqual(type(result[1]), text_type)
+
+ def test_same_value_returned_if_cached(self):
+ result1 = self._callFUT('/foo/bar')
+ result2 = self._callFUT('/foo/bar')
+ self.assertEqual(result1, (text_('foo'), text_('bar')))
+ self.assertEqual(result2, (text_('foo'), text_('bar')))
+
+ def test_unicode_simple(self):
+ path = text_('/abc')
+ self.assertEqual(self._callFUT(path), (text_('abc'),))
+
+ def test_highorder(self):
+ la = b'La Pe\xc3\xb1a'
+ latin1 = native_(la)
+ result = self._callFUT(latin1)
+ self.assertEqual(result, (text_(la, 'utf-8'),))
+
+ def test_highorder_undecodeable(self):
+ from pyramid.exceptions import URLDecodeError
+ la = text_(b'La Pe\xc3\xb1a', 'utf-8')
+ notlatin1 = native_(la)
+ self.assertRaises(URLDecodeError, self._callFUT, notlatin1)
+
+class ResourceTreeTraverserTests(unittest.TestCase):
+ def setUp(self):
+ cleanUp()
+
+ def tearDown(self):
+ cleanUp()
+
+ def _getTargetClass(self):
+ from pyramid.traversal import ResourceTreeTraverser
+ return ResourceTreeTraverser
+
+ def _makeOne(self, *arg, **kw):
+ klass = self._getTargetClass()
+ return klass(*arg, **kw)
+
+ def _getEnviron(self, **kw):
+ environ = {}
+ environ.update(kw)
+ return environ
+
+ def test_class_conforms_to_ITraverser(self):
+ from zope.interface.verify import verifyClass
+ from pyramid.interfaces import ITraverser
+ verifyClass(ITraverser, self._getTargetClass())
+
+ def test_instance_conforms_to_ITraverser(self):
+ from zope.interface.verify import verifyObject
+ from pyramid.interfaces import ITraverser
+ context = DummyContext()
+ verifyObject(ITraverser, self._makeOne(context))
+
+ def test_call_with_empty_pathinfo(self):
+ policy = self._makeOne(None)
+ environ = self._getEnviron()
+ request = DummyRequest(environ, path_info='')
+ result = policy(request)
+ self.assertEqual(result['context'], None)
+ self.assertEqual(result['view_name'], '')
+ self.assertEqual(result['subpath'], ())
+ self.assertEqual(result['traversed'], ())
+ self.assertEqual(result['root'], policy.root)
+ self.assertEqual(result['virtual_root'], policy.root)
+ self.assertEqual(result['virtual_root_path'], ())
+
+ def test_call_with_pathinfo_KeyError(self):
+ policy = self._makeOne(None)
+ environ = self._getEnviron()
+ request = DummyRequest(environ, toraise=KeyError)
+ result = policy(request)
+ self.assertEqual(result['context'], None)
+ self.assertEqual(result['view_name'], '')
+ self.assertEqual(result['subpath'], ())
+ self.assertEqual(result['traversed'], ())
+ self.assertEqual(result['root'], policy.root)
+ self.assertEqual(result['virtual_root'], policy.root)
+ self.assertEqual(result['virtual_root_path'], ())
+
+ def test_call_with_pathinfo_highorder(self):
+ path = text_(b'/Qu\xc3\xa9bec', 'utf-8')
+ foo = DummyContext(None, path)
+ root = DummyContext(foo, 'root')
+ policy = self._makeOne(root)
+ environ = self._getEnviron()
+ request = DummyRequest(environ, path_info=path)
+ result = policy(request)
+ self.assertEqual(result['context'], foo)
+ self.assertEqual(result['view_name'], '')
+ self.assertEqual(result['subpath'], ())
+ self.assertEqual(result['traversed'], (path[1:],))
+ self.assertEqual(result['root'], policy.root)
+ self.assertEqual(result['virtual_root'], policy.root)
+ self.assertEqual(result['virtual_root_path'], ())
+
+ def test_call_pathel_with_no_getitem(self):
+ policy = self._makeOne(None)
+ environ = self._getEnviron()
+ request = DummyRequest(environ, path_info=text_('/foo/bar'))
+ result = policy(request)
+ self.assertEqual(result['context'], None)
+ self.assertEqual(result['view_name'], 'foo')
+ self.assertEqual(result['subpath'], ('bar',))
+ self.assertEqual(result['traversed'], ())
+ self.assertEqual(result['root'], policy.root)
+ self.assertEqual(result['virtual_root'], policy.root)
+ self.assertEqual(result['virtual_root_path'], ())
+
+ def test_call_withconn_getitem_emptypath_nosubpath(self):
+ root = DummyContext()
+ policy = self._makeOne(root)
+ environ = self._getEnviron()
+ request = DummyRequest(environ, path_info=text_(''))
+ result = policy(request)
+ self.assertEqual(result['context'], root)
+ self.assertEqual(result['view_name'], '')
+ self.assertEqual(result['subpath'], ())
+ self.assertEqual(result['traversed'], ())
+ self.assertEqual(result['root'], root)
+ self.assertEqual(result['virtual_root'], root)
+ self.assertEqual(result['virtual_root_path'], ())
+
+ def test_call_withconn_getitem_withpath_nosubpath(self):
+ foo = DummyContext()
+ root = DummyContext(foo)
+ policy = self._makeOne(root)
+ environ = self._getEnviron()
+ request = DummyRequest(environ, path_info=text_('/foo/bar'))
+ result = policy(request)
+ self.assertEqual(result['context'], foo)
+ self.assertEqual(result['view_name'], 'bar')
+ self.assertEqual(result['subpath'], ())
+ self.assertEqual(result['traversed'], (text_('foo'),))
+ self.assertEqual(result['root'], root)
+ self.assertEqual(result['virtual_root'], root)
+ self.assertEqual(result['virtual_root_path'], ())
+
+ def test_call_withconn_getitem_withpath_withsubpath(self):
+ foo = DummyContext()
+ root = DummyContext(foo)
+ policy = self._makeOne(root)
+ environ = self._getEnviron()
+ request = DummyRequest(environ, path_info=text_('/foo/bar/baz/buz'))
+ result = policy(request)
+ self.assertEqual(result['context'], foo)
+ self.assertEqual(result['view_name'], 'bar')
+ self.assertEqual(result['subpath'], ('baz', 'buz'))
+ self.assertEqual(result['traversed'], (text_('foo'),))
+ self.assertEqual(result['root'], root)
+ self.assertEqual(result['virtual_root'], root)
+ self.assertEqual(result['virtual_root_path'], ())
+
+ def test_call_with_explicit_viewname(self):
+ foo = DummyContext()
+ root = DummyContext(foo)
+ policy = self._makeOne(root)
+ environ = self._getEnviron()
+ request = DummyRequest(environ, path_info=text_('/@@foo'))
+ result = policy(request)
+ self.assertEqual(result['context'], root)
+ self.assertEqual(result['view_name'], 'foo')
+ self.assertEqual(result['subpath'], ())
+ self.assertEqual(result['traversed'], ())
+ self.assertEqual(result['root'], root)
+ self.assertEqual(result['virtual_root'], root)
+ self.assertEqual(result['virtual_root_path'], ())
+
+ def test_call_with_vh_root(self):
+ environ = self._getEnviron(HTTP_X_VHM_ROOT='/foo/bar')
+ baz = DummyContext(None, 'baz')
+ bar = DummyContext(baz, 'bar')
+ foo = DummyContext(bar, 'foo')
+ root = DummyContext(foo, 'root')
+ policy = self._makeOne(root)
+ request = DummyRequest(environ, path_info=text_('/baz'))
+ result = policy(request)
+ self.assertEqual(result['context'], baz)
+ self.assertEqual(result['view_name'], '')
+ self.assertEqual(result['subpath'], ())
+ self.assertEqual(result['traversed'],
+ (text_('foo'), text_('bar'), text_('baz')))
+ self.assertEqual(result['root'], root)
+ self.assertEqual(result['virtual_root'], bar)
+ self.assertEqual(result['virtual_root_path'],
+ (text_('foo'), text_('bar')))
+
+ def test_call_with_vh_root2(self):
+ environ = self._getEnviron(HTTP_X_VHM_ROOT='/foo')
+ baz = DummyContext(None, 'baz')
+ bar = DummyContext(baz, 'bar')
+ foo = DummyContext(bar, 'foo')
+ root = DummyContext(foo, 'root')
+ policy = self._makeOne(root)
+ request = DummyRequest(environ, path_info=text_('/bar/baz'))
+ result = policy(request)
+ self.assertEqual(result['context'], baz)
+ self.assertEqual(result['view_name'], '')
+ self.assertEqual(result['subpath'], ())
+ self.assertEqual(result['traversed'],
+ (text_('foo'), text_('bar'), text_('baz')))
+ self.assertEqual(result['root'], root)
+ self.assertEqual(result['virtual_root'], foo)
+ self.assertEqual(result['virtual_root_path'], (text_('foo'),))
+
+ def test_call_with_vh_root3(self):
+ environ = self._getEnviron(HTTP_X_VHM_ROOT='/')
+ baz = DummyContext()
+ bar = DummyContext(baz)
+ foo = DummyContext(bar)
+ root = DummyContext(foo)
+ policy = self._makeOne(root)
+ request = DummyRequest(environ, path_info=text_('/foo/bar/baz'))
+ result = policy(request)
+ self.assertEqual(result['context'], baz)
+ self.assertEqual(result['view_name'], '')
+ self.assertEqual(result['subpath'], ())
+ self.assertEqual(result['traversed'],
+ (text_('foo'), text_('bar'), text_('baz')))
+ self.assertEqual(result['root'], root)
+ self.assertEqual(result['virtual_root'], root)
+ self.assertEqual(result['virtual_root_path'], ())
+
+ def test_call_with_vh_root4(self):
+ environ = self._getEnviron(HTTP_X_VHM_ROOT='/foo/bar/baz')
+ baz = DummyContext(None, 'baz')
+ bar = DummyContext(baz, 'bar')
+ foo = DummyContext(bar, 'foo')
+ root = DummyContext(foo, 'root')
+ policy = self._makeOne(root)
+ request = DummyRequest(environ, path_info=text_('/'))
+ result = policy(request)
+ self.assertEqual(result['context'], baz)
+ self.assertEqual(result['view_name'], '')
+ self.assertEqual(result['subpath'], ())
+ self.assertEqual(result['traversed'],
+ (text_('foo'), text_('bar'), text_('baz')))
+ self.assertEqual(result['root'], root)
+ self.assertEqual(result['virtual_root'], baz)
+ self.assertEqual(result['virtual_root_path'],
+ (text_('foo'), text_('bar'), text_('baz')))
+
+ def test_call_with_vh_root_path_root(self):
+ policy = self._makeOne(None)
+ environ = self._getEnviron(HTTP_X_VHM_ROOT='/')
+ request = DummyRequest(environ, path_info=text_('/'))
+ result = policy(request)
+ self.assertEqual(result['context'], None)
+ self.assertEqual(result['view_name'], '')
+ self.assertEqual(result['subpath'], ())
+ self.assertEqual(result['traversed'], ())
+ self.assertEqual(result['root'], policy.root)
+ self.assertEqual(result['virtual_root'], policy.root)
+ self.assertEqual(result['virtual_root_path'], ())
+
+ def test_call_with_vh_root_highorder(self):
+ path = text_(b'Qu\xc3\xa9bec', 'utf-8')
+ bar = DummyContext(None, 'bar')
+ foo = DummyContext(bar, path)
+ root = DummyContext(foo, 'root')
+ policy = self._makeOne(root)
+ if PY2:
+ vhm_root = b'/Qu\xc3\xa9bec'
+ else:
+ vhm_root = b'/Qu\xc3\xa9bec'.decode('latin-1')
+ environ = self._getEnviron(HTTP_X_VHM_ROOT=vhm_root)
+ request = DummyRequest(environ, path_info=text_('/bar'))
+ result = policy(request)
+ self.assertEqual(result['context'], bar)
+ self.assertEqual(result['view_name'], '')
+ self.assertEqual(result['subpath'], ())
+ self.assertEqual(
+ result['traversed'],
+ (path, text_('bar'))
+ )
+ self.assertEqual(result['root'], policy.root)
+ self.assertEqual(result['virtual_root'], foo)
+ self.assertEqual(
+ result['virtual_root_path'],
+ (path,)
+ )
+
+ def test_path_info_raises_unicodedecodeerror(self):
+ from pyramid.exceptions import URLDecodeError
+ foo = DummyContext()
+ root = DummyContext(foo)
+ policy = self._makeOne(root)
+ environ = self._getEnviron()
+ toraise = UnicodeDecodeError('ascii', b'a', 2, 3, '5')
+ request = DummyRequest(environ, toraise=toraise)
+ request.matchdict = None
+ self.assertRaises(URLDecodeError, policy, request)
+
+ def test_withroute_nothingfancy(self):
+ resource = DummyContext()
+ traverser = self._makeOne(resource)
+ request = DummyRequest({})
+ request.matchdict = {}
+ result = traverser(request)
+ self.assertEqual(result['context'], resource)
+ self.assertEqual(result['view_name'], '')
+ self.assertEqual(result['subpath'], ())
+ self.assertEqual(result['traversed'], ())
+ self.assertEqual(result['root'], resource)
+ self.assertEqual(result['virtual_root'], resource)
+ self.assertEqual(result['virtual_root_path'], ())
+
+ def test_withroute_with_subpath_string(self):
+ resource = DummyContext()
+ traverser = self._makeOne(resource)
+ matchdict = {'subpath':'/a/b/c'}
+ request = DummyRequest({})
+ request.matchdict = matchdict
+ result = traverser(request)
+ self.assertEqual(result['context'], resource)
+ self.assertEqual(result['view_name'], '')
+ self.assertEqual(result['subpath'], ('a', 'b','c'))
+ self.assertEqual(result['traversed'], ())
+ self.assertEqual(result['root'], resource)
+ self.assertEqual(result['virtual_root'], resource)
+ self.assertEqual(result['virtual_root_path'], ())
+
+ def test_withroute_with_subpath_tuple(self):
+ resource = DummyContext()
+ traverser = self._makeOne(resource)
+ matchdict = {'subpath':('a', 'b', 'c')}
+ request = DummyRequest({})
+ request.matchdict = matchdict
+ result = traverser(request)
+ self.assertEqual(result['context'], resource)
+ self.assertEqual(result['view_name'], '')
+ self.assertEqual(result['subpath'], ('a', 'b','c'))
+ self.assertEqual(result['traversed'], ())
+ self.assertEqual(result['root'], resource)
+ self.assertEqual(result['virtual_root'], resource)
+ self.assertEqual(result['virtual_root_path'], ())
+
+ def test_withroute_and_traverse_string(self):
+ resource = DummyContext()
+ traverser = self._makeOne(resource)
+ matchdict = {'traverse':text_('foo/bar')}
+ request = DummyRequest({})
+ request.matchdict = matchdict
+ result = traverser(request)
+ self.assertEqual(result['context'], resource)
+ self.assertEqual(result['view_name'], 'foo')
+ self.assertEqual(result['subpath'], ('bar',))
+ self.assertEqual(result['traversed'], ())
+ self.assertEqual(result['root'], resource)
+ self.assertEqual(result['virtual_root'], resource)
+ self.assertEqual(result['virtual_root_path'], ())
+
+ def test_withroute_and_traverse_tuple(self):
+ resource = DummyContext()
+ traverser = self._makeOne(resource)
+ matchdict = {'traverse':('foo', 'bar')}
+ request = DummyRequest({})
+ request.matchdict = matchdict
+ result = traverser(request)
+ self.assertEqual(result['context'], resource)
+ self.assertEqual(result['view_name'], 'foo')
+ self.assertEqual(result['subpath'], ('bar',))
+ self.assertEqual(result['traversed'], ())
+ self.assertEqual(result['root'], resource)
+ self.assertEqual(result['virtual_root'], resource)
+ self.assertEqual(result['virtual_root_path'], ())
+
+ def test_withroute_and_traverse_empty(self):
+ resource = DummyContext()
+ traverser = self._makeOne(resource)
+ matchdict = {'traverse':''}
+ request = DummyRequest({})
+ request.matchdict = matchdict
+ result = traverser(request)
+ self.assertEqual(result['context'], resource)
+ self.assertEqual(result['view_name'], '')
+ self.assertEqual(result['subpath'], ())
+ self.assertEqual(result['traversed'], ())
+ self.assertEqual(result['root'], resource)
+ self.assertEqual(result['virtual_root'], resource)
+ self.assertEqual(result['virtual_root_path'], ())
+
+ def test_withroute_and_traverse_and_vroot(self):
+ abc = DummyContext()
+ resource = DummyContext(next=abc)
+ environ = self._getEnviron(HTTP_X_VHM_ROOT='/abc')
+ request = DummyRequest(environ)
+ traverser = self._makeOne(resource)
+ matchdict = {'traverse':text_('/foo/bar')}
+ request.matchdict = matchdict
+ result = traverser(request)
+ self.assertEqual(result['context'], abc)
+ self.assertEqual(result['view_name'], 'foo')
+ self.assertEqual(result['subpath'], ('bar',))
+ self.assertEqual(result['traversed'], ('abc', 'foo'))
+ self.assertEqual(result['root'], resource)
+ self.assertEqual(result['virtual_root'], abc)
+ self.assertEqual(result['virtual_root_path'], ('abc',))
+
+class FindInterfaceTests(unittest.TestCase):
+ def _callFUT(self, context, iface):
+ from pyramid.traversal import find_interface
+ return find_interface(context, iface)
+
+ def test_it_interface(self):
+ baz = DummyContext()
+ bar = DummyContext(baz)
+ foo = DummyContext(bar)
+ root = DummyContext(foo)
+ root.__parent__ = None
+ root.__name__ = 'root'
+ foo.__parent__ = root
+ foo.__name__ = 'foo'
+ bar.__parent__ = foo
+ bar.__name__ = 'bar'
+ baz.__parent__ = bar
+ baz.__name__ = 'baz'
+ from zope.interface import directlyProvides
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ directlyProvides(root, IFoo)
+ result = self._callFUT(baz, IFoo)
+ self.assertEqual(result.__name__, 'root')
+
+ def test_it_class(self):
+ class DummyRoot(object):
+ def __init__(self, child):
+ self.child = child
+ baz = DummyContext()
+ bar = DummyContext(baz)
+ foo = DummyContext(bar)
+ root = DummyRoot(foo)
+ root.__parent__ = None
+ root.__name__ = 'root'
+ foo.__parent__ = root
+ foo.__name__ = 'foo'
+ bar.__parent__ = foo
+ bar.__name__ = 'bar'
+ baz.__parent__ = bar
+ baz.__name__ = 'baz'
+ result = self._callFUT(baz, DummyRoot)
+ self.assertEqual(result.__name__, 'root')
+
+class FindRootTests(unittest.TestCase):
+ def _callFUT(self, context):
+ from pyramid.traversal import find_root
+ return find_root(context)
+
+ def test_it(self):
+ dummy = DummyContext()
+ baz = DummyContext()
+ baz.__parent__ = dummy
+ baz.__name__ = 'baz'
+ dummy.__parent__ = None
+ dummy.__name__ = None
+ result = self._callFUT(baz)
+ self.assertEqual(result, dummy)
+
+class FindResourceTests(unittest.TestCase):
+ def _callFUT(self, context, name):
+ from pyramid.traversal import find_resource
+ return find_resource(context, name)
+
+ def _registerTraverser(self, traverser):
+ from pyramid.threadlocal import get_current_registry
+ reg = get_current_registry()
+ from pyramid.interfaces import ITraverser
+ from zope.interface import Interface
+ reg.registerAdapter(traverser, (Interface,), ITraverser)
+
+ def test_list(self):
+ resource = DummyContext()
+ traverser = make_traverser({'context':resource, 'view_name':''})
+ self._registerTraverser(traverser)
+ result = self._callFUT(resource, [''])
+ self.assertEqual(result, resource)
+ self.assertEqual(resource.request.environ['PATH_INFO'], '/')
+
+ def test_generator(self):
+ resource = DummyContext()
+ traverser = make_traverser({'context':resource, 'view_name':''})
+ self._registerTraverser(traverser)
+ def foo():
+ yield ''
+ result = self._callFUT(resource, foo())
+ self.assertEqual(result, resource)
+ self.assertEqual(resource.request.environ['PATH_INFO'], '/')
+
+ def test_self_string_found(self):
+ resource = DummyContext()
+ traverser = make_traverser({'context':resource, 'view_name':''})
+ self._registerTraverser(traverser)
+ result = self._callFUT(resource, '')
+ self.assertEqual(result, resource)
+ self.assertEqual(resource.request.environ['PATH_INFO'], '')
+
+ def test_self_tuple_found(self):
+ resource = DummyContext()
+ traverser = make_traverser({'context':resource, 'view_name':''})
+ self._registerTraverser(traverser)
+ result = self._callFUT(resource, ())
+ self.assertEqual(result, resource)
+ self.assertEqual(resource.request.environ['PATH_INFO'], '')
+
+ def test_relative_string_found(self):
+ resource = DummyContext()
+ baz = DummyContext()
+ traverser = make_traverser({'context':baz, 'view_name':''})
+ self._registerTraverser(traverser)
+ result = self._callFUT(resource, 'baz')
+ self.assertEqual(result, baz)
+ self.assertEqual(resource.request.environ['PATH_INFO'], 'baz')
+
+ def test_relative_tuple_found(self):
+ resource = DummyContext()
+ baz = DummyContext()
+ traverser = make_traverser({'context':baz, 'view_name':''})
+ self._registerTraverser(traverser)
+ result = self._callFUT(resource, ('baz',))
+ self.assertEqual(result, baz)
+ self.assertEqual(resource.request.environ['PATH_INFO'], 'baz')
+
+ def test_relative_string_notfound(self):
+ resource = DummyContext()
+ baz = DummyContext()
+ traverser = make_traverser({'context':baz, 'view_name':'bar'})
+ self._registerTraverser(traverser)
+ self.assertRaises(KeyError, self._callFUT, resource, 'baz')
+ self.assertEqual(resource.request.environ['PATH_INFO'], 'baz')
+
+ def test_relative_tuple_notfound(self):
+ resource = DummyContext()
+ baz = DummyContext()
+ traverser = make_traverser({'context':baz, 'view_name':'bar'})
+ self._registerTraverser(traverser)
+ self.assertRaises(KeyError, self._callFUT, resource, ('baz',))
+ self.assertEqual(resource.request.environ['PATH_INFO'], 'baz')
+
+ def test_absolute_string_found(self):
+ root = DummyContext()
+ resource = DummyContext()
+ resource.__parent__ = root
+ resource.__name__ = 'baz'
+ traverser = make_traverser({'context':root, 'view_name':''})
+ self._registerTraverser(traverser)
+ result = self._callFUT(resource, '/')
+ self.assertEqual(result, root)
+ self.assertEqual(root.wascontext, True)
+ self.assertEqual(root.request.environ['PATH_INFO'], '/')
+
+ def test_absolute_tuple_found(self):
+ root = DummyContext()
+ resource = DummyContext()
+ resource.__parent__ = root
+ resource.__name__ = 'baz'
+ traverser = make_traverser({'context':root, 'view_name':''})
+ self._registerTraverser(traverser)
+ result = self._callFUT(resource, ('',))
+ self.assertEqual(result, root)
+ self.assertEqual(root.wascontext, True)
+ self.assertEqual(root.request.environ['PATH_INFO'], '/')
+
+ def test_absolute_string_notfound(self):
+ root = DummyContext()
+ resource = DummyContext()
+ resource.__parent__ = root
+ resource.__name__ = 'baz'
+ traverser = make_traverser({'context':root, 'view_name':'fuz'})
+ self._registerTraverser(traverser)
+ self.assertRaises(KeyError, self._callFUT, resource, '/')
+ self.assertEqual(root.wascontext, True)
+ self.assertEqual(root.request.environ['PATH_INFO'], '/')
+
+ def test_absolute_tuple_notfound(self):
+ root = DummyContext()
+ resource = DummyContext()
+ resource.__parent__ = root
+ resource.__name__ = 'baz'
+ traverser = make_traverser({'context':root, 'view_name':'fuz'})
+ self._registerTraverser(traverser)
+ self.assertRaises(KeyError, self._callFUT, resource, ('',))
+ self.assertEqual(root.wascontext, True)
+ self.assertEqual(root.request.environ['PATH_INFO'], '/')
+
+ def test_absolute_unicode_found(self):
+ # test for bug wiggy found in wild, traceback stack:
+ # root = u'/%E6%B5%81%E8%A1%8C%E8%B6%8B%E5%8A%BF'
+ # wiggy's code: section=find_resource(page, root)
+ # find_resource L76: D = traverse(resource, path)
+ # traverse L291: return traverser(request)
+ # __call__ line 568: vpath_tuple = traversal_path(vpath)
+ # lru_cached line 91: f(*arg)
+ # traversal_path line 443: path.encode('ascii')
+ # UnicodeEncodeError: 'ascii' codec can't encode characters in
+ # position 1-12: ordinal not in range(128)
+ #
+ # solution: encode string to ascii in pyramid.traversal.traverse
+ # before passing it along to webob as path_info
+ from pyramid.traversal import ResourceTreeTraverser
+ unprintable = DummyContext()
+ root = DummyContext(unprintable)
+ unprintable.__parent__ = root
+ unprintable.__name__ = text_(
+ b'/\xe6\xb5\x81\xe8\xa1\x8c\xe8\xb6\x8b\xe5\x8a\xbf', 'utf-8')
+ root.__parent__ = None
+ root.__name__ = None
+ traverser = ResourceTreeTraverser
+ self._registerTraverser(traverser)
+ result = self._callFUT(
+ root,
+ text_(b'/%E6%B5%81%E8%A1%8C%E8%B6%8B%E5%8A%BF')
+ )
+ self.assertEqual(result, unprintable)
+
+class ResourcePathTests(unittest.TestCase):
+ def _callFUT(self, resource, *elements):
+ from pyramid.traversal import resource_path
+ return resource_path(resource, *elements)
+
+ def test_it(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'
+ result = self._callFUT(baz, 'this/theotherthing', 'that')
+ self.assertEqual(result, '/foo%20/bar/baz/this%2Ftheotherthing/that')
+
+ def test_root_default(self):
+ root = DummyContext()
+ root.__parent__ = None
+ root.__name__ = None
+ result = self._callFUT(root)
+ self.assertEqual(result, '/')
+
+ def test_root_default_emptystring(self):
+ root = DummyContext()
+ root.__parent__ = None
+ root.__name__ = ''
+ result = self._callFUT(root)
+ self.assertEqual(result, '/')
+
+ def test_root_object_nonnull_name_direct(self):
+ root = DummyContext()
+ root.__parent__ = None
+ root.__name__ = 'flubadub'
+ result = self._callFUT(root)
+ self.assertEqual(result, 'flubadub') # insane case
+
+ def test_root_object_nonnull_name_indirect(self):
+ root = DummyContext()
+ root.__parent__ = None
+ root.__name__ = 'flubadub'
+ other = DummyContext()
+ other.__parent__ = root
+ other.__name__ = 'barker'
+ result = self._callFUT(other)
+ self.assertEqual(result, 'flubadub/barker') # insane case
+
+ def test_nonroot_default(self):
+ root = DummyContext()
+ root.__parent__ = None
+ root.__name__ = None
+ other = DummyContext()
+ other.__parent__ = root
+ other.__name__ = 'other'
+ result = self._callFUT(other)
+ self.assertEqual(result, '/other')
+
+ def test_path_with_None_itermediate_names(self):
+ root = DummyContext()
+ root.__parent__ = None
+ root.__name__ = None
+ other = DummyContext()
+ other.__parent__ = root
+ other.__name__ = None
+ other2 = DummyContext()
+ other2.__parent__ = other
+ other2.__name__ = 'other2'
+ result = self._callFUT(other2)
+ self.assertEqual(result, '//other2')
+
+class ResourcePathTupleTests(unittest.TestCase):
+ def _callFUT(self, resource, *elements):
+ from pyramid.traversal import resource_path_tuple
+ return resource_path_tuple(resource, *elements)
+
+ def test_it(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'
+ result = self._callFUT(baz, 'this/theotherthing', 'that')
+ self.assertEqual(result, ('','foo ', 'bar', 'baz', 'this/theotherthing',
+ 'that'))
+
+ def test_root_default(self):
+ root = DummyContext()
+ root.__parent__ = None
+ root.__name__ = None
+ result = self._callFUT(root)
+ self.assertEqual(result, ('',))
+
+ def test_root_default_emptystring_name(self):
+ root = DummyContext()
+ root.__parent__ = None
+ root.__name__ = ''
+ other = DummyContext()
+ other.__parent__ = root
+ other.__name__ = 'other'
+ result = self._callFUT(other)
+ self.assertEqual(result, ('', 'other',))
+
+ def test_nonroot_default(self):
+ root = DummyContext()
+ root.__parent__ = None
+ root.__name__ = None
+ other = DummyContext()
+ other.__parent__ = root
+ other.__name__ = 'other'
+ result = self._callFUT(other)
+ self.assertEqual(result, ('', 'other'))
+
+ def test_path_with_None_itermediate_names(self):
+ root = DummyContext()
+ root.__parent__ = None
+ root.__name__ = None
+ other = DummyContext()
+ other.__parent__ = root
+ other.__name__ = None
+ other2 = DummyContext()
+ other2.__parent__ = other
+ other2.__name__ = 'other2'
+ result = self._callFUT(other2)
+ self.assertEqual(result, ('', '', 'other2'))
+
+class QuotePathSegmentTests(unittest.TestCase):
+ def _callFUT(self, s):
+ from pyramid.traversal import quote_path_segment
+ return quote_path_segment(s)
+
+ def test_unicode(self):
+ la = text_(b'/La Pe\xc3\xb1a', 'utf-8')
+ result = self._callFUT(la)
+ self.assertEqual(result, '%2FLa%20Pe%C3%B1a')
+
+ def test_string(self):
+ s = '/ hello!'
+ result = self._callFUT(s)
+ self.assertEqual(result, '%2F%20hello!')
+
+ def test_int(self):
+ s = 12345
+ result = self._callFUT(s)
+ self.assertEqual(result, '12345')
+
+ def test_long(self):
+ from pyramid.compat import long
+ import sys
+ s = long(sys.maxsize + 1)
+ result = self._callFUT(s)
+ expected = str(s)
+ self.assertEqual(result, expected)
+
+ def test_other(self):
+ class Foo(object):
+ def __str__(self):
+ return 'abc'
+ s = Foo()
+ result = self._callFUT(s)
+ self.assertEqual(result, 'abc')
+
+class ResourceURLTests(unittest.TestCase):
+ def _makeOne(self, context, url):
+ return self._getTargetClass()(context, url)
+
+ def _getTargetClass(self):
+ from pyramid.traversal import ResourceURL
+ return ResourceURL
+
+ def test_instance_conforms_to_IResourceURL(self):
+ from pyramid.interfaces import IResourceURL
+ from zope.interface.verify import verifyObject
+ context = DummyContext()
+ request = DummyRequest()
+ verifyObject(IResourceURL, self._makeOne(context, request))
+
+ def test_IResourceURL_attributes_with_vroot(self):
+ from pyramid.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'
+ environ = {VH_ROOT_KEY:'/one'}
+ request = DummyRequest(environ)
+ context_url = self._makeOne(two, request)
+ self.assertEqual(context_url.physical_path, '/one/two/')
+ self.assertEqual(context_url.virtual_path, '/two/')
+ self.assertEqual(context_url.physical_path_tuple, ('', 'one', 'two',''))
+ self.assertEqual(context_url.virtual_path_tuple, ('', 'two', ''))
+
+ def test_IResourceURL_attributes_vroot_ends_with_slash(self):
+ from pyramid.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'
+ environ = {VH_ROOT_KEY:'/one/'}
+ request = DummyRequest(environ)
+ context_url = self._makeOne(two, request)
+ self.assertEqual(context_url.physical_path, '/one/two/')
+ self.assertEqual(context_url.virtual_path, '/two/')
+ self.assertEqual(context_url.physical_path_tuple, ('', 'one', 'two',''))
+ self.assertEqual(context_url.virtual_path_tuple, ('', 'two', ''))
+
+ def test_IResourceURL_attributes_no_vroot(self):
+ root = DummyContext()
+ root.__parent__ = None
+ root.__name__ = None
+ one = DummyContext()
+ one.__parent__ = root
+ one.__name__ = 'one'
+ two = DummyContext()
+ two.__parent__ = one
+ two.__name__ = 'two'
+ environ = {}
+ request = DummyRequest(environ)
+ context_url = self._makeOne(two, request)
+ self.assertEqual(context_url.physical_path, '/one/two/')
+ self.assertEqual(context_url.virtual_path, '/one/two/')
+ self.assertEqual(context_url.physical_path_tuple, ('', 'one', 'two',''))
+ self.assertEqual(context_url.virtual_path_tuple, ('', 'one', 'two', ''))
+
+class TestVirtualRoot(unittest.TestCase):
+ def setUp(self):
+ cleanUp()
+
+ def tearDown(self):
+ cleanUp()
+
+ def _callFUT(self, resource, request):
+ from pyramid.traversal import virtual_root
+ return virtual_root(resource, request)
+
+ def _registerTraverser(self, traverser):
+ from pyramid.threadlocal import get_current_registry
+ reg = get_current_registry()
+ from pyramid.interfaces import ITraverser
+ from zope.interface import Interface
+ reg.registerAdapter(traverser, (Interface,), ITraverser)
+
+ def test_virtual_root_no_virtual_root_path(self):
+ root = DummyContext()
+ root.__name__ = None
+ root.__parent__ = None
+ one = DummyContext()
+ one.__name__ = 'one'
+ one.__parent__ = root
+ request = DummyRequest()
+ result = self._callFUT(one, request)
+ self.assertEqual(result, root)
+
+ def test_virtual_root_no_virtual_root_path_with_root_on_request(self):
+ context = DummyContext()
+ context.__parent__ = None
+ request = DummyRequest()
+ request.root = DummyContext()
+ result = self._callFUT(context, request)
+ self.assertEqual(result, request.root)
+
+ def test_virtual_root_with_virtual_root_path(self):
+ from pyramid.interfaces import VH_ROOT_KEY
+ root = DummyContext()
+ root.__parent__ = None
+ context = DummyContext()
+ context.__name__ = 'one'
+ context.__parent__ = root
+ traversed_to = DummyContext()
+ environ = {VH_ROOT_KEY:'/one'}
+ request = DummyRequest(environ)
+ traverser = make_traverser({'context':traversed_to, 'view_name':''})
+ self._registerTraverser(traverser)
+ result = self._callFUT(context, request)
+ self.assertEqual(result, traversed_to)
+ self.assertEqual(root.request.environ['PATH_INFO'], '/one')
+
+ def test_default(self):
+ context = DummyContext()
+ request = _makeRequest()
+ request.environ['PATH_INFO'] = '/'
+ result = self._callFUT(context, request)
+ self.assertEqual(result, context)
+
+ def test_default_no_registry_on_request(self):
+ context = DummyContext()
+ request = _makeRequest()
+ del request.registry
+ request.environ['PATH_INFO'] = '/'
+ result = self._callFUT(context, request)
+ self.assertEqual(result, context)
+
+class TraverseTests(unittest.TestCase):
+ def setUp(self):
+ cleanUp()
+
+ def tearDown(self):
+ cleanUp()
+
+ def _callFUT(self, context, name):
+ from pyramid.traversal import traverse
+ return traverse(context, name)
+
+ def _registerTraverser(self, traverser):
+ from pyramid.threadlocal import get_current_registry
+ reg = get_current_registry()
+ from pyramid.interfaces import ITraverser
+ from zope.interface import Interface
+ reg.registerAdapter(traverser, (Interface,), ITraverser)
+
+ def test_request_has_registry(self):
+ from pyramid.threadlocal import get_current_registry
+ resource = DummyContext()
+ traverser = make_traverser({'context':resource, 'view_name':''})
+ self._registerTraverser(traverser)
+ self._callFUT(resource, [''])
+ self.assertEqual(resource.request.registry, get_current_registry())
+
+ def test_list(self):
+ resource = DummyContext()
+ traverser = make_traverser({'context':resource, 'view_name':''})
+ self._registerTraverser(traverser)
+ self._callFUT(resource, [''])
+ self.assertEqual(resource.request.environ['PATH_INFO'], '/')
+
+ def test_generator(self):
+ resource = DummyContext()
+ traverser = make_traverser({'context':resource, 'view_name':''})
+ self._registerTraverser(traverser)
+ def foo():
+ yield ''
+ self._callFUT(resource, foo())
+ self.assertEqual(resource.request.environ['PATH_INFO'], '/')
+
+ def test_self_string_found(self):
+ resource = DummyContext()
+ traverser = make_traverser({'context':resource, 'view_name':''})
+ self._registerTraverser(traverser)
+ self._callFUT(resource, '')
+ self.assertEqual(resource.request.environ['PATH_INFO'], '')
+
+ def test_self_unicode_found(self):
+ resource = DummyContext()
+ traverser = make_traverser({'context':resource, 'view_name':''})
+ self._registerTraverser(traverser)
+ self._callFUT(resource, text_(''))
+ self.assertEqual(resource.request.environ['PATH_INFO'], '')
+
+ def test_self_tuple_found(self):
+ resource = DummyContext()
+ traverser = make_traverser({'context':resource, 'view_name':''})
+ self._registerTraverser(traverser)
+ self._callFUT(resource, ())
+ self.assertEqual(resource.request.environ['PATH_INFO'], '')
+
+ def test_relative_string_found(self):
+ resource = DummyContext()
+ baz = DummyContext()
+ traverser = make_traverser({'context':baz, 'view_name':''})
+ self._registerTraverser(traverser)
+ self._callFUT(resource, 'baz')
+ self.assertEqual(resource.request.environ['PATH_INFO'], 'baz')
+
+ def test_relative_tuple_found(self):
+ resource = DummyContext()
+ baz = DummyContext()
+ traverser = make_traverser({'context':baz, 'view_name':''})
+ self._registerTraverser(traverser)
+ self._callFUT(resource, ('baz',))
+ self.assertEqual(resource.request.environ['PATH_INFO'], 'baz')
+
+ def test_absolute_string_found(self):
+ root = DummyContext()
+ resource = DummyContext()
+ resource.__parent__ = root
+ resource.__name__ = 'baz'
+ traverser = make_traverser({'context':root, 'view_name':''})
+ self._registerTraverser(traverser)
+ self._callFUT(resource, '/')
+ self.assertEqual(root.wascontext, True)
+ self.assertEqual(root.request.environ['PATH_INFO'], '/')
+
+ def test_absolute_tuple_found(self):
+ root = DummyContext()
+ resource = DummyContext()
+ resource.__parent__ = root
+ resource.__name__ = 'baz'
+ traverser = make_traverser({'context':root, 'view_name':''})
+ self._registerTraverser(traverser)
+ self._callFUT(resource, ('',))
+ self.assertEqual(root.wascontext, True)
+ self.assertEqual(root.request.environ['PATH_INFO'], '/')
+
+ def test_empty_sequence(self):
+ root = DummyContext()
+ resource = DummyContext()
+ resource.__parent__ = root
+ resource.__name__ = 'baz'
+ traverser = make_traverser({'context':root, 'view_name':''})
+ self._registerTraverser(traverser)
+ self._callFUT(resource, [])
+ self.assertEqual(resource.wascontext, True)
+ self.assertEqual(resource.request.environ['PATH_INFO'], '')
+
+ def test_default_traverser(self):
+ resource = DummyContext()
+ result = self._callFUT(resource, '')
+ self.assertEqual(result['view_name'], '')
+ self.assertEqual(result['context'], resource)
+
+ def test_requestfactory_overridden(self):
+ from pyramid.interfaces import IRequestFactory
+ from pyramid.request import Request
+ from pyramid.threadlocal import get_current_registry
+ reg = get_current_registry()
+ class MyRequest(Request):
+ pass
+ reg.registerUtility(MyRequest, IRequestFactory)
+ resource = DummyContext()
+ traverser = make_traverser({'context':resource, 'view_name':''})
+ self._registerTraverser(traverser)
+ self._callFUT(resource, [''])
+ self.assertEqual(resource.request.__class__, MyRequest)
+
+class TestDefaultRootFactory(unittest.TestCase):
+ def _getTargetClass(self):
+ from pyramid.traversal import DefaultRootFactory
+ return DefaultRootFactory
+
+ def _makeOne(self, environ):
+ return self._getTargetClass()(environ)
+
+ def test_it(self):
+ class DummyRequest(object):
+ pass
+ root = self._makeOne(DummyRequest())
+ self.assertEqual(root.__parent__, None)
+ self.assertEqual(root.__name__, None)
+
+class Test__join_path_tuple(unittest.TestCase):
+ def _callFUT(self, tup):
+ from pyramid.traversal import _join_path_tuple
+ return _join_path_tuple(tup)
+
+ def test_empty_tuple(self):
+ # tests "or '/'" case
+ result = self._callFUT(())
+ self.assertEqual(result, '/')
+
+ def test_nonempty_tuple(self):
+ result = self._callFUT(('x',))
+ self.assertEqual(result, 'x')
+
+ def test_segments_with_unsafes(self):
+ safe_segments = tuple(u"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._~!$&'()*+,;=:@")
+ result = self._callFUT(safe_segments)
+ self.assertEqual(result, u'/'.join(safe_segments))
+ unsafe_segments = tuple(chr(i) for i in range(0x20, 0x80) if not chr(i) in safe_segments) + (u'あ',)
+ result = self._callFUT(unsafe_segments)
+ self.assertEqual(result, u'/'.join(''.join('%%%02X' % (ord(c) if isinstance(c, str) else c) for c in unsafe_segment.encode('utf-8')) for unsafe_segment in unsafe_segments))
+
+
+def make_traverser(result):
+ class DummyTraverser(object):
+ def __init__(self, context):
+ self.context = context
+ context.wascontext = True
+ def __call__(self, request):
+ self.context.request = request
+ return result
+ return DummyTraverser
+
+class DummyContext(object):
+ __parent__ = None
+ def __init__(self, next=None, name=None):
+ self.next = next
+ self.__name__ = name
+
+ def __getitem__(self, name):
+ if self.next is None:
+ raise KeyError(name)
+ return self.next
+
+ def __repr__(self):
+ return '<DummyContext with name %s at id %s>'%(self.__name__, id(self))
+
+class DummyRequest:
+
+ application_url = 'http://example.com:5432' # app_url never ends with slash
+ matchdict = None
+ matched_route = None
+
+ def __init__(self, environ=None, path_info=text_('/'), toraise=None):
+ if environ is None:
+ environ = {}
+ self.environ = environ
+ self._set_path_info(path_info)
+ self.toraise = toraise
+
+ def _get_path_info(self):
+ if self.toraise:
+ raise self.toraise
+ return self._path_info
+
+ def _set_path_info(self, v):
+ self._path_info = v
+
+ path_info = property(_get_path_info, _set_path_info)
+
+
+def _makeRequest(environ=None):
+ from pyramid.registry import Registry
+ request = DummyRequest()
+ request.registry = Registry()
+ return request