Beispiel #1
0
 def setUp(self):
     PlacelessSetup.setUp(self)
     # Build up a wrapper chain
     self.root = C('root')
     self.folder = contained(C('folder'), self.root, name='folder')
     self.item = contained(C('item'), self.folder, name='item')
     self.tr = Traverser(self.item)
Beispiel #2
0
    def setUp(self):
        PlacelessSetup.setUp(self)
        # Build up a wrapper chain
        root = C('root')
        interface.directlyProvides(root, IRoot)
        folder = C('folder')
        item = C('item')

        self.root = root  # root is not usually wrapped
        self.folder = contained(folder, self.root, name='folder')
        self.item = contained(item, self.folder, name='item')
        self.unwrapped_item = item
        self.broken_chain_folder = contained(folder, None)
        self.broken_chain_item = contained(item,
                                           self.broken_chain_folder,
                                           name='item')
        root.folder = folder
        folder.item = item

        self.tr = Traverser(root)
        zope.component.provideAdapter(Traverser, (None, ), ITraverser)
        zope.component.provideAdapter(DefaultTraversable, (None, ),
                                      ITraversable)
        zope.component.provideAdapter(LocationPhysicallyLocatable, (None, ),
                                      ILocationInfo)
        zope.component.provideAdapter(RootPhysicallyLocatable, (IRoot, ),
                                      ILocationInfo)
    def testTraverseOldStyleClass(self):
        class AnOldStyleClass:
            x = object()
        container = {}
        container['theclass'] = AnOldStyleClass

        tr = Traverser(container)
        self.assert_(tr.traverse('theclass/x') is AnOldStyleClass.x)
Beispiel #4
0
    def testTraverseOldStyleClass(self):
        class AnOldStyleClass:
            x = object()

        container = {}
        container['theclass'] = AnOldStyleClass

        tr = Traverser(container)
        self.assertTrue(tr.traverse('theclass/x') is AnOldStyleClass.x)
    def testAllAllowed(self):
        defineChecker(C, Checker({'folder': CheckerPublic,
                                  'item': CheckerPublic,
                                  }))
        tr = Traverser(ProxyFactory(self.root))
        item = self.item

        self.assertEquals(tr.traverse(('', 'folder', 'item')), item)
        self.assertEquals(tr.traverse(('folder', 'item')), item)
Beispiel #6
0
    def testAllAllowed(self):
        defineChecker(
            C, Checker({
                'folder': CheckerPublic,
                'item': CheckerPublic,
            }))
        tr = Traverser(ProxyFactory(self.root))
        item = self.item

        self.assertEqual(tr.traverse(('', 'folder', 'item')), item)
        self.assertEqual(tr.traverse(('folder', 'item')), item)
 def testTraversingDictSeesDictAPI(self):
     adict = {
         'foo': 'bar',
         'anotherdict': {'bar': 'foo'},
         'items': '123',
         }
     tr = Traverser(adict)
     self.assertEqual(tr.traverse('items'), adict.items)
     self.assertEqual(tr.traverse('anotherdict/bar'), 'foo')
     self.assertEqual(tr.traverse('anotherdict/items'),
                      adict['anotherdict'].items)
Beispiel #8
0
    def testItemDenied(self):
        endInteraction()
        newInteraction(ParticipationStub('no one'))
        defineChecker(C, Checker({'item': 'Waaaa', 'folder': CheckerPublic}))
        tr = Traverser(ProxyFactory(self.root))
        folder = self.folder

        self.assertRaises(Unauthorized, tr.traverse, ('', 'folder', 'item'))
        self.assertRaises(Unauthorized, tr.traverse, ('folder', 'item'))
        self.assertEqual(tr.traverse(('', 'folder')), folder)
        self.assertEqual(tr.traverse(('folder', '..', 'folder')), folder)
        self.assertEqual(tr.traverse(('folder', )), folder)
