diff options
| author | Michael Merickel <michael@merickel.org> | 2018-10-14 21:11:41 -0500 |
|---|---|---|
| committer | Michael Merickel <michael@merickel.org> | 2018-10-14 21:11:41 -0500 |
| commit | 3670c2cdb732d378ba6d38e72e7cd875ff726aa9 (patch) | |
| tree | 5213452a778c992d42602efe7d3b3655a349abd5 /tests/test_traversal.py | |
| parent | 2b024920847481592b1a13d4006d2a9fa8881d72 (diff) | |
| download | pyramid-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.py | 1221 |
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 |