Beispiel #9
0
 def testTraversingDictSeesDictAPI(self):
     adict = {
         'foo': 'bar',
         'anotherdict': {
             'bar': 'foo'
         },
         'items': '123',
     }
     tr = Traverser(adict)
     self.assertEqual(tr.traverse('items'), adict.items)
     self.assertEqual(tr.traverse('anotherdict/bar'), 'foo')
     self.assertEqual(tr.traverse('anotherdict/items'),
                      adict['anotherdict'].items)
    def testItemDenied(self):
        endInteraction()
        newInteraction(ParticipationStub('no one'))
        defineChecker(C, Checker({'item': 'Waaaa', 'folder': CheckerPublic}))
        tr = Traverser(ProxyFactory(self.root))
        folder = self.folder

        self.assertRaises(Unauthorized, tr.traverse,
            ('', 'folder', 'item'))
        self.assertRaises(Unauthorized, tr.traverse,
            ('folder', 'item'))
        self.assertEquals(tr.traverse(('', 'folder')), folder)
        self.assertEquals(tr.traverse(('folder', '..', 'folder')),
                          folder)
        self.assertEquals(tr.traverse(('folder',)), folder)
 def setUp(self):
     PlacelessSetup.setUp(self)
     # Build up a wrapper chain
     self.root = C('root')
     self.folder = contained(C('folder'), self.root, name='folder')
     self.item = contained(C('item'), self.folder, name='item')
     self.tr = Traverser(self.item)
    def setUp(self):
        PlacelessSetup.setUp(self)
        # Build up a wrapper chain
        root = C('root')
        interface.directlyProvides(root, IRoot)
        folder = C('folder')
        item = C('item')

        self.root = root  # root is not usually wrapped
        self.folder = contained(folder, self.root, name='folder')
        self.item = contained(item, self.folder, name='item')
        self.unwrapped_item = item
        self.broken_chain_folder = contained(folder, None)
        self.broken_chain_item = contained(
            item,
            self.broken_chain_folder,
            name='item'
        )
        root.folder = folder
        folder.item = item

        self.tr = Traverser(root)
        zope.component.provideAdapter(Traverser, (None,), ITraverser)
        zope.component.provideAdapter(DefaultTraversable, (None,), ITraversable)
        zope.component.provideAdapter(LocationPhysicallyLocatable, (None,),
                                      ILocationInfo)
        zope.component.provideAdapter(RootPhysicallyLocatable,
                                      (IRoot,), ILocationInfo)
Beispiel #13
0
    def setUp(self):
        self.root = root = C('root')
        directlyProvides(self.root, IRoot)
        self.folder = folder = C('folder')
        self.item = item = C('item')

        root.folder = folder
        folder.item = item

        self.tr = Traverser(root)
Beispiel #14
0
    def setUp(self):
        PlacelessSetup.setUp(self)

        zope.component.provideAdapter(DefaultTraversable, (None, ),
                                      ITraversable)
        zope.component.provideAdapter(LocationPhysicallyLocatable, (None, ),
                                      ILocationInfo)
        zope.component.provideAdapter(RootPhysicallyLocatable, (IRoot, ),
                                      ILocationInfo)

        # Build up a wrapper chain
        self.root = root = C('root')
        directlyProvides(self.root, IRoot)
        self.folder = folder = contained(C('folder'), root, 'folder')
        self.item = item = contained(C('item'), folder, 'item')

        root.folder = folder
        folder.item = item

        self.tr = Traverser(root)
Beispiel #15
0
    def testException(self):
        # nail the fact that AttributeError raised in a @property
        # decorated method gets masked by traversal
        self.root.foobar = ExceptionRaiser('foobar')

        endInteraction()
        newInteraction(ParticipationStub('no one'))
        tr = Traverser(self.root)

        # AttributeError becomes LocationError if there's no __getitem__
        # on the object
        self.assertRaises(LocationError, tr.traverse,
                          ('foobar', 'attributeerror'))
        # Other exceptions raised as usual
        self.assertRaises(ValueError, tr.traverse, ('foobar', 'valueerror'))
Beispiel #16
0
class TraverserTests(PlacelessSetup, unittest.TestCase):
    def setUp(self):
        PlacelessSetup.setUp(self)
        # Build up a wrapper chain
        self.root = C('root')
        self.folder = contained(C('folder'), self.root, name='folder')
        self.item = contained(C('item'), self.folder, name='item')
        self.tr = Traverser(self.item)

    def testImplementsITraverser(self):
        self.assertTrue(ITraverser.providedBy(self.tr))

    def testVerifyInterfaces(self):
        for interface in implementedBy(Traverser):
            verifyClass(interface, Traverser)

    def test_traverse_empty_path_is_context(self):
        self.assertIs(self.item, self.tr.traverse(''))
class TraverserTests(PlacelessSetup, unittest.TestCase):

    def setUp(self):
        PlacelessSetup.setUp(self)
        # Build up a wrapper chain
        self.root = C('root')
        self.folder = contained(C('folder'), self.root, name='folder')
        self.item = contained(C('item'), self.folder, name='item')
        self.tr = Traverser(self.item)

    def testImplementsITraverser(self):
        self.assertTrue(ITraverser.providedBy(self.tr))

    def testVerifyInterfaces(self):
        for interface in implementedBy(Traverser):
            verifyClass(interface, Traverser)

    def test_traverse_empty_path_is_context(self):
        self.assertIs(self.item, self.tr.traverse(''))
    def setUp(self):
        PlacelessSetup.setUp(self)

        zope.component.provideAdapter(DefaultTraversable, (None,), ITraversable)
        zope.component.provideAdapter(LocationPhysicallyLocatable, (None,),
                                      ILocationInfo)
        zope.component.provideAdapter(RootPhysicallyLocatable,
                                      (IRoot,), ILocationInfo)

        # Build up a wrapper chain
        self.root = root = C('root')
        directlyProvides(self.root, IRoot)
        self.folder = folder = contained(C('folder'), root, 'folder')
        self.item = item = contained(C('item'), folder, 'item')

        root.folder = folder
        folder.item = item

        self.tr = Traverser(root)
Beispiel #19
0
class UnrestrictedTraverseTests(PlacelessSetup, unittest.TestCase):
    def setUp(self):
        PlacelessSetup.setUp(self)

        zope.component.provideAdapter(DefaultTraversable, (None, ),
                                      ITraversable)
        zope.component.provideAdapter(LocationPhysicallyLocatable, (None, ),
                                      ILocationInfo)
        zope.component.provideAdapter(RootPhysicallyLocatable, (IRoot, ),
                                      ILocationInfo)

        # Build up a wrapper chain
        self.root = root = C('root')
        directlyProvides(self.root, IRoot)
        self.folder = folder = contained(C('folder'), root, 'folder')
        self.item = item = contained(C('item'), folder, 'item')

        root.folder = folder
        folder.item = item

        self.tr = Traverser(root)

    def testSimplePathString(self):
        tr = self.tr
        item = self.item

        self.assertEqual(tr.traverse('/folder/item'), item)
        self.assertEqual(tr.traverse('folder/item'), item)
        self.assertEqual(tr.traverse('/folder/item/'), item)

    def testSimplePathUnicode(self):
        tr = self.tr
        item = self.item

        self.assertEqual(tr.traverse(u'/folder/item'), item)
        self.assertEqual(tr.traverse(u'folder/item'), item)
        self.assertEqual(tr.traverse(u'/folder/item/'), item)

    def testSimplePathTuple(self):
        tr = self.tr
        item = self.item

        self.assertEqual(tr.traverse(('', 'folder', 'item')), item)
        self.assertEqual(tr.traverse(('folder', 'item')), item)

    def testComplexPathString(self):
        tr = self.tr
        item = self.item

        self.assertEqual(tr.traverse('/folder/../folder/./item'), item)

    def testNotFoundDefault(self):
        self.assertEqual(self.tr.traverse('foo', 'notFound'), 'notFound')

    def testNotFoundNoDefault(self):
        self.assertRaises(LocationError, self.tr.traverse, 'foo')

    def testTraverseOldStyleClass(self):
        class AnOldStyleClass:
            x = object()

        container = {}
        container['theclass'] = AnOldStyleClass

        tr = Traverser(container)
        self.assertTrue(tr.traverse('theclass/x') is AnOldStyleClass.x)

    def testTraversingDictSeesDictAPI(self):
        adict = {
            'foo': 'bar',
            'anotherdict': {
                'bar': 'foo'
            },
            'items': '123',
        }
        tr = Traverser(adict)
        self.assertEqual(tr.traverse('items'), adict.items)
        self.assertEqual(tr.traverse('anotherdict/bar'), 'foo')
        self.assertEqual(tr.traverse('anotherdict/items'),
                         adict['anotherdict'].items)

    def testTraversingDoesntFailOnStrings(self):
        adict = {'foo': 'bar'}
        tr = Traverser(adict)
        # This used to raise type error before
        self.assertRaises(LocationError, tr.traverse, 'foo/baz')
class UnrestrictedTraverseTests(PlacelessSetup, unittest.TestCase):
    def setUp(self):
        PlacelessSetup.setUp(self)

        zope.component.provideAdapter(DefaultTraversable, (None,), ITraversable)
        zope.component.provideAdapter(LocationPhysicallyLocatable, (None,),
                                      ILocationInfo)
        zope.component.provideAdapter(RootPhysicallyLocatable,
                                      (IRoot,), ILocationInfo)

        # Build up a wrapper chain
        self.root = root = C('root')
        directlyProvides(self.root, IRoot)
        self.folder = folder = contained(C('folder'), root, 'folder')
        self.item = item = contained(C('item'), folder, 'item')

        root.folder = folder
        folder.item = item

        self.tr = Traverser(root)

    def testSimplePathString(self):
        tr = self.tr
        item = self.item

        self.assertEquals(tr.traverse('/folder/item'), item)
        self.assertEquals(tr.traverse('folder/item'), item)
        self.assertEquals(tr.traverse('/folder/item/'), item)

    def testSimplePathUnicode(self):
        tr = self.tr
        item = self.item

        self.assertEquals(tr.traverse(u'/folder/item'), item)
        self.assertEquals(tr.traverse(u'folder/item'), item)
        self.assertEquals(tr.traverse(u'/folder/item/'), item)

    def testSimplePathTuple(self):
        tr = self.tr
        item = self.item

        self.assertEquals(tr.traverse(('', 'folder', 'item')),
                          item)
        self.assertEquals(tr.traverse(('folder', 'item')), item)

    def testComplexPathString(self):
        tr = self.tr
        item = self.item

        self.assertEquals(tr.traverse('/folder/../folder/./item'),
            item)

    def testNotFoundDefault(self):
        self.assertEquals(self.tr.traverse('foo', 'notFound'),
            'notFound')

    def testNotFoundNoDefault(self):
        self.assertRaises(LocationError, self.tr.traverse, 'foo')

    def testTraverseOldStyleClass(self):
        class AnOldStyleClass:
            x = object()
        container = {}
        container['theclass'] = AnOldStyleClass

        tr = Traverser(container)
        self.assert_(tr.traverse('theclass/x') is AnOldStyleClass.x)

    def testTraversingDictSeesDictAPI(self):
        adict = {
            'foo': 'bar',
            'anotherdict': {'bar': 'foo'},
            'items': '123',
            }
        tr = Traverser(adict)
        self.assertEqual(tr.traverse('items'), adict.items)
        self.assertEqual(tr.traverse('anotherdict/bar'), 'foo')
        self.assertEqual(tr.traverse('anotherdict/items'),
                         adict['anotherdict'].items)

    def testTraversingDoesntFailOnStrings(self):
        adict = {'foo': 'bar'}
        tr = Traverser(adict)
        # This used to raise type error before
        self.assertRaises(LocationError, tr.traverse, 'foo/baz')
Beispiel #21
0
 def testTraversingDoesntFailOnStrings(self):
     adict = {'foo': 'bar'}
     tr = Traverser(adict)
     # This used to raise type error before
     self.assertRaises(LocationError, tr.traverse, 'foo/baz')
class TestFunctional(PlacelessSetup, unittest.TestCase):

    def setUp(self):
        PlacelessSetup.setUp(self)
        # Build up a wrapper chain
        root = C('root')
        interface.directlyProvides(root, IRoot)
        folder = C('folder')
        item = C('item')

        self.root = root  # root is not usually wrapped
        self.folder = contained(folder, self.root, name='folder')
        self.item = contained(item, self.folder, name='item')
        self.unwrapped_item = item
        self.broken_chain_folder = contained(folder, None)
        self.broken_chain_item = contained(
            item,
            self.broken_chain_folder,
            name='item'
        )
        root.folder = folder
        folder.item = item

        self.tr = Traverser(root)
        zope.component.provideAdapter(Traverser, (None,), ITraverser)
        zope.component.provideAdapter(DefaultTraversable, (None,), ITraversable)
        zope.component.provideAdapter(LocationPhysicallyLocatable, (None,),
                                      ILocationInfo)
        zope.component.provideAdapter(RootPhysicallyLocatable,
                                      (IRoot,), ILocationInfo)

    def testTraverse(self):
        from zope.traversing.api import traverse
        self.assertEqual(
            traverse(self.item, '/folder/item'),
            self.tr.traverse('/folder/item')
            )

    def test_traverse_with_default(self):
        from zope.traversing.api import traverse
        self.assertIs(
            traverse(self.item, '/no/path', self),
            self
        )

    def testTraverseFromUnwrapped(self):
        from zope.traversing.api import traverse
        self.assertRaises(
            TypeError,
            traverse,
            self.unwrapped_item, '/folder/item'
            )

    def testTraverseName(self):
        from zope.traversing.api import traverseName
        self.assertEqual(
            traverseName(self.folder, 'item'),
            self.tr.traverse('/folder/item')
        )
        self.assertEqual(
            traverseName(self.item, '.'),
            self.tr.traverse('/folder/item')
        )
        self.assertEqual(
            traverseName(self.item, '..'),
            self.tr.traverse('/folder')
        )
        self.assertEqual(
            traverseName(self.folder, 'item', default=self),
            self.tr.traverse('/folder/item')
        )
        self.assertIs(
            traverseName(self.folder, 'nothing', default=self),
            self,
        )

        # TODO test that ++names++ and @@names work too

    def testTraverseNameBadValue(self):
        from zope.traversing.api import traverseName
        self.assertRaises(
            LocationError,
            traverseName,
            self.folder, '../root'
            )
        self.assertRaises(
            LocationError,
            traverseName,
            self.folder, '/root'
            )
        self.assertRaises(
            LocationError,
            traverseName,
            self.folder, './item'
            )

    def testTraverseNameUnicode(self):
        from zope.traversing.api import traverseName
        from zope.interface import implementer

        @implementer(ITraversable)
        class BrokenTraversable(object):
            def traverse(self, name, furtherPath):
                getattr(self, u'\u2019', None)
                # The above actually works on Python 3
                raise unittest.SkipTest("Unicode attrs legal on Py3")

        self.assertRaises(
            LocationError,
            traverseName,
            BrokenTraversable(), '')


    def testGetName(self):
        from zope.traversing.api import getName
        self.assertEqual(
            getName(self.item),
            'item'
            )

    def testGetParent(self):
        from zope.traversing.api import getParent
        self.assertEqual(
            getParent(self.item),
            self.folder
            )

    def testGetParentFromRoot(self):
        from zope.traversing.api import getParent
        self.assertEqual(
            getParent(self.root),
            None
            )

    def testGetParentBrokenChain(self):
        from zope.traversing.api import getParent
        self.assertRaises(
            TypeError,
            getParent,
            self.broken_chain_folder
            )

    def testGetParentFromUnwrapped(self):
        from zope.traversing.api import getParent
        self.assertRaises(
            TypeError,
            getParent,
            self.unwrapped_item
            )

    def testGetParents(self):
        from zope.traversing.api import getParents
        self.assertEqual(
            getParents(self.item),
            [self.folder, self.root]
            )

    def testGetParentsBrokenChain(self):
        from zope.traversing.api import getParents
        self.assertRaises(
            TypeError,
            getParents,
            self.broken_chain_item
            )

    def testGetPath(self):
        from zope.traversing.api import getPath
        self.assertEqual(
            getPath(self.item),
            u'/folder/item'
            )

    def testGetPathOfRoot(self):
        from zope.traversing.api import getPath
        self.assertEqual(
            getPath(self.root),
            u'/',
            )

    def testGetNameOfRoot(self):
        from zope.traversing.api import getName
        self.assertEqual(
            getName(self.root),
            u'',
            )

    def testGetRoot(self):
        from zope.traversing.api import getRoot
        self.assertEqual(
            getRoot(self.item),
            self.root
            )

    def testCanonicalPath(self):

        _bad_locations = (
            (ValueError, '\xa323'),
            (ValueError, ''),
            (ValueError, '//'),
            (ValueError, '/foo//bar'),

            # regarding the next two errors:
            # having a trailing slash on a location is undefined.
            # we might want to give it a particular meaning for zope3 later
            # for now, it is an invalid location identifier
            (ValueError, '/foo/bar/'),
            (ValueError, 'foo/bar/'),

            (IndexError, '/a/../..'),
            (ValueError, '/a//v'),
            )

        # sequence of N-tuples:
        #   (loc_returned_as_string, input, input, ...)
        # The string and tuple are tested as input as well as being the
        # specification for output.

        _good_locations = (
            # location returned as string
            (u'/xx/yy/zz',
             # arguments to try in addition to the above
             '/xx/yy/zz',
             '/xx/./yy/ww/../zz',
            ),
            (u'/xx/yy/zz',
             '/xx/yy/zz',
            ),
            (u'/xx',
             '/xx',
            ),
            (u'/',
             '/',
             self.root,
            ),
        )

        from zope.traversing.api import canonicalPath

        for error_type, value in _bad_locations:
            self.assertRaises(error_type, canonicalPath, value)

        for spec in _good_locations:
            correct_answer = spec[0]
            for argument in spec:
                self.assertEqual(canonicalPath(argument), correct_answer,
                                 "failure on %s" % argument)


    def test_normalizePath(self):

        _bad_locations = (
            (ValueError, '//'),
            (ValueError, '/foo//bar'),
            (IndexError, '/a/../..'),
            (IndexError, '/a/./../..'),
            )

        # sequence of N-tuples:
        #   (loc_returned_as_string, input, input, ...)
        # The string and tuple are tested as input as well as being the
        # specification for output.

        _good_locations = (
            # location returned as string
            ('/xx/yy/zz',
             # arguments to try in addition to the above
             '/xx/yy/zz',
             '/xx/./yy/ww/../zz',
             '/xx/./yy/ww/./../zz',
            ),
            ('xx/yy/zz',
             # arguments to try in addition to the above
             'xx/yy/zz',
             'xx/./yy/ww/../zz',
             'xx/./yy/ww/./../zz',
            ),
            ('/xx/yy/zz',
             '/xx/yy/zz',
            ),
            ('/xx',
             '/xx',
            ),
            ('/',
             '/',
            ),
        )


        from zope.traversing.api import _normalizePath

        for error_type, value in _bad_locations:
            self.assertRaises(error_type, _normalizePath, value)

        for spec in _good_locations:
            correct_answer = spec[0]
            for argument in spec:
                self.assertEqual(_normalizePath(argument), correct_answer,
                                 "failure on %s" % argument)

    def test_joinPath_slashes(self):
        from zope.traversing.api import joinPath
        path = u'/'
        args = ('/test', 'bla', '/foo', 'bar')
        self.assertRaises(ValueError, joinPath, path, *args)

        args = ('/test', 'bla', 'foo/', '/bar')
        self.assertRaises(ValueError, joinPath, path, *args)

    def test_joinPath(self):
        from zope.traversing.api import joinPath
        path = u'/bla'
        args = ('foo', 'bar', 'baz', 'bone')
        self.assertEqual(joinPath(path, *args), u'/bla/foo/bar/baz/bone')

        path = u'bla'
        args = ('foo', 'bar', 'baz', 'bone')
        self.assertEqual(joinPath(path, *args), u'bla/foo/bar/baz/bone')

        path = u'bla'
        args = ('foo', 'bar/baz', 'bone')
        self.assertEqual(joinPath(path, *args), u'bla/foo/bar/baz/bone')

        path = u'bla/'
        args = ('foo', 'bar', 'baz', 'bone')
        self.assertRaises(ValueError, joinPath, path, *args)

    def test_joinPath_normalize(self):
        from zope.traversing.api import joinPath
        path = u'/bla'
        args = ('foo', 'bar', '..', 'baz', 'bone')
        self.assertEqual(joinPath(path, *args), u'/bla/foo/baz/bone')

        path = u'bla'
        args = ('foo', 'bar', '.', 'baz', 'bone')
        self.assertEqual(joinPath(path, *args), u'bla/foo/bar/baz/bone')

        path = u'/'
        args = ('foo', 'bar', '.', 'baz', 'bone')
        self.assertEqual(joinPath(path, *args), u'/foo/bar/baz/bone')

    def test_joinPath_empty_args(self):
        from zope.traversing.api import joinPath
        path = 'abc'
        self.assertEqual(joinPath(path), u'abc')
Beispiel #23
0
class TestFunctional(PlacelessSetup, unittest.TestCase):
    def setUp(self):
        PlacelessSetup.setUp(self)
        # Build up a wrapper chain
        root = C('root')
        interface.directlyProvides(root, IRoot)
        folder = C('folder')
        item = C('item')

        self.root = root  # root is not usually wrapped
        self.folder = contained(folder, self.root, name='folder')
        self.item = contained(item, self.folder, name='item')
        self.unwrapped_item = item
        self.broken_chain_folder = contained(folder, None)
        self.broken_chain_item = contained(item,
                                           self.broken_chain_folder,
                                           name='item')
        root.folder = folder
        folder.item = item

        self.tr = Traverser(root)
        zope.component.provideAdapter(Traverser, (None, ), ITraverser)
        zope.component.provideAdapter(DefaultTraversable, (None, ),
                                      ITraversable)
        zope.component.provideAdapter(LocationPhysicallyLocatable, (None, ),
                                      ILocationInfo)
        zope.component.provideAdapter(RootPhysicallyLocatable, (IRoot, ),
                                      ILocationInfo)

    def testTraverse(self):
        from zope.traversing.api import traverse
        self.assertEqual(traverse(self.item, '/folder/item'),
                         self.tr.traverse('/folder/item'))

    def test_traverse_with_default(self):
        from zope.traversing.api import traverse
        self.assertIs(traverse(self.item, '/no/path', self), self)

    def testTraverseFromUnwrapped(self):
        from zope.traversing.api import traverse
        self.assertRaises(TypeError, traverse, self.unwrapped_item,
                          '/folder/item')

    def testTraverseName(self):
        from zope.traversing.api import traverseName
        self.assertEqual(traverseName(self.folder, 'item'),
                         self.tr.traverse('/folder/item'))
        self.assertEqual(traverseName(self.item, '.'),
                         self.tr.traverse('/folder/item'))
        self.assertEqual(traverseName(self.item, '..'),
                         self.tr.traverse('/folder'))
        self.assertEqual(traverseName(self.folder, 'item', default=self),
                         self.tr.traverse('/folder/item'))
        self.assertIs(
            traverseName(self.folder, 'nothing', default=self),
            self,
        )

        # TODO test that ++names++ and @@names work too

    def testTraverseNameBadValue(self):
        from zope.traversing.api import traverseName
        self.assertRaises(LocationError, traverseName, self.folder, '../root')
        self.assertRaises(LocationError, traverseName, self.folder, '/root')
        self.assertRaises(LocationError, traverseName, self.folder, './item')

    def testTraverseNameUnicode(self):
        from zope.traversing.api import traverseName
        from zope.interface import implementer

        @implementer(ITraversable)
        class BrokenTraversable(object):
            def traverse(self, name, furtherPath):
                getattr(self, u'\u2019', None)
                # The above actually works on Python 3
                raise unittest.SkipTest("Unicode attrs legal on Py3")

        self.assertRaises(LocationError, traverseName, BrokenTraversable(), '')

    def testGetName(self):
        from zope.traversing.api import getName
        self.assertEqual(getName(self.item), 'item')

    def testGetParent(self):
        from zope.traversing.api import getParent
        self.assertEqual(getParent(self.item), self.folder)

    def testGetParentFromRoot(self):
        from zope.traversing.api import getParent
        self.assertEqual(getParent(self.root), None)

    def testGetParentBrokenChain(self):
        from zope.traversing.api import getParent
        self.assertRaises(TypeError, getParent, self.broken_chain_folder)

    def testGetParentFromUnwrapped(self):
        from zope.traversing.api import getParent
        self.assertRaises(TypeError, getParent, self.unwrapped_item)

    def testGetParents(self):
        from zope.traversing.api import getParents
        self.assertEqual(getParents(self.item), [self.folder, self.root])

    def testGetParentsBrokenChain(self):
        from zope.traversing.api import getParents
        self.assertRaises(TypeError, getParents, self.broken_chain_item)

    def testGetPath(self):
        from zope.traversing.api import getPath
        self.assertEqual(getPath(self.item), u'/folder/item')

    def testGetPathOfRoot(self):
        from zope.traversing.api import getPath
        self.assertEqual(
            getPath(self.root),
            u'/',
        )

    def testGetNameOfRoot(self):
        from zope.traversing.api import getName
        self.assertEqual(
            getName(self.root),
            u'',
        )

    def testGetRoot(self):
        from zope.traversing.api import getRoot
        self.assertEqual(getRoot(self.item), self.root)

    def testCanonicalPath(self):

        _bad_locations = (
            (ValueError, '\xa323'),
            (ValueError, ''),
            (ValueError, '//'),
            (ValueError, '/foo//bar'),

            # regarding the next two errors:
            # having a trailing slash on a location is undefined.
            # we might want to give it a particular meaning for zope3 later
            # for now, it is an invalid location identifier
            (ValueError, '/foo/bar/'),
            (ValueError, 'foo/bar/'),
            (IndexError, '/a/../..'),
            (ValueError, '/a//v'),
        )

        # sequence of N-tuples:
        #   (loc_returned_as_string, input, input, ...)
        # The string and tuple are tested as input as well as being the
        # specification for output.

        _good_locations = (
            # location returned as string
            (
                u'/xx/yy/zz',
                # arguments to try in addition to the above
                '/xx/yy/zz',
                '/xx/./yy/ww/../zz',
            ),
            (
                u'/xx/yy/zz',
                '/xx/yy/zz',
            ),
            (
                u'/xx',
                '/xx',
            ),
            (
                u'/',
                '/',
                self.root,
            ),
        )

        from zope.traversing.api import canonicalPath

        for error_type, value in _bad_locations:
            self.assertRaises(error_type, canonicalPath, value)

        for spec in _good_locations:
            correct_answer = spec[0]
            for argument in spec:
                self.assertEqual(canonicalPath(argument), correct_answer,
                                 "failure on %s" % argument)

    def test_normalizePath(self):

        _bad_locations = (
            (ValueError, '//'),
            (ValueError, '/foo//bar'),
            (IndexError, '/a/../..'),
            (IndexError, '/a/./../..'),
        )

        # sequence of N-tuples:
        #   (loc_returned_as_string, input, input, ...)
        # The string and tuple are tested as input as well as being the
        # specification for output.

        _good_locations = (
            # location returned as string
            (
                '/xx/yy/zz',
                # arguments to try in addition to the above
                '/xx/yy/zz',
                '/xx/./yy/ww/../zz',
                '/xx/./yy/ww/./../zz',
            ),
            (
                'xx/yy/zz',
                # arguments to try in addition to the above
                'xx/yy/zz',
                'xx/./yy/ww/../zz',
                'xx/./yy/ww/./../zz',
            ),
            (
                '/xx/yy/zz',
                '/xx/yy/zz',
            ),
            (
                '/xx',
                '/xx',
            ),
            (
                '/',
                '/',
            ),
        )

        from zope.traversing.api import _normalizePath

        for error_type, value in _bad_locations:
            self.assertRaises(error_type, _normalizePath, value)

        for spec in _good_locations:
            correct_answer = spec[0]
            for argument in spec:
                self.assertEqual(_normalizePath(argument), correct_answer,
                                 "failure on %s" % argument)

    def test_joinPath_slashes(self):
        from zope.traversing.api import joinPath
        path = u'/'
        args = ('/test', 'bla', '/foo', 'bar')
        self.assertRaises(ValueError, joinPath, path, *args)

        args = ('/test', 'bla', 'foo/', '/bar')
        self.assertRaises(ValueError, joinPath, path, *args)

    def test_joinPath(self):
        from zope.traversing.api import joinPath
        path = u'/bla'
        args = ('foo', 'bar', 'baz', 'bone')
        self.assertEqual(joinPath(path, *args), u'/bla/foo/bar/baz/bone')

        path = u'bla'
        args = ('foo', 'bar', 'baz', 'bone')
        self.assertEqual(joinPath(path, *args), u'bla/foo/bar/baz/bone')

        path = u'bla'
        args = ('foo', 'bar/baz', 'bone')
        self.assertEqual(joinPath(path, *args), u'bla/foo/bar/baz/bone')

        path = u'bla/'
        args = ('foo', 'bar', 'baz', 'bone')
        self.assertRaises(ValueError, joinPath, path, *args)

    def test_joinPath_normalize(self):
        from zope.traversing.api import joinPath
        path = u'/bla'
        args = ('foo', 'bar', '..', 'baz', 'bone')
        self.assertEqual(joinPath(path, *args), u'/bla/foo/baz/bone')

        path = u'bla'
        args = ('foo', 'bar', '.', 'baz', 'bone')
        self.assertEqual(joinPath(path, *args), u'bla/foo/bar/baz/bone')

        path = u'/'
        args = ('foo', 'bar', '.', 'baz', 'bone')
        self.assertEqual(joinPath(path, *args), u'/foo/bar/baz/bone')

    def test_joinPath_empty_args(self):
        from zope.traversing.api import joinPath
        path = 'abc'
        self.assertEqual(joinPath(path), u'abc')