[Checkins] SVN: zope.traversing/tags/3.5.1/ Tag 3.5.1

Dan Korostelev nadako at gmail.com
Mon Feb 2 07:25:13 EST 2009


Log message for revision 95965:
  Tag 3.5.1

Changed:
  A   zope.traversing/tags/3.5.1/
  D   zope.traversing/tags/3.5.1/CHANGES.txt
  A   zope.traversing/tags/3.5.1/CHANGES.txt
  D   zope.traversing/tags/3.5.1/buildout.cfg
  A   zope.traversing/tags/3.5.1/buildout.cfg
  D   zope.traversing/tags/3.5.1/setup.py
  A   zope.traversing/tags/3.5.1/setup.py
  D   zope.traversing/tags/3.5.1/src/
  A   zope.traversing/tags/3.5.1/src/
  D   zope.traversing/tags/3.5.1/src/zope/traversing/DEPENDENCIES.cfg
  D   zope.traversing/tags/3.5.1/src/zope/traversing/adapters.py
  A   zope.traversing/tags/3.5.1/src/zope/traversing/adapters.py
  D   zope.traversing/tags/3.5.1/src/zope/traversing/api.py
  A   zope.traversing/tags/3.5.1/src/zope/traversing/api.py
  D   zope.traversing/tags/3.5.1/src/zope/traversing/browser/configure.zcml
  A   zope.traversing/tags/3.5.1/src/zope/traversing/browser/configure.zcml
  D   zope.traversing/tags/3.5.1/src/zope/traversing/configure.zcml
  A   zope.traversing/tags/3.5.1/src/zope/traversing/configure.zcml
  D   zope.traversing/tags/3.5.1/src/zope/traversing/interfaces.py
  A   zope.traversing/tags/3.5.1/src/zope/traversing/interfaces.py
  D   zope.traversing/tags/3.5.1/src/zope/traversing/namespace.py
  A   zope.traversing/tags/3.5.1/src/zope/traversing/namespace.py
  D   zope.traversing/tags/3.5.1/src/zope/traversing/testing.py
  A   zope.traversing/tags/3.5.1/src/zope/traversing/testing.py
  D   zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_conveniencefunctions.py
  A   zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_conveniencefunctions.py
  D   zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_physicallocationadapters.py
  A   zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_physicallocationadapters.py
  D   zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_skin.py
  A   zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_skin.py
  D   zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_traverser.py
  A   zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_traverser.py

-=-
Deleted: zope.traversing/tags/3.5.1/CHANGES.txt
===================================================================
--- zope.traversing/trunk/CHANGES.txt	2009-02-02 12:05:48 UTC (rev 95959)
+++ zope.traversing/tags/3.5.1/CHANGES.txt	2009-02-02 12:25:12 UTC (rev 95965)
@@ -1,82 +0,0 @@
-=======
-Changes
-=======
-
-3.5.1 (unreleased)
-------------------
-
-- The ``RootPhysicallyLocatable`` adapter has been superseded by the
-  refactored ``zope.location.traversing.LocationPhysicallyLocatable``
-  that we depend on since 3.5.0a4.
-  Remove the adapter and its registration, and making its import place
-  pointing to ``zope.location.traversing.LocationPhysicallyLocatable``
-  to maintain backward-compatibility.
-
-- Use direct imports instead of compatibility ones for things that were
-  moved to ``zope.location``.
-
-- Remove the ``zope.traversing.interfaces.INamespaceHandler`` interface,
-  as it seems not to be used for years.
-
-3.5.0 (2009-01-31)
-------------------
-
-- Use zope.container instead of zope.app.container.
-
-- Use zope.site instead of zope.app.folder in the unit tests.
-
-- Reduced, but did not eliminate, test dependencies on zope.app.component.
-
-3.5.0a4 (2008-08-01)
---------------------
-
-- Reverse dependencies between zope.location and zope.traversing.
-
-- Updated (test) dependencies and tests to expect and work with a spec
-  compliant TAL interpreter as available in zope.tal >= 3.5.0.
-- Fixed deprecation warning caused by using an old module name for
-  ZopeSecurityPolicy in ftesting.zcml
-- Made sure traversing doesn't raise an TypeError but a TraversalError when the
-  traversal step before yielded a string.
-
-
-3.5.0a3 (2007-12-28)
---------------------
-
-- backed out the controversial `++skin++` traverser for XML-RPC.
-
-
-3.5.0a2 (2007-11-28)
---------------------
-
-- ported 3.4.1a1 to trunk
-
-  - Do not use unicode strings to set the application server in the virtual
-    host namespace. This caused absolute_url to create unicode URL's.
-
-- Added a traverer for ++skin++ for XMLRPC skins (IXMLRPCSkinType). This also
-  means that the normal ++skin++ namespace handler is only bound to
-  IBrowserRequest. 
-
-- Resolved the dependency on zope.app.applicationcontrol by importing the
-  application controller only if the package is available.
-
-
-3.4.1a1 (2007-11-13)
---------------------
-
-Do not use unicode strings to set the application server in the virtual host
-namespace. This caused absolute_url to create unicode URL's.
-
-
-3.4.0 (2007-09-29)
-------------------
-
-No further changes since 3.4.0a1.
-
-3.4.0a1 (2007-04-22)
---------------------
-
-Initial release as a separate project, corresponds to zope.traversing
-from Zope 3.4.0a1
-

Copied: zope.traversing/tags/3.5.1/CHANGES.txt (from rev 95964, zope.traversing/trunk/CHANGES.txt)
===================================================================
--- zope.traversing/tags/3.5.1/CHANGES.txt	                        (rev 0)
+++ zope.traversing/tags/3.5.1/CHANGES.txt	2009-02-02 12:25:12 UTC (rev 95965)
@@ -0,0 +1,89 @@
+=======
+Changes
+=======
+
+3.5.1 (2009-02-02)
+------------------
+
+- The ``RootPhysicallyLocatable`` adapter has been superseded by the
+  refactored ``zope.location.traversing.LocationPhysicallyLocatable``
+  that we depend on since 3.5.0a4.
+
+  Remove the adapter and its registration, and making its import place
+  pointing to ``zope.location.traversing.LocationPhysicallyLocatable``
+  to maintain backward-compatibility.
+
+  This also fixes a bug introduced in version 3.5.0a4 when trying to
+  call ``getParents`` function for the root object.
+
+- Use direct imports instead of compatibility ones for things that were
+  moved to ``zope.location``.
+
+- Remove the ``zope.traversing.interfaces.INamespaceHandler`` interface,
+  as it seems not to be used for years.
+
+- Change package's mailing list address to zope-dev at zope.org instead
+  of retired zope3-dev at zope.org
+
+3.5.0 (2009-01-31)
+------------------
+
+- Use zope.container instead of zope.app.container.
+
+- Use zope.site instead of zope.app.folder in the unit tests.
+
+- Reduced, but did not eliminate, test dependencies on zope.app.component.
+
+3.5.0a4 (2008-08-01)
+--------------------
+
+- Reverse dependencies between zope.location and zope.traversing.
+
+- Updated (test) dependencies and tests to expect and work with a spec
+  compliant TAL interpreter as available in zope.tal >= 3.5.0.
+- Fixed deprecation warning caused by using an old module name for
+  ZopeSecurityPolicy in ftesting.zcml
+- Made sure traversing doesn't raise an TypeError but a TraversalError when the
+  traversal step before yielded a string.
+
+
+3.5.0a3 (2007-12-28)
+--------------------
+
+- backed out the controversial `++skin++` traverser for XML-RPC.
+
+
+3.5.0a2 (2007-11-28)
+--------------------
+
+- ported 3.4.1a1 to trunk
+
+  - Do not use unicode strings to set the application server in the virtual
+    host namespace. This caused absolute_url to create unicode URL's.
+
+- Added a traverer for ++skin++ for XMLRPC skins (IXMLRPCSkinType). This also
+  means that the normal ++skin++ namespace handler is only bound to
+  IBrowserRequest. 
+
+- Resolved the dependency on zope.app.applicationcontrol by importing the
+  application controller only if the package is available.
+
+
+3.4.1a1 (2007-11-13)
+--------------------
+
+Do not use unicode strings to set the application server in the virtual host
+namespace. This caused absolute_url to create unicode URL's.
+
+
+3.4.0 (2007-09-29)
+------------------
+
+No further changes since 3.4.0a1.
+
+3.4.0a1 (2007-04-22)
+--------------------
+
+Initial release as a separate project, corresponds to zope.traversing
+from Zope 3.4.0a1
+

Deleted: zope.traversing/tags/3.5.1/buildout.cfg
===================================================================
--- zope.traversing/trunk/buildout.cfg	2009-02-02 12:05:48 UTC (rev 95959)
+++ zope.traversing/tags/3.5.1/buildout.cfg	2009-02-02 12:25:12 UTC (rev 95965)
@@ -1,18 +0,0 @@
-[buildout]
-develop = . ../zope.location
-parts = test coverage-test coverage-report
-
-[test]
-recipe = zc.recipe.testrunner
-eggs = zope.traversing [test]
-
-[coverage-test]
-recipe = zc.recipe.testrunner
-eggs = zope.traversing [test]
-defaults = ['--coverage', '../../coverage']
-
-[coverage-report]
-recipe = zc.recipe.egg
-eggs = z3c.coverage
-scripts = coverage=coverage-report
-arguments = ('coverage', 'coverage/report')

Copied: zope.traversing/tags/3.5.1/buildout.cfg (from rev 95963, zope.traversing/trunk/buildout.cfg)
===================================================================
--- zope.traversing/tags/3.5.1/buildout.cfg	                        (rev 0)
+++ zope.traversing/tags/3.5.1/buildout.cfg	2009-02-02 12:25:12 UTC (rev 95965)
@@ -0,0 +1,18 @@
+[buildout]
+develop = .
+parts = test coverage-test coverage-report
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = zope.traversing [test]
+
+[coverage-test]
+recipe = zc.recipe.testrunner
+eggs = zope.traversing [test]
+defaults = ['--coverage', '../../coverage']
+
+[coverage-report]
+recipe = zc.recipe.egg
+eggs = z3c.coverage
+scripts = coverage=coverage-report
+arguments = ('coverage', 'coverage/report')

Deleted: zope.traversing/tags/3.5.1/setup.py
===================================================================
--- zope.traversing/trunk/setup.py	2009-02-02 12:05:48 UTC (rev 95959)
+++ zope.traversing/tags/3.5.1/setup.py	2009-02-02 12:25:12 UTC (rev 95965)
@@ -1,60 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2006 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Setup for zope.traversing package
-
-$Id$
-"""
-from setuptools import setup, find_packages
-
-long_description = (open('README.txt').read() +
-                    '\n\n' +
-                    open('CHANGES.txt').read())
-
-setup(name='zope.traversing',
-      version = '3.5.1dev',
-      url='http://pypi.python.org/pypi/zope.traversing',
-      license='ZPL 2.1',
-      author='Zope Corporation and Contributors',
-      author_email='zope3-dev at zope.org',
-      description="Resolving paths in the object hierarchy",
-      long_description=long_description,
-
-      packages=find_packages('src'),
-      package_dir = {'': 'src'},
-      namespace_packages=['zope',],
-      extras_require = dict(test=['zope.app.testing',
-                                  'zope.app.securitypolicy',
-                                  'zope.app.zcmlfiles',
-                                  'zope.app.zptpage',
-                                  'zope.app.applicationcontrol',
-                                  'zope.app.component',
-                                  'zope.container',
-                                  'zope.site',
-                                  # The tests expect a spec-compliant TAL
-                                  # interpreter as found in zope.tal 3.5.0
-                                  'zope.tal >= 3.5.0',
-                                  ]),
-      install_requires=['setuptools',
-                        'zope.component',
-                        'zope.i18n',
-                        'zope.i18nmessageid',
-                        'zope.interface',
-                        'zope.proxy',
-                        'zope.publisher',
-                        'zope.security',
-                        'zope.location>=3.5.1',
-                        ],
-      include_package_data = True,
-      zip_safe = False,
-      )

Copied: zope.traversing/tags/3.5.1/setup.py (from rev 95964, zope.traversing/trunk/setup.py)
===================================================================
--- zope.traversing/tags/3.5.1/setup.py	                        (rev 0)
+++ zope.traversing/tags/3.5.1/setup.py	2009-02-02 12:25:12 UTC (rev 95965)
@@ -0,0 +1,60 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Setup for zope.traversing package
+
+$Id$
+"""
+from setuptools import setup, find_packages
+
+long_description = (open('README.txt').read() +
+                    '\n\n' +
+                    open('CHANGES.txt').read())
+
+setup(name='zope.traversing',
+      version = '3.5.1',
+      url='http://pypi.python.org/pypi/zope.traversing',
+      license='ZPL 2.1',
+      author='Zope Corporation and Contributors',
+      author_email='zope-dev at zope.org',
+      description="Resolving paths in the object hierarchy",
+      long_description=long_description,
+
+      packages=find_packages('src'),
+      package_dir = {'': 'src'},
+      namespace_packages=['zope',],
+      extras_require = dict(test=['zope.app.testing',
+                                  'zope.app.securitypolicy',
+                                  'zope.app.zcmlfiles',
+                                  'zope.app.zptpage',
+                                  'zope.app.applicationcontrol',
+                                  'zope.app.component',
+                                  'zope.container',
+                                  'zope.site',
+                                  # The tests expect a spec-compliant TAL
+                                  # interpreter as found in zope.tal 3.5.0
+                                  'zope.tal >= 3.5.0',
+                                  ]),
+      install_requires=['setuptools',
+                        'zope.component',
+                        'zope.i18n',
+                        'zope.i18nmessageid',
+                        'zope.interface',
+                        'zope.proxy',
+                        'zope.publisher',
+                        'zope.security',
+                        'zope.location>=3.5.1',
+                        ],
+      include_package_data = True,
+      zip_safe = False,
+      )

Deleted: zope.traversing/tags/3.5.1/src/zope/traversing/DEPENDENCIES.cfg
===================================================================
--- zope.traversing/trunk/src/zope/traversing/DEPENDENCIES.cfg	2009-02-02 06:01:56 UTC (rev 95956)
+++ zope.traversing/tags/3.5.1/src/zope/traversing/DEPENDENCIES.cfg	2009-02-02 12:25:12 UTC (rev 95965)
@@ -1,14 +0,0 @@
-# zope.annotation only for testing
-zope.annotation
-# TODO: minimize zope.app
-zope.app
-zope.component
-zope.i18n
-zope.i18nmessageid
-zope.interface
-# zope.location only for testing
-zope.location
-zope.testing
-zope.proxy
-zope.publisher
-zope.security

Deleted: zope.traversing/tags/3.5.1/src/zope/traversing/adapters.py
===================================================================
--- zope.traversing/trunk/src/zope/traversing/adapters.py	2009-02-02 06:01:56 UTC (rev 95956)
+++ zope.traversing/tags/3.5.1/src/zope/traversing/adapters.py	2009-02-02 12:25:12 UTC (rev 95965)
@@ -1,171 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Adapters for the traversing mechanism
-
-$Id$
-"""
-from types import StringTypes
-
-import zope.interface
-import zope.component
-
-from zope.traversing.interfaces import TraversalError
-from zope.traversing.interfaces import IPhysicallyLocatable
-from zope.traversing.interfaces import IContainmentRoot
-from zope.traversing.interfaces import ITraverser, ITraversable
-
-from zope.traversing.namespace import namespaceLookup
-from zope.traversing.namespace import UnexpectedParameters
-from zope.traversing.namespace import nsParse
-
-_marker = object()  # opaque marker that doesn't get security proxied
-
-class DefaultTraversable(object):
-    """Traverses objects via attribute and item lookup"""
-    zope.interface.implements(ITraversable)
-
-    def __init__(self, subject):
-        self._subject = subject
-
-    def traverse(self, name, furtherPath):
-        subject = self._subject
-        __traceback_info__ = (subject, name, furtherPath)
-        attr = getattr(subject, name, _marker)
-        if attr is not _marker:
-            return attr
-        if hasattr(subject, '__getitem__'):
-            try:
-                return subject[name]
-            except (KeyError, TypeError):
-                pass
-        raise TraversalError(subject, name)
-
-class RootPhysicallyLocatable(object):
-    __doc__ = IPhysicallyLocatable.__doc__
-
-    zope.component.adapts(IContainmentRoot)
-    zope.interface.implements(IPhysicallyLocatable)
-
-    def __init__(self, context):
-        self.context = context
-
-    def getPath(self):
-        "See IPhysicallyLocatable"
-        return u'/'
-
-    def getRoot(self):
-        "See IPhysicallyLocatable"
-        return self.context
-
-    def getName(self):
-        "See IPhysicallyLocatable"
-        return u''
-
-    def getNearestSite(self):
-        "See IPhysicallyLocatable"
-        return self.context
-
-
-class Traverser(object):
-    """Provide traverse features"""
-
-    zope.interface.implements(ITraverser)
-
-    # This adapter can be used for any object.
-
-    def __init__(self, wrapper):
-        self.context = wrapper
-
-    def traverse(self, path, default=_marker, request=None):
-        if not path:
-            return self.context
-
-        if isinstance(path, StringTypes):
-            path = path.split('/')
-            if len(path) > 1 and not path[-1]:
-                # Remove trailing slash
-                path.pop()
-        else:
-            path = list(path)
-
-        path.reverse()
-        pop = path.pop
-
-        curr = self.context
-        if not path[-1]:
-            # Start at the root
-            pop()
-            curr = IPhysicallyLocatable(self.context).getRoot()
-        try:
-            while path:
-                name = pop()
-                curr = traversePathElement(curr, name, path, request=request)
-
-            return curr
-        except TraversalError:
-            if default == _marker:
-                raise
-            return default
-
-
-def traversePathElement(obj, name, further_path, default=_marker,
-                        traversable=None, request=None):
-    """Traverse a single step 'name' relative to the given object.
-
-    'name' must be a string. '.' and '..' are treated specially, as well as
-    names starting with '@' or '+'. Otherwise 'name' will be treated as a
-    single path segment.
-
-    'further_path' is a list of names still to be traversed.  This method
-    is allowed to change the contents of 'further_path'.
-
-    You can explicitly pass in an ITraversable as the 'traversable'
-    argument. If you do not, the given object will be adapted to ITraversable.
-
-    'request' is passed in when traversing from presentation code. This
-    allows paths like @@foo to work.
-
-    Raises TraversalError if path cannot be found and 'default' was
-    not provided.
-
-    """
-    __traceback_info__ = (obj, name)
-
-    if name == '.':
-        return obj
-
-    if name == '..':
-        return obj.__parent__
- 
-    if name and name[:1] in '@+':
-        ns, nm = nsParse(name)
-        if ns:
-            return namespaceLookup(ns, nm, obj, request)
-    else:
-        nm = name
-
-    if traversable is None:
-        traversable = ITraversable(obj, None)
-        if traversable is None:
-            raise TraversalError('No traversable adapter found', obj)
-
-    try:
-        return traversable.traverse(nm, further_path)
-    except TraversalError:
-        if default is not _marker:
-            return default
-        else:
-            raise
-
-    return obj

Copied: zope.traversing/tags/3.5.1/src/zope/traversing/adapters.py (from rev 95959, zope.traversing/trunk/src/zope/traversing/adapters.py)
===================================================================
--- zope.traversing/tags/3.5.1/src/zope/traversing/adapters.py	                        (rev 0)
+++ zope.traversing/tags/3.5.1/src/zope/traversing/adapters.py	2009-02-02 12:25:12 UTC (rev 95965)
@@ -0,0 +1,148 @@
+##############################################################################
+#
+# Copyright (c) 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Adapters for the traversing mechanism
+
+$Id$
+"""
+from types import StringTypes
+
+import zope.interface
+import zope.component
+
+from zope.location.interfaces \
+    import ILocationInfo, LocationError, ITraverser
+from zope.traversing.interfaces import ITraversable
+
+from zope.traversing.namespace import namespaceLookup
+from zope.traversing.namespace import UnexpectedParameters
+from zope.traversing.namespace import nsParse
+
+# BBB: LocationPhysicallyLocatable does the same thing for root object
+# as the RootPhysicallyLocatable that used to be defined here.
+from zope.location.traversing import LocationPhysicallyLocatable as RootPhysicallyLocatable
+
+_marker = object()  # opaque marker that doesn't get security proxied
+
+class DefaultTraversable(object):
+    """Traverses objects via attribute and item lookup"""
+    zope.interface.implements(ITraversable)
+
+    def __init__(self, subject):
+        self._subject = subject
+
+    def traverse(self, name, furtherPath):
+        subject = self._subject
+        __traceback_info__ = (subject, name, furtherPath)
+        attr = getattr(subject, name, _marker)
+        if attr is not _marker:
+            return attr
+        if hasattr(subject, '__getitem__'):
+            try:
+                return subject[name]
+            except (KeyError, TypeError):
+                pass
+        raise LocationError(subject, name)
+
+class Traverser(object):
+    """Provide traverse features"""
+
+    zope.interface.implements(ITraverser)
+
+    # This adapter can be used for any object.
+
+    def __init__(self, wrapper):
+        self.context = wrapper
+
+    def traverse(self, path, default=_marker, request=None):
+        if not path:
+            return self.context
+
+        if isinstance(path, StringTypes):
+            path = path.split('/')
+            if len(path) > 1 and not path[-1]:
+                # Remove trailing slash
+                path.pop()
+        else:
+            path = list(path)
+
+        path.reverse()
+        pop = path.pop
+
+        curr = self.context
+        if not path[-1]:
+            # Start at the root
+            pop()
+            curr = ILocationInfo(self.context).getRoot()
+        try:
+            while path:
+                name = pop()
+                curr = traversePathElement(curr, name, path, request=request)
+
+            return curr
+        except LocationError:
+            if default == _marker:
+                raise
+            return default
+
+
+def traversePathElement(obj, name, further_path, default=_marker,
+                        traversable=None, request=None):
+    """Traverse a single step 'name' relative to the given object.
+
+    'name' must be a string. '.' and '..' are treated specially, as well as
+    names starting with '@' or '+'. Otherwise 'name' will be treated as a
+    single path segment.
+
+    'further_path' is a list of names still to be traversed.  This method
+    is allowed to change the contents of 'further_path'.
+
+    You can explicitly pass in an ITraversable as the 'traversable'
+    argument. If you do not, the given object will be adapted to ITraversable.
+
+    'request' is passed in when traversing from presentation code. This
+    allows paths like @@foo to work.
+
+    Raises LocationError if path cannot be found and 'default' was
+    not provided.
+
+    """
+    __traceback_info__ = (obj, name)
+
+    if name == '.':
+        return obj
+
+    if name == '..':
+        return obj.__parent__
+ 
+    if name and name[:1] in '@+':
+        ns, nm = nsParse(name)
+        if ns:
+            return namespaceLookup(ns, nm, obj, request)
+    else:
+        nm = name
+
+    if traversable is None:
+        traversable = ITraversable(obj, None)
+        if traversable is None:
+            raise LocationError('No traversable adapter found', obj)
+
+    try:
+        return traversable.traverse(nm, further_path)
+    except LocationError:
+        if default is not _marker:
+            return default
+        else:
+            raise
+
+    return obj

Deleted: zope.traversing/tags/3.5.1/src/zope/traversing/api.py
===================================================================
--- zope.traversing/trunk/src/zope/traversing/api.py	2009-02-02 06:01:56 UTC (rev 95956)
+++ zope.traversing/tags/3.5.1/src/zope/traversing/api.py	2009-02-02 12:25:12 UTC (rev 95965)
@@ -1,209 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Convenience functions for traversing the object tree.
-
-$Id$
-"""
-from zope.interface import moduleProvides
-from zope.traversing.interfaces import IContainmentRoot, ITraversalAPI
-from zope.traversing.interfaces import ITraverser, IPhysicallyLocatable
-from zope.traversing.interfaces import TraversalError
-
-moduleProvides(ITraversalAPI)
-__all__ = tuple(ITraversalAPI)
-
-_marker = object()
-
-def joinPath(path, *args):
-    """Join the given relative paths to the given path.
-
-    Returns a unicode path.
-
-    The path should be well-formed, and not end in a '/' unless it is
-    the root path. It can be either a string (ascii only) or unicode.
-    The positional arguments are relative paths to be added to the
-    path as new path segments.  The path may be absolute or relative.
-
-    A segment may not start with a '/' because that would be confused
-    with an absolute path. A segment may not end with a '/' because we
-    do not allow '/' at the end of relative paths.  A segment may
-    consist of . or .. to mean "the same place", or "the parent path"
-    respectively. A '.' should be removed and a '..' should cause the
-    segment to the left to be removed.  joinPath('/', '..') should
-    raise an exception.
-    """
-
-    if not args:
-        # Concatenating u'' is much quicker than unicode(path)
-        return u'' + path
-    if path != '/' and path.endswith('/'):
-        raise ValueError('path must not end with a "/": %s' % path)
-    if path != '/':
-        path += u'/'
-    for arg in args:
-        if arg.startswith('/') or arg.endswith('/'):
-            raise ValueError("Leading or trailing slashes in path elements")
-    return _normalizePath(path + u'/'.join(args))
-
-def getPath(obj):
-    """Returns a string representing the physical path to the object.
-    """
-    return IPhysicallyLocatable(obj).getPath()
-
-def getRoot(obj):
-    """Returns the root of the traversal for the given object.
-    """
-    return IPhysicallyLocatable(obj).getRoot()
-
-def traverse(object, path, default=_marker, request=None):
-    """Traverse 'path' relative to the given object.
-
-    'path' is a string with path segments separated by '/'.
-
-    'request' is passed in when traversing from presentation code. This
-    allows paths like @@foo to work.
-
-    Raises TraversalError if path cannot be found
-
-    Note: calling traverse with a path argument taken from an untrusted
-          source, such as an HTTP request form variable, is a bad idea.
-          It could allow a maliciously constructed request to call
-          code unexpectedly.
-          Consider using traverseName instead.
-    """
-    traverser = ITraverser(object)
-    if default is _marker:
-        return traverser.traverse(path, request=request)
-    else:
-        return traverser.traverse(path, default=default, request=request)
-
-def traverseName(obj, name, default=_marker, traversable=None, request=None):
-    """Traverse a single step 'name' relative to the given object.
-
-    'name' must be a string. '.' and '..' are treated specially, as well as
-    names starting with '@' or '+'. Otherwise 'name' will be treated as a
-    single path segment.
-
-    You can explicitly pass in an ITraversable as the 'traversable'
-    argument. If you do not, the given object will be adapted to ITraversable.
-
-    'request' is passed in when traversing from presentation code. This
-    allows paths like @@foo to work.
-
-    Raises TraversalError if path cannot be found and 'default' was
-    not provided.
-
-    """
-    further_path = []
-    if default is _marker:
-        obj = traversePathElement(obj, name, further_path,
-                                  traversable=traversable, request=request)
-    else:
-        obj = traversePathElement(obj, name, further_path, default=default,
-                                  traversable=traversable, request=request)
-    if further_path:
-        raise NotImplementedError('further_path returned from traverse')
-    else:
-        return obj
-
-def getName(obj):
-    """Get the name an object was traversed via
-    """
-    return IPhysicallyLocatable(obj).getName()
-
-def getParent(obj):
-    """Returns the container the object was traversed via.
-
-    Returns None if the object is a containment root.
-    Raises TypeError if the object doesn't have enough context to get the
-    parent.
-    """
-    
-    if IContainmentRoot.providedBy(obj):
-        return None
-    
-    parent = getattr(obj, '__parent__', None)
-    if parent is not None:
-        return parent
-
-    raise TypeError("Not enough context information to get parent", obj)
-
-
-
-def getParents(obj):
-    """Returns a list starting with the given object's parent followed by
-    each of its parents.
-
-    Raises a TypeError if the context doesn't go all the way down to
-    a containment root.
-    """
-    return IPhysicallyLocatable(obj).getParents()
-
-
-def _normalizePath(path):
-    """Normalize a path by resolving '.' and '..' path elements."""
-
-    # Special case for the root path.
-    if path == u'/':
-        return path
-
-    new_segments = []
-    prefix = u''
-    if path.startswith('/'):
-        prefix = u'/'
-        path = path[1:]
-
-    for segment in path.split(u'/'):
-        if segment == u'.':
-            continue
-        if segment == u'..':
-            new_segments.pop()  # raises IndexError if there is nothing to pop
-            continue
-        if not segment:
-            raise ValueError('path must not contain empty segments: %s'
-                             % path)
-        new_segments.append(segment)
-
-    return prefix + u'/'.join(new_segments)
-
-def canonicalPath(path_or_object):
-    """Returns a canonical absolute unicode path for the given path or object.
-
-    Resolves segments that are '.' or '..'.
-
-    Raises ValueError if a badly formed path is given.
-    """
-    if isinstance(path_or_object, (str, unicode)):
-        path = path_or_object
-        if not path:
-            raise ValueError("path must be non-empty: %s" % path)
-    else:
-        path = getPath(path_or_object)
-
-    path = u'' + path
-
-    # Special case for the root path.
-    if path == u'/':
-        return path
-
-    if path[0] != u'/':
-        raise ValueError('canonical path must start with a "/": %s' % path)
-    if path[-1] == u'/':
-        raise ValueError('path must not end with a "/": %s' % path)
-
-    # Break path into segments. Process '.' and '..' segments.
-    return _normalizePath(path)
-
-# import this down here to avoid circular imports
-from zope.traversing.adapters import traversePathElement

Copied: zope.traversing/tags/3.5.1/src/zope/traversing/api.py (from rev 95959, zope.traversing/trunk/src/zope/traversing/api.py)
===================================================================
--- zope.traversing/tags/3.5.1/src/zope/traversing/api.py	                        (rev 0)
+++ zope.traversing/tags/3.5.1/src/zope/traversing/api.py	2009-02-02 12:25:12 UTC (rev 95965)
@@ -0,0 +1,209 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Convenience functions for traversing the object tree.
+
+$Id$
+"""
+from zope.interface import moduleProvides
+from zope.location.interfaces \
+    import ILocationInfo, IRoot, LocationError, ITraverser
+from zope.traversing.interfaces import ITraversalAPI
+
+moduleProvides(ITraversalAPI)
+__all__ = tuple(ITraversalAPI)
+
+_marker = object()
+
+def joinPath(path, *args):
+    """Join the given relative paths to the given path.
+
+    Returns a unicode path.
+
+    The path should be well-formed, and not end in a '/' unless it is
+    the root path. It can be either a string (ascii only) or unicode.
+    The positional arguments are relative paths to be added to the
+    path as new path segments.  The path may be absolute or relative.
+
+    A segment may not start with a '/' because that would be confused
+    with an absolute path. A segment may not end with a '/' because we
+    do not allow '/' at the end of relative paths.  A segment may
+    consist of . or .. to mean "the same place", or "the parent path"
+    respectively. A '.' should be removed and a '..' should cause the
+    segment to the left to be removed.  joinPath('/', '..') should
+    raise an exception.
+    """
+
+    if not args:
+        # Concatenating u'' is much quicker than unicode(path)
+        return u'' + path
+    if path != '/' and path.endswith('/'):
+        raise ValueError('path must not end with a "/": %s' % path)
+    if path != '/':
+        path += u'/'
+    for arg in args:
+        if arg.startswith('/') or arg.endswith('/'):
+            raise ValueError("Leading or trailing slashes in path elements")
+    return _normalizePath(path + u'/'.join(args))
+
+def getPath(obj):
+    """Returns a string representing the physical path to the object.
+    """
+    return ILocationInfo(obj).getPath()
+
+def getRoot(obj):
+    """Returns the root of the traversal for the given object.
+    """
+    return ILocationInfo(obj).getRoot()
+
+def traverse(object, path, default=_marker, request=None):
+    """Traverse 'path' relative to the given object.
+
+    'path' is a string with path segments separated by '/'.
+
+    'request' is passed in when traversing from presentation code. This
+    allows paths like @@foo to work.
+
+    Raises LocationError if path cannot be found
+
+    Note: calling traverse with a path argument taken from an untrusted
+          source, such as an HTTP request form variable, is a bad idea.
+          It could allow a maliciously constructed request to call
+          code unexpectedly.
+          Consider using traverseName instead.
+    """
+    traverser = ITraverser(object)
+    if default is _marker:
+        return traverser.traverse(path, request=request)
+    else:
+        return traverser.traverse(path, default=default, request=request)
+
+def traverseName(obj, name, default=_marker, traversable=None, request=None):
+    """Traverse a single step 'name' relative to the given object.
+
+    'name' must be a string. '.' and '..' are treated specially, as well as
+    names starting with '@' or '+'. Otherwise 'name' will be treated as a
+    single path segment.
+
+    You can explicitly pass in an ITraversable as the 'traversable'
+    argument. If you do not, the given object will be adapted to ITraversable.
+
+    'request' is passed in when traversing from presentation code. This
+    allows paths like @@foo to work.
+
+    Raises LocationError if path cannot be found and 'default' was
+    not provided.
+
+    """
+    further_path = []
+    if default is _marker:
+        obj = traversePathElement(obj, name, further_path,
+                                  traversable=traversable, request=request)
+    else:
+        obj = traversePathElement(obj, name, further_path, default=default,
+                                  traversable=traversable, request=request)
+    if further_path:
+        raise NotImplementedError('further_path returned from traverse')
+    else:
+        return obj
+
+def getName(obj):
+    """Get the name an object was traversed via
+    """
+    return ILocationInfo(obj).getName()
+
+def getParent(obj):
+    """Returns the container the object was traversed via.
+
+    Returns None if the object is a containment root.
+    Raises TypeError if the object doesn't have enough context to get the
+    parent.
+    """
+    
+    if IRoot.providedBy(obj):
+        return None
+    
+    parent = getattr(obj, '__parent__', None)
+    if parent is not None:
+        return parent
+
+    raise TypeError("Not enough context information to get parent", obj)
+
+
+
+def getParents(obj):
+    """Returns a list starting with the given object's parent followed by
+    each of its parents.
+
+    Raises a TypeError if the context doesn't go all the way down to
+    a containment root.
+    """
+    return ILocationInfo(obj).getParents()
+
+
+def _normalizePath(path):
+    """Normalize a path by resolving '.' and '..' path elements."""
+
+    # Special case for the root path.
+    if path == u'/':
+        return path
+
+    new_segments = []
+    prefix = u''
+    if path.startswith('/'):
+        prefix = u'/'
+        path = path[1:]
+
+    for segment in path.split(u'/'):
+        if segment == u'.':
+            continue
+        if segment == u'..':
+            new_segments.pop()  # raises IndexError if there is nothing to pop
+            continue
+        if not segment:
+            raise ValueError('path must not contain empty segments: %s'
+                             % path)
+        new_segments.append(segment)
+
+    return prefix + u'/'.join(new_segments)
+
+def canonicalPath(path_or_object):
+    """Returns a canonical absolute unicode path for the given path or object.
+
+    Resolves segments that are '.' or '..'.
+
+    Raises ValueError if a badly formed path is given.
+    """
+    if isinstance(path_or_object, (str, unicode)):
+        path = path_or_object
+        if not path:
+            raise ValueError("path must be non-empty: %s" % path)
+    else:
+        path = getPath(path_or_object)
+
+    path = u'' + path
+
+    # Special case for the root path.
+    if path == u'/':
+        return path
+
+    if path[0] != u'/':
+        raise ValueError('canonical path must start with a "/": %s' % path)
+    if path[-1] == u'/':
+        raise ValueError('path must not end with a "/": %s' % path)
+
+    # Break path into segments. Process '.' and '..' segments.
+    return _normalizePath(path)
+
+# import this down here to avoid circular imports
+from zope.traversing.adapters import traversePathElement

Deleted: zope.traversing/tags/3.5.1/src/zope/traversing/browser/configure.zcml
===================================================================
--- zope.traversing/trunk/src/zope/traversing/browser/configure.zcml	2009-02-02 06:01:56 UTC (rev 95956)
+++ zope.traversing/tags/3.5.1/src/zope/traversing/browser/configure.zcml	2009-02-02 12:25:12 UTC (rev 95965)
@@ -1,55 +0,0 @@
-<configure
-    xmlns="http://namespaces.zope.org/zope"
-    xmlns:browser="http://namespaces.zope.org/browser">
-
-  <view
-      for="*"
-      name="absolute_url"
-      factory=".AbsoluteURL"
-      type="zope.publisher.interfaces.http.IHTTPRequest"
-      permission="zope.Public"
-      allowed_interface=".interfaces.IAbsoluteURL"
-      />
-      
-  <view
-      for="*"
-      factory=".AbsoluteURL"
-      type="zope.publisher.interfaces.http.IHTTPRequest"
-      permission="zope.Public"
-      provides=".interfaces.IAbsoluteURL"
-      />
-
-  <view
-      for="zope.traversing.interfaces.IContainmentRoot"
-      name="absolute_url"
-      factory=".SiteAbsoluteURL"
-      type="zope.publisher.interfaces.http.IHTTPRequest"
-      permission="zope.Public"
-      allowed_interface=".interfaces.IAbsoluteURL"
-      />
-      
-  <view
-      for="zope.traversing.interfaces.IContainmentRoot"
-      factory=".SiteAbsoluteURL"
-      type="zope.publisher.interfaces.http.IHTTPRequest"
-      permission="zope.Public"
-      provides=".interfaces.IAbsoluteURL"
-      />
-
-  <browser:page
-      for="*"
-      name="absolute_url"
-      class=".AbsoluteURL"
-      permission="zope.Public"
-      allowed_interface=".interfaces.IAbsoluteURL"
-      />
-
-  <browser:page
-      for="zope.traversing.interfaces.IContainmentRoot"
-      name="absolute_url"
-      class=".SiteAbsoluteURL"
-      permission="zope.Public"
-      allowed_interface=".interfaces.IAbsoluteURL"
-      />
-
-</configure>

Copied: zope.traversing/tags/3.5.1/src/zope/traversing/browser/configure.zcml (from rev 95959, zope.traversing/trunk/src/zope/traversing/browser/configure.zcml)
===================================================================
--- zope.traversing/tags/3.5.1/src/zope/traversing/browser/configure.zcml	                        (rev 0)
+++ zope.traversing/tags/3.5.1/src/zope/traversing/browser/configure.zcml	2009-02-02 12:25:12 UTC (rev 95965)
@@ -0,0 +1,55 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:browser="http://namespaces.zope.org/browser">
+
+  <view
+      for="*"
+      name="absolute_url"
+      factory=".AbsoluteURL"
+      type="zope.publisher.interfaces.http.IHTTPRequest"
+      permission="zope.Public"
+      allowed_interface=".interfaces.IAbsoluteURL"
+      />
+      
+  <view
+      for="*"
+      factory=".AbsoluteURL"
+      type="zope.publisher.interfaces.http.IHTTPRequest"
+      permission="zope.Public"
+      provides=".interfaces.IAbsoluteURL"
+      />
+
+  <view
+      for="zope.location.interfaces.IRoot"
+      name="absolute_url"
+      factory=".SiteAbsoluteURL"
+      type="zope.publisher.interfaces.http.IHTTPRequest"
+      permission="zope.Public"
+      allowed_interface=".interfaces.IAbsoluteURL"
+      />
+      
+  <view
+      for="zope.location.interfaces.IRoot"
+      factory=".SiteAbsoluteURL"
+      type="zope.publisher.interfaces.http.IHTTPRequest"
+      permission="zope.Public"
+      provides=".interfaces.IAbsoluteURL"
+      />
+
+  <browser:page
+      for="*"
+      name="absolute_url"
+      class=".AbsoluteURL"
+      permission="zope.Public"
+      allowed_interface=".interfaces.IAbsoluteURL"
+      />
+
+  <browser:page
+      for="zope.location.interfaces.IRoot"
+      name="absolute_url"
+      class=".SiteAbsoluteURL"
+      permission="zope.Public"
+      allowed_interface=".interfaces.IAbsoluteURL"
+      />
+
+</configure>

Deleted: zope.traversing/tags/3.5.1/src/zope/traversing/configure.zcml
===================================================================
--- zope.traversing/trunk/src/zope/traversing/configure.zcml	2009-02-02 06:01:56 UTC (rev 95956)
+++ zope.traversing/tags/3.5.1/src/zope/traversing/configure.zcml	2009-02-02 12:25:12 UTC (rev 95965)
@@ -1,122 +0,0 @@
-<configure xmlns="http://namespaces.zope.org/zope"
-  xmlns:zcml="http://namespaces.zope.org/zcml">
-
-<adapter
-    for="*"
-    factory="zope.traversing.adapters.Traverser"
-    provides="zope.traversing.interfaces.ITraverser" />
-
-<adapter
-    for="*"
-    factory="zope.traversing.adapters.DefaultTraversable"
-    provides="zope.traversing.interfaces.ITraversable" />
-
-<adapter factory="zope.traversing.adapters.RootPhysicallyLocatable" />
-
-<adapter
-    name="etc"
-    provides="zope.traversing.interfaces.ITraversable" for="*"
-    factory="zope.traversing.namespace.etc"
-    />
-<view
-    name="etc"
-    type="zope.interface.Interface"
-    provides="zope.traversing.interfaces.ITraversable" for="*"
-    factory="zope.traversing.namespace.etc"
-    />
-
-<adapter
-    name="attribute"
-    provides="zope.traversing.interfaces.ITraversable" for="*"
-    factory="zope.traversing.namespace.attr"
-    />
-<view
-    name="attribute"
-    type="zope.interface.Interface"
-    provides="zope.traversing.interfaces.ITraversable" for="*"
-    factory="zope.traversing.namespace.attr"
-    />
-
-<adapter
-    name="adapter"
-    provides="zope.traversing.interfaces.ITraversable" for="*"
-    factory="zope.traversing.namespace.adapter"
-    />
-<view
-    name="adapter"
-    type="zope.interface.Interface"
-    provides="zope.traversing.interfaces.ITraversable" for="*"
-    factory="zope.traversing.namespace.adapter"
-    />
-
-<adapter
-    name="item"
-    provides="zope.traversing.interfaces.ITraversable" for="*"
-    factory="zope.traversing.namespace.item"
-    />
-<view
-    name="item" type="*"
-    provides="zope.traversing.interfaces.ITraversable" for="*"
-    factory="zope.traversing.namespace.item"
-    />
-
-<adapter
-    name="acquire"
-    provides="zope.traversing.interfaces.ITraversable" for="*"
-    factory="zope.traversing.namespace.acquire"
-    />
-<view
-    name="acquire" type="*"
-    provides="zope.traversing.interfaces.ITraversable" for="*"
-    factory="zope.traversing.namespace.acquire"
-    />
-
-<view
-    name="view" type="*"
-    provides="zope.traversing.interfaces.ITraversable" for="*"
-    factory="zope.traversing.namespace.view"
-    />
-
-<view
-    name="resource" type="*"
-    provides="zope.traversing.interfaces.ITraversable" for="*"
-    factory="zope.traversing.namespace.resource"
-    />
-
-<adapter
-    name="lang"
-    provides="zope.traversing.interfaces.ITraversable" for="*"
-    factory="zope.traversing.namespace.lang"
-    />
-<view
-    name="lang" type="*"
-    provides="zope.traversing.interfaces.ITraversable" for="*"
-    factory="zope.traversing.namespace.lang"
-    />
-
-<view
-    name="skin" type="*"
-    provides="zope.traversing.interfaces.ITraversable" for="*"
-    factory="zope.traversing.namespace.skin"
-    />
-
-<view
-    name="vh" type="*"
-    provides="zope.traversing.interfaces.ITraversable" for="*"
-    factory="zope.traversing.namespace.vh"
-    />
-
-<!-- The debug namespace allows acess to things that should not normally be
- visible (e.g. file system read acces).
-
- See issue 507 for the rationale of binding this to developer-mode only.
- -->
-
-<view
-    zcml:condition="have devmode"
-    name="debug" type="*"
-    provides="zope.traversing.interfaces.ITraversable" for="*"
-    factory="zope.traversing.namespace.debug"
-    />
-
-</configure>

Copied: zope.traversing/tags/3.5.1/src/zope/traversing/configure.zcml (from rev 95959, zope.traversing/trunk/src/zope/traversing/configure.zcml)
===================================================================
--- zope.traversing/tags/3.5.1/src/zope/traversing/configure.zcml	                        (rev 0)
+++ zope.traversing/tags/3.5.1/src/zope/traversing/configure.zcml	2009-02-02 12:25:12 UTC (rev 95965)
@@ -0,0 +1,120 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+  xmlns:zcml="http://namespaces.zope.org/zcml">
+
+<adapter
+    for="*"
+    factory="zope.traversing.adapters.Traverser"
+    provides="zope.location.interfaces.ITraverser" />
+
+<adapter
+    for="*"
+    factory="zope.traversing.adapters.DefaultTraversable"
+    provides="zope.traversing.interfaces.ITraversable" />
+
+<adapter
+    name="etc"
+    provides="zope.traversing.interfaces.ITraversable" for="*"
+    factory="zope.traversing.namespace.etc"
+    />
+<view
+    name="etc"
+    type="zope.interface.Interface"
+    provides="zope.traversing.interfaces.ITraversable" for="*"
+    factory="zope.traversing.namespace.etc"
+    />
+
+<adapter
+    name="attribute"
+    provides="zope.traversing.interfaces.ITraversable" for="*"
+    factory="zope.traversing.namespace.attr"
+    />
+<view
+    name="attribute"
+    type="zope.interface.Interface"
+    provides="zope.traversing.interfaces.ITraversable" for="*"
+    factory="zope.traversing.namespace.attr"
+    />
+
+<adapter
+    name="adapter"
+    provides="zope.traversing.interfaces.ITraversable" for="*"
+    factory="zope.traversing.namespace.adapter"
+    />
+<view
+    name="adapter"
+    type="zope.interface.Interface"
+    provides="zope.traversing.interfaces.ITraversable" for="*"
+    factory="zope.traversing.namespace.adapter"
+    />
+
+<adapter
+    name="item"
+    provides="zope.traversing.interfaces.ITraversable" for="*"
+    factory="zope.traversing.namespace.item"
+    />
+<view
+    name="item" type="*"
+    provides="zope.traversing.interfaces.ITraversable" for="*"
+    factory="zope.traversing.namespace.item"
+    />
+
+<adapter
+    name="acquire"
+    provides="zope.traversing.interfaces.ITraversable" for="*"
+    factory="zope.traversing.namespace.acquire"
+    />
+<view
+    name="acquire" type="*"
+    provides="zope.traversing.interfaces.ITraversable" for="*"
+    factory="zope.traversing.namespace.acquire"
+    />
+
+<view
+    name="view" type="*"
+    provides="zope.traversing.interfaces.ITraversable" for="*"
+    factory="zope.traversing.namespace.view"
+    />
+
+<view
+    name="resource" type="*"
+    provides="zope.traversing.interfaces.ITraversable" for="*"
+    factory="zope.traversing.namespace.resource"
+    />
+
+<adapter
+    name="lang"
+    provides="zope.traversing.interfaces.ITraversable" for="*"
+    factory="zope.traversing.namespace.lang"
+    />
+<view
+    name="lang" type="*"
+    provides="zope.traversing.interfaces.ITraversable" for="*"
+    factory="zope.traversing.namespace.lang"
+    />
+
+<view
+    name="skin" type="*"
+    provides="zope.traversing.interfaces.ITraversable" for="*"
+    factory="zope.traversing.namespace.skin"
+    />
+
+<view
+    name="vh" type="*"
+    provides="zope.traversing.interfaces.ITraversable" for="*"
+    factory="zope.traversing.namespace.vh"
+    />
+
+<!-- The debug namespace allows acess to things that should not normally be
+ visible (e.g. file system read acces).
+
+ See issue 507 for the rationale of binding this to developer-mode only.
+ -->
+
+<view
+    zcml:condition="have devmode"
+    name="debug" type="*"
+    provides="zope.traversing.interfaces.ITraversable" for="*"
+    factory="zope.traversing.namespace.debug"
+    />
+
+</configure>

Deleted: zope.traversing/tags/3.5.1/src/zope/traversing/interfaces.py
===================================================================
--- zope.traversing/trunk/src/zope/traversing/interfaces.py	2009-02-02 06:01:56 UTC (rev 95956)
+++ zope.traversing/tags/3.5.1/src/zope/traversing/interfaces.py	2009-02-02 12:25:12 UTC (rev 95965)
@@ -1,159 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Interfaces to do with traversing.
-
-$Id$
-"""
-
-from zope.interface import Interface
-
-# BBB: Re-import symbols to their old location.
-from zope.location.interfaces import LocationError as TraversalError
-from zope.location.interfaces import IRoot as IContainmentRoot
-from zope.location.interfaces import ILocationInfo as IPhysicallyLocatable
-from zope.location.interfaces import ITraverser
-
-
-#TODO this does not seem to be used anywhere. Remove it? --philiKON
-class INamespaceHandler(Interface):
-
-    def __call__(name, object, request):
-        """Access a name in a namespace
-
-        The name lookup usually depends on an object and/or a
-        request. If an object or request is unavailable, None will be passed.
-
-        The parameters provided, are passed as a sequence of
-        name, value items.  The 'pname' argument has the original name
-        before parameters were removed.
-
-        It is not the responsibility of the handler to give the return value a
-        location.
-        """
-
-
-class ITraversable(Interface):
-    """To traverse an object, this interface must be provided"""
-
-    def traverse(name, furtherPath):
-        """Get the next item on the path
-
-        Should return the item corresponding to 'name' or raise
-        TraversalError where appropriate.
-
-        'name' is an ASCII string or Unicode object.
-
-        'furtherPath' is a list of names still to be traversed. This
-        method is allowed to change the contents of furtherPath.
-        """
-
-class ITraversalAPI(Interface):
-    """Common API functions to ease traversal computations
-    """
-
-    def joinPath(path, *args):
-        """Join the given relative paths to the given path.
-
-        Returns a unicode path.
-
-        The path should be well-formed, and not end in a '/' unless it is
-        the root path. It can be either a string (ascii only) or unicode.
-        The positional arguments are relative paths to be added to the
-        path as new path segments.  The path may be absolute or relative.
-
-        A segment may not start with a '/' because that would be confused
-        with an absolute path. A segment may not end with a '/' because we
-        do not allow '/' at the end of relative paths.  A segment may
-        consist of . or .. to mean "the same place", or "the parent path"
-        respectively. A '.' should be removed and a '..' should cause the
-        segment to the left to be removed.  joinPath('/', '..') should
-        raise an exception.
-        """
-
-    def getPath(obj):
-        """Returns a string representing the physical path to the object.
-        """
-
-    def getRoot(obj):
-        """Returns the root of the traversal for the given object.
-        """
-
-    def traverse(object, path, default=None, request=None):
-        """Traverse 'path' relative to the given object.
-
-        'path' is a string with path segments separated by '/'.
-
-        'request' is passed in when traversing from presentation code. This
-        allows paths like @@foo to work.
-
-        Raises TraversalError if path cannot be found
-
-        Note: calling traverse with a path argument taken from an untrusted
-              source, such as an HTTP request form variable, is a bad idea.
-              It could allow a maliciously constructed request to call
-              code unexpectedly.
-              Consider using traverseName instead.
-        """
-
-    def traverseName(obj, name, default=None, traversable=None,
-                     request=None):
-        """Traverse a single step 'name' relative to the given object.
-
-        'name' must be a string. '.' and '..' are treated specially, as well as
-        names starting with '@' or '+'. Otherwise 'name' will be treated as a
-        single path segment.
-
-        You can explicitly pass in an ITraversable as the
-        'traversable' argument. If you do not, the given object will
-        be adapted to ITraversable.
-
-        'request' is passed in when traversing from presentation code. This
-        allows paths like @@foo to work.
-
-        Raises TraversalError if path cannot be found and 'default' was
-        not provided.
-
-        """
-
-    def getName(obj):
-        """Get the name an object was traversed via
-        """
-
-    def getParent(obj):
-        """Returns the container the object was traversed via.
-
-        Returns None if the object is a containment root.
-        Raises TypeError if the object doesn't have enough context to get the
-        parent.
-        """
-
-    def getParents(obj):
-        """Returns a list starting with the given object's parent followed by
-        each of its parents.
-
-        Raises a TypeError if the context doesn't go all the way down to
-        a containment root.
-        """
-
-    def canonicalPath(path_or_object):
-        """Returns a canonical absolute unicode path for the path or object.
-
-        Resolves segments that are '.' or '..'.
-
-        Raises ValueError if a badly formed path is given.
-        """
-
-class IPathAdapter(Interface):
-    """Marker interface for adapters to be used in paths
-    """

Copied: zope.traversing/tags/3.5.1/src/zope/traversing/interfaces.py (from rev 95959, zope.traversing/trunk/src/zope/traversing/interfaces.py)
===================================================================
--- zope.traversing/tags/3.5.1/src/zope/traversing/interfaces.py	                        (rev 0)
+++ zope.traversing/tags/3.5.1/src/zope/traversing/interfaces.py	2009-02-02 12:25:12 UTC (rev 95965)
@@ -0,0 +1,141 @@
+##############################################################################
+#
+# Copyright (c) 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Interfaces to do with traversing.
+
+$Id$
+"""
+
+from zope.interface import Interface
+
+# BBB: Re-import symbols to their old location.
+from zope.location.interfaces import LocationError as TraversalError
+from zope.location.interfaces import IRoot as IContainmentRoot
+from zope.location.interfaces import ILocationInfo as IPhysicallyLocatable
+from zope.location.interfaces import ITraverser
+
+
+class ITraversable(Interface):
+    """To traverse an object, this interface must be provided"""
+
+    def traverse(name, furtherPath):
+        """Get the next item on the path
+
+        Should return the item corresponding to 'name' or raise
+        LocationError where appropriate.
+
+        'name' is an ASCII string or Unicode object.
+
+        'furtherPath' is a list of names still to be traversed. This
+        method is allowed to change the contents of furtherPath.
+        """
+
+class ITraversalAPI(Interface):
+    """Common API functions to ease traversal computations
+    """
+
+    def joinPath(path, *args):
+        """Join the given relative paths to the given path.
+
+        Returns a unicode path.
+
+        The path should be well-formed, and not end in a '/' unless it is
+        the root path. It can be either a string (ascii only) or unicode.
+        The positional arguments are relative paths to be added to the
+        path as new path segments.  The path may be absolute or relative.
+
+        A segment may not start with a '/' because that would be confused
+        with an absolute path. A segment may not end with a '/' because we
+        do not allow '/' at the end of relative paths.  A segment may
+        consist of . or .. to mean "the same place", or "the parent path"
+        respectively. A '.' should be removed and a '..' should cause the
+        segment to the left to be removed.  joinPath('/', '..') should
+        raise an exception.
+        """
+
+    def getPath(obj):
+        """Returns a string representing the physical path to the object.
+        """
+
+    def getRoot(obj):
+        """Returns the root of the traversal for the given object.
+        """
+
+    def traverse(object, path, default=None, request=None):
+        """Traverse 'path' relative to the given object.
+
+        'path' is a string with path segments separated by '/'.
+
+        'request' is passed in when traversing from presentation code. This
+        allows paths like @@foo to work.
+
+        Raises LocationError if path cannot be found
+
+        Note: calling traverse with a path argument taken from an untrusted
+              source, such as an HTTP request form variable, is a bad idea.
+              It could allow a maliciously constructed request to call
+              code unexpectedly.
+              Consider using traverseName instead.
+        """
+
+    def traverseName(obj, name, default=None, traversable=None,
+                     request=None):
+        """Traverse a single step 'name' relative to the given object.
+
+        'name' must be a string. '.' and '..' are treated specially, as well as
+        names starting with '@' or '+'. Otherwise 'name' will be treated as a
+        single path segment.
+
+        You can explicitly pass in an ITraversable as the
+        'traversable' argument. If you do not, the given object will
+        be adapted to ITraversable.
+
+        'request' is passed in when traversing from presentation code. This
+        allows paths like @@foo to work.
+
+        Raises LocationError if path cannot be found and 'default' was
+        not provided.
+
+        """
+
+    def getName(obj):
+        """Get the name an object was traversed via
+        """
+
+    def getParent(obj):
+        """Returns the container the object was traversed via.
+
+        Returns None if the object is a containment root.
+        Raises TypeError if the object doesn't have enough context to get the
+        parent.
+        """
+
+    def getParents(obj):
+        """Returns a list starting with the given object's parent followed by
+        each of its parents.
+
+        Raises a TypeError if the context doesn't go all the way down to
+        a containment root.
+        """
+
+    def canonicalPath(path_or_object):
+        """Returns a canonical absolute unicode path for the path or object.
+
+        Resolves segments that are '.' or '..'.
+
+        Raises ValueError if a badly formed path is given.
+        """
+
+class IPathAdapter(Interface):
+    """Marker interface for adapters to be used in paths
+    """

Deleted: zope.traversing/tags/3.5.1/src/zope/traversing/namespace.py
===================================================================
--- zope.traversing/trunk/src/zope/traversing/namespace.py	2009-02-02 06:01:56 UTC (rev 95956)
+++ zope.traversing/tags/3.5.1/src/zope/traversing/namespace.py	2009-02-02 12:25:12 UTC (rev 95965)
@@ -1,587 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""URL Namespace Implementations
-
-$Id$
-"""
-__docformat__ = 'restructuredtext'
-
-import re
-
-import zope.component
-import zope.interface
-from zope.i18n.interfaces import IModifiableUserPreferredLanguages
-from zope.component.interfaces import ComponentLookupError
-from zope.interface import providedBy, directlyProvides, directlyProvidedBy
-from zope.publisher.interfaces.browser import IBrowserSkinType
-from zope.publisher.browser import applySkin
-from zope.security.proxy import removeSecurityProxy
-from zope.traversing.interfaces import ITraversable, IPathAdapter
-from zope.traversing.interfaces import TraversalError, IContainmentRoot
-
-
-class UnexpectedParameters(TraversalError):
-    "Unexpected namespace parameters were provided."
-
-class ExcessiveDepth(TraversalError):
-    "Too many levels of containment. We don't believe them."
-
-def namespaceLookup(ns, name, object, request=None):
-    """Lookup a value from a namespace
-
-    We look up a value using a view or an adapter, depending on
-    whether a request is passed.
-
-    Let's start with adapter-based transersal:
-
-      >>> class I(zope.interface.Interface):
-      ...     'Test interface'
-      >>> class C(object):
-      ...     zope.interface.implements(I)
-
-    We'll register a simple testing adapter:
-
-      >>> class Adapter(object):
-      ...     def __init__(self, context):
-      ...         self.context = context
-      ...     def traverse(self, name, remaining):
-      ...         return name+'42'
-
-      >>> zope.component.provideAdapter(Adapter, (I,), ITraversable, 'foo')
-
-    Then given an object, we can traverse it with a
-    namespace-qualified name:
-
-      >>> namespaceLookup('foo', 'bar', C())
-      'bar42'
-
-    If we give an invalid namespace, we'll get a not found error:
-
-      >>> namespaceLookup('fiz', 'bar', C())    # doctest: +ELLIPSIS
-      Traceback (most recent call last):
-      ...
-      LocationError: (<zope.traversing.namespace.C object at 0x...>, '++fiz++bar')
-
-    We'll get the same thing if we provide a request:
-
-      >>> from zope.publisher.browser import TestRequest
-      >>> request = TestRequest()
-      >>> namespaceLookup('foo', 'bar', C(), request)    # doctest: +ELLIPSIS
-      Traceback (most recent call last):
-      ...
-      LocationError: (<zope.traversing.namespace.C object at 0x...>, '++foo++bar')
-
-    We need to provide a view:
-
-      >>> class View(object):
-      ...     def __init__(self, context, request):
-      ...         pass
-      ...     def traverse(self, name, remaining):
-      ...         return name+'fromview'
-      >>> from zope.traversing.testing import browserView
-      >>> browserView(I, 'foo', View, providing=ITraversable)
-
-      >>> namespaceLookup('foo', 'bar', C(), request)
-      'barfromview'
-
-    Clean up:
-
-      >>> from zope.testing.cleanup import cleanUp
-      >>> cleanUp()
-    """
-    if request is not None:
-        traverser = zope.component.queryMultiAdapter((object, request),
-                                                     ITraversable, ns)
-    else:
-        traverser = zope.component.queryAdapter(object, ITraversable, ns)
-
-    if traverser is None:
-        raise TraversalError(object, "++%s++%s" % (ns, name))
-
-    return traverser.traverse(name, ())
-
-
-namespace_pattern = re.compile('[+][+]([a-zA-Z0-9_]+)[+][+]')
-
-def nsParse(name):
-    """Parse a namespace-qualified name into a namespace name and a
-    name.  Returns the namespace name and a name.
-
-    A namespace-qualified name is usually of the form ++ns++name, as in:
-
-      >>> nsParse('++acquire++foo')
-      ('acquire', 'foo')
-
-    The part inside the +s must be an identifier, so:
-
-      >>> nsParse('++hello world++foo')
-      ('', '++hello world++foo')
-      >>> nsParse('+++acquire+++foo')
-      ('', '+++acquire+++foo')
-
-    But it may also be a @@foo, which implies the view namespace:
-
-      >>> nsParse('@@foo')
-      ('view', 'foo')
-
-      >>> nsParse('@@@foo')
-      ('view', '@foo')
-
-      >>> nsParse('@foo')
-      ('', '@foo')
-
-    """
-    ns = ''
-    if name.startswith('@@'):
-        ns = 'view'
-        name = name[2:]
-    else:
-        match = namespace_pattern.match(name)
-        if match:
-            prefix, ns = match.group(0, 1)
-            name = name[len(prefix):]
-
-    return ns, name
-
-def getResource(site, name, request):
-    resource = queryResource(site, name, request)
-    if resource is None:
-        raise TraversalError(site, name)
-    return resource
-
-def queryResource(site, name, request, default=None):
-    resource = zope.component.queryAdapter(request, name=name)
-    if resource is None:
-        return default
-
-    # We need to set the __parent__ and __name__.  We need the unproxied
-    # resource to do this.  We still return the proxied resource.
-    r = removeSecurityProxy(resource)
-
-    r.__parent__ = site
-    r.__name__ = name
-
-    return resource
-
-# ---- namespace processors below ----
-
-class SimpleHandler(object):
-
-    zope.interface.implements(ITraversable)
-
-    def __init__(self, context, request=None):
-        """Simple handlers can be used as adapters or views
-
-        They ignore their second constructor arg and store the first
-        one in their context attr:
-
-          >>> SimpleHandler(42).context
-          42
-
-          >>> SimpleHandler(42, 43).context
-          42
-        """
-        self.context = context
-
-class acquire(SimpleHandler):
-    """Traversal adapter for the acquire namespace
-    """
-
-    def traverse(self, name, remaining):
-        """Acquire a name
-
-        Let's set up some example data:
-
-          >>> class testcontent(object):
-          ...     zope.interface.implements(ITraversable)
-          ...     def traverse(self, name, remaining):
-          ...         v = getattr(self, name, None)
-          ...         if v is None:
-          ...             raise TraversalError(self, name)
-          ...         return v
-          ...     def __repr__(self):
-          ...         return 'splat'
-
-          >>> ob = testcontent()
-          >>> ob.a = 1
-          >>> ob.__parent__ = testcontent()
-          >>> ob.__parent__.b = 2
-          >>> ob.__parent__.__parent__ = testcontent()
-          >>> ob.__parent__.__parent__.c = 3
-
-        And acquire some names:
-
-          >>> adapter = acquire(ob)
-
-          >>> adapter.traverse('a', ())
-          1
-
-          >>> adapter.traverse('b', ())
-          2
-
-          >>> adapter.traverse('c', ())
-          3
-
-          >>> adapter.traverse('d', ())
-          Traceback (most recent call last):
-          ...
-          LocationError: (splat, 'd')
-        """
-        i = 0
-        ob = self.context
-        while i < 200:
-            i += 1
-            traversable = ITraversable(ob, None)
-            if traversable is not None:
-                try:
-                    # ??? what do we do if the path gets bigger?
-                    path = []
-                    next = traversable.traverse(name, path)
-                    if path:
-                        continue
-                except TraversalError:
-                    pass
-
-                else:
-                    return next
-
-            ob = getattr(ob, '__parent__', None)
-            if ob is None:
-                raise TraversalError(self.context, name)
-
-        raise ExcessiveDepth(self.context, name)
-
-class attr(SimpleHandler):
-
-    def traverse(self, name, ignored):
-        """Attribute traversal adapter
-
-        This adapter just provides traversal to attributes:
-
-          >>> ob = {'x': 1}
-          >>> adapter = attr(ob)
-          >>> adapter.traverse('keys', ())()
-          ['x']
-
-        """
-        return getattr(self.context, name)
-
-class item(SimpleHandler):
-
-    def traverse(self, name, ignored):
-        """Item traversal adapter
-
-           This adapter just provides traversal to items:
-
-              >>> ob = {'x': 42}
-              >>> adapter = item(ob)
-              >>> adapter.traverse('x', ())
-              42
-           """
-        return self.context[name]
-
-class etc(SimpleHandler):
-
-    def traverse(self, name, ignored):
-        # TODO:
-        # This is here now to allow us to get site managers from a
-        # separate namespace from the content. We add and etc
-        # namespace to allow us to handle misc objects.  We'll apply
-        # YAGNI for now and hard code this. We'll want something more
-        # general later. We were thinking of just calling "get"
-        # methods, but this is probably too magic. In particular, we
-        # will treat returned objects as sub-objects wrt security and
-        # not all get methods may satisfy this assumption. It might be
-        # best to introduce some sort of etc registry.
-
-        ob = self.context
-
-        if (name in ('process', 'ApplicationController')
-            and IContainmentRoot.providedBy(ob)):
-            # import the application controller here to avoid circular
-            # import problems
-            try:
-                from zope.app.applicationcontrol.applicationcontrol \
-                     import applicationController
-            except ImportError:
-                pass
-            else:
-                return applicationController
-
-        if name not in ('site',):
-            raise TraversalError(ob, name)
-
-        method_name = "getSiteManager"
-        method = getattr(ob, method_name, None)
-        if method is None:
-            raise TraversalError(ob, name)
-
-        try:
-            return method()
-        except ComponentLookupError:
-            raise TraversalError(ob, name)
-
-
-class view(object):
-
-    zope.interface.implements(ITraversable)
-
-    def __init__(self, context, request):
-        self.context = context
-        self.request = request
-
-    def traverse(self, name, ignored):
-        view = zope.component.queryMultiAdapter((self.context, self.request),
-                                                name=name)
-        if view is None:
-            raise TraversalError(self.context, name)
-
-        return view
-
-class resource(view):
-
-    def traverse(self, name, ignored):
-        # The context is important here, since it becomes the parent of the
-        # resource, which is needed to generate the absolute URL.
-        return getResource(self.context, name, self.request)
-
-class lang(view):
-
-    def traverse(self, name, ignored):
-        self.request.shiftNameToApplication()
-        languages = IModifiableUserPreferredLanguages(self.request)
-        languages.setPreferredLanguages([name])
-        return self.context
-
-class skin(view):
-
-    def traverse(self, name, ignored):
-        self.request.shiftNameToApplication()
-        try:
-            skin = zope.component.getUtility(IBrowserSkinType, name)
-        except ComponentLookupError:
-            raise TraversalError("++skin++%s" % name)
-        applySkin(self.request, skin)
-        return self.context
-
-class vh(view):
-
-    def traverse(self, name, ignored):
-
-        request = self.request
-
-        traversal_stack = request.getTraversalStack()
-        app_names = []
-
-        name = name.encode('utf8')
-        if name:
-            try:
-                proto, host, port = name.split(":")
-            except ValueError:
-                raise ValueError("Vhost directive should have the form "
-                                 "++vh++protocol:host:port")
-
-            request.setApplicationServer(host, proto, port)
-
-        if '++' in traversal_stack:
-            segment = traversal_stack.pop()
-            while segment != '++':
-                app_names.append(segment)
-                segment = traversal_stack.pop()
-            request.setTraversalStack(traversal_stack)
-        else:
-            raise ValueError(
-                "Must have a path element '++' after a virtual host "
-                "directive.")
-
-        request.setVirtualHostRoot(app_names)
-
-        return self.context
-
-
-class adapter(SimpleHandler):
-
-    def traverse(self, name, ignored):
-        """Adapter traversal adapter
-
-        This adapter provides traversal to named adapters registered
-        to provide IPathAdapter.
-
-        To demonstrate this, we need to register some adapters:
-
-          >>> def adapter1(ob):
-          ...     return 1
-          >>> def adapter2(ob):
-          ...     return 2
-          >>> zope.component.provideAdapter(
-          ...     adapter1, (None,), IPathAdapter, 'a1')
-          >>> zope.component.provideAdapter(
-          ...     adapter2, (None,), IPathAdapter, 'a2')
-
-        Now, with these adapters in place, we can use the traversal adapter:
-
-          >>> ob = object()
-          >>> adapter = adapter(ob)
-          >>> adapter.traverse('a1', ())
-          1
-          >>> adapter.traverse('a2', ())
-          2
-          >>> try:
-          ...     adapter.traverse('bob', ())
-          ... except TraversalError:
-          ...     print 'no adapter'
-          no adapter
-
-        Clean up:
-
-          >>> from zope.testing.cleanup import cleanUp
-          >>> cleanUp()
-        """
-        try:
-            return zope.component.getAdapter(self.context, IPathAdapter, name)
-        except ComponentLookupError:
-            raise TraversalError(self.context, name)
-
-
-class debug(view):
-
-    def traverse(self, name, ignored):
-        """Debug traversal adapter
-
-        This adapter allows debugging flags to be set in the request.
-        See IDebugFlags.
-
-        Setup for demonstration:
-
-            >>> from zope.publisher.browser import TestRequest
-            >>> request = TestRequest()
-            >>> ob = object()
-            >>> adapter = debug(ob, request)
-
-        in debug mode, ++debug++source enables source annotations
-
-            >>> request.debug.sourceAnnotations
-            False
-            >>> adapter.traverse('source', ()) is ob
-            True
-            >>> request.debug.sourceAnnotations
-            True
-
-        ++debug++tal enables TAL markup in output
-
-            >>> request.debug.showTAL
-            False
-            >>> adapter.traverse('tal', ()) is ob
-            True
-            >>> request.debug.showTAL
-            True
-
-        ++debug++errors enables tracebacks (by switching to debug skin)
-
-            >>> from zope.publisher.interfaces.browser import IBrowserRequest
-
-            >>> class Debug(IBrowserRequest):
-            ...     pass
-            >>> directlyProvides(Debug, IBrowserSkinType)
-            >>> zope.component.provideUtility(
-            ...     Debug, IBrowserSkinType, name='Debug')
-
-            >>> Debug.providedBy(request)
-            False
-            >>> adapter.traverse('errors', ()) is ob
-            True
-            >>> Debug.providedBy(request)
-            True
-
-        You can specify several flags separated by commas
-
-            >>> adapter.traverse('source,tal', ()) is ob
-            True
-
-        Unknown flag names cause exceptions
-
-            >>> try:
-            ...     adapter.traverse('badflag', ())
-            ... except ValueError:
-            ...     print 'unknown debugging flag'
-            unknown debugging flag
-
-        """
-        if __debug__:
-            request = self.request
-            for flag in name.split(','):
-                if flag == 'source':
-                    request.debug.sourceAnnotations = True
-                elif flag == 'tal':
-                    request.debug.showTAL = True
-                elif flag == 'errors':
-                    # TODO: I am not sure this is the best solution.  What
-                    # if we want to enable tracebacks when also trying to
-                    # debug a different skin?
-                    skin = zope.component.getUtility(IBrowserSkinType, 'Debug')
-                    directlyProvides(request, providedBy(request)+skin)
-                else:
-                    raise ValueError("Unknown debug flag: %s" % flag)
-            return self.context
-        else:
-            raise ValueError("Debug flags only allowed in debug mode")
-
-    if not __debug__:
-        # If not in debug mode, we should get an error:
-        traverse.__doc__ = """Disabled debug traversal adapter
-
-        This adapter allows debugging flags to be set in the request,
-        but it is disabled because Python was run with -O.
-
-        Setup for demonstration:
-
-            >>> from zope.publisher.browser import TestRequest
-            >>> request = TestRequest()
-            >>> ob = object()
-            >>> adapter = debug(ob, request)
-
-        in debug mode, ++debug++source enables source annotations
-
-            >>> request.debug.sourceAnnotations
-            False
-            >>> adapter.traverse('source', ()) is ob
-            Traceback (most recent call last):
-            ...
-            ValueError: Debug flags only allowed in debug mode
-
-        ++debug++tal enables TAL markup in output
-
-            >>> request.debug.showTAL
-            False
-            >>> adapter.traverse('tal', ()) is ob
-            Traceback (most recent call last):
-            ...
-            ValueError: Debug flags only allowed in debug mode
-
-        ++debug++errors enables tracebacks (by switching to debug skin)
-
-            >>> Debug.providedBy(request)
-            False
-            >>> adapter.traverse('errors', ()) is ob
-            Traceback (most recent call last):
-            ...
-            ValueError: Debug flags only allowed in debug mode
-
-        You can specify several flags separated by commas
-
-            >>> adapter.traverse('source,tal', ()) is ob
-            Traceback (most recent call last):
-            ...
-            ValueError: Debug flags only allowed in debug mode
-        """

Copied: zope.traversing/tags/3.5.1/src/zope/traversing/namespace.py (from rev 95959, zope.traversing/trunk/src/zope/traversing/namespace.py)
===================================================================
--- zope.traversing/tags/3.5.1/src/zope/traversing/namespace.py	                        (rev 0)
+++ zope.traversing/tags/3.5.1/src/zope/traversing/namespace.py	2009-02-02 12:25:12 UTC (rev 95965)
@@ -0,0 +1,587 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""URL Namespace Implementations
+
+$Id$
+"""
+__docformat__ = 'restructuredtext'
+
+import re
+
+import zope.component
+import zope.interface
+from zope.i18n.interfaces import IModifiableUserPreferredLanguages
+from zope.component.interfaces import ComponentLookupError
+from zope.interface import providedBy, directlyProvides, directlyProvidedBy
+from zope.location.interfaces import IRoot, LocationError
+from zope.publisher.interfaces.browser import IBrowserSkinType
+from zope.publisher.browser import applySkin
+from zope.security.proxy import removeSecurityProxy
+from zope.traversing.interfaces import ITraversable, IPathAdapter
+
+
+class UnexpectedParameters(LocationError):
+    "Unexpected namespace parameters were provided."
+
+class ExcessiveDepth(LocationError):
+    "Too many levels of containment. We don't believe them."
+
+def namespaceLookup(ns, name, object, request=None):
+    """Lookup a value from a namespace
+
+    We look up a value using a view or an adapter, depending on
+    whether a request is passed.
+
+    Let's start with adapter-based transersal:
+
+      >>> class I(zope.interface.Interface):
+      ...     'Test interface'
+      >>> class C(object):
+      ...     zope.interface.implements(I)
+
+    We'll register a simple testing adapter:
+
+      >>> class Adapter(object):
+      ...     def __init__(self, context):
+      ...         self.context = context
+      ...     def traverse(self, name, remaining):
+      ...         return name+'42'
+
+      >>> zope.component.provideAdapter(Adapter, (I,), ITraversable, 'foo')
+
+    Then given an object, we can traverse it with a
+    namespace-qualified name:
+
+      >>> namespaceLookup('foo', 'bar', C())
+      'bar42'
+
+    If we give an invalid namespace, we'll get a not found error:
+
+      >>> namespaceLookup('fiz', 'bar', C())    # doctest: +ELLIPSIS
+      Traceback (most recent call last):
+      ...
+      LocationError: (<zope.traversing.namespace.C object at 0x...>, '++fiz++bar')
+
+    We'll get the same thing if we provide a request:
+
+      >>> from zope.publisher.browser import TestRequest
+      >>> request = TestRequest()
+      >>> namespaceLookup('foo', 'bar', C(), request)    # doctest: +ELLIPSIS
+      Traceback (most recent call last):
+      ...
+      LocationError: (<zope.traversing.namespace.C object at 0x...>, '++foo++bar')
+
+    We need to provide a view:
+
+      >>> class View(object):
+      ...     def __init__(self, context, request):
+      ...         pass
+      ...     def traverse(self, name, remaining):
+      ...         return name+'fromview'
+      >>> from zope.traversing.testing import browserView
+      >>> browserView(I, 'foo', View, providing=ITraversable)
+
+      >>> namespaceLookup('foo', 'bar', C(), request)
+      'barfromview'
+
+    Clean up:
+
+      >>> from zope.testing.cleanup import cleanUp
+      >>> cleanUp()
+    """
+    if request is not None:
+        traverser = zope.component.queryMultiAdapter((object, request),
+                                                     ITraversable, ns)
+    else:
+        traverser = zope.component.queryAdapter(object, ITraversable, ns)
+
+    if traverser is None:
+        raise LocationError(object, "++%s++%s" % (ns, name))
+
+    return traverser.traverse(name, ())
+
+
+namespace_pattern = re.compile('[+][+]([a-zA-Z0-9_]+)[+][+]')
+
+def nsParse(name):
+    """Parse a namespace-qualified name into a namespace name and a
+    name.  Returns the namespace name and a name.
+
+    A namespace-qualified name is usually of the form ++ns++name, as in:
+
+      >>> nsParse('++acquire++foo')
+      ('acquire', 'foo')
+
+    The part inside the +s must be an identifier, so:
+
+      >>> nsParse('++hello world++foo')
+      ('', '++hello world++foo')
+      >>> nsParse('+++acquire+++foo')
+      ('', '+++acquire+++foo')
+
+    But it may also be a @@foo, which implies the view namespace:
+
+      >>> nsParse('@@foo')
+      ('view', 'foo')
+
+      >>> nsParse('@@@foo')
+      ('view', '@foo')
+
+      >>> nsParse('@foo')
+      ('', '@foo')
+
+    """
+    ns = ''
+    if name.startswith('@@'):
+        ns = 'view'
+        name = name[2:]
+    else:
+        match = namespace_pattern.match(name)
+        if match:
+            prefix, ns = match.group(0, 1)
+            name = name[len(prefix):]
+
+    return ns, name
+
+def getResource(site, name, request):
+    resource = queryResource(site, name, request)
+    if resource is None:
+        raise LocationError(site, name)
+    return resource
+
+def queryResource(site, name, request, default=None):
+    resource = zope.component.queryAdapter(request, name=name)
+    if resource is None:
+        return default
+
+    # We need to set the __parent__ and __name__.  We need the unproxied
+    # resource to do this.  We still return the proxied resource.
+    r = removeSecurityProxy(resource)
+
+    r.__parent__ = site
+    r.__name__ = name
+
+    return resource
+
+# ---- namespace processors below ----
+
+class SimpleHandler(object):
+
+    zope.interface.implements(ITraversable)
+
+    def __init__(self, context, request=None):
+        """Simple handlers can be used as adapters or views
+
+        They ignore their second constructor arg and store the first
+        one in their context attr:
+
+          >>> SimpleHandler(42).context
+          42
+
+          >>> SimpleHandler(42, 43).context
+          42
+        """
+        self.context = context
+
+class acquire(SimpleHandler):
+    """Traversal adapter for the acquire namespace
+    """
+
+    def traverse(self, name, remaining):
+        """Acquire a name
+
+        Let's set up some example data:
+
+          >>> class testcontent(object):
+          ...     zope.interface.implements(ITraversable)
+          ...     def traverse(self, name, remaining):
+          ...         v = getattr(self, name, None)
+          ...         if v is None:
+          ...             raise LocationError(self, name)
+          ...         return v
+          ...     def __repr__(self):
+          ...         return 'splat'
+
+          >>> ob = testcontent()
+          >>> ob.a = 1
+          >>> ob.__parent__ = testcontent()
+          >>> ob.__parent__.b = 2
+          >>> ob.__parent__.__parent__ = testcontent()
+          >>> ob.__parent__.__parent__.c = 3
+
+        And acquire some names:
+
+          >>> adapter = acquire(ob)
+
+          >>> adapter.traverse('a', ())
+          1
+
+          >>> adapter.traverse('b', ())
+          2
+
+          >>> adapter.traverse('c', ())
+          3
+
+          >>> adapter.traverse('d', ())
+          Traceback (most recent call last):
+          ...
+          LocationError: (splat, 'd')
+        """
+        i = 0
+        ob = self.context
+        while i < 200:
+            i += 1
+            traversable = ITraversable(ob, None)
+            if traversable is not None:
+                try:
+                    # ??? what do we do if the path gets bigger?
+                    path = []
+                    next = traversable.traverse(name, path)
+                    if path:
+                        continue
+                except LocationError:
+                    pass
+
+                else:
+                    return next
+
+            ob = getattr(ob, '__parent__', None)
+            if ob is None:
+                raise LocationError(self.context, name)
+
+        raise ExcessiveDepth(self.context, name)
+
+class attr(SimpleHandler):
+
+    def traverse(self, name, ignored):
+        """Attribute traversal adapter
+
+        This adapter just provides traversal to attributes:
+
+          >>> ob = {'x': 1}
+          >>> adapter = attr(ob)
+          >>> adapter.traverse('keys', ())()
+          ['x']
+
+        """
+        return getattr(self.context, name)
+
+class item(SimpleHandler):
+
+    def traverse(self, name, ignored):
+        """Item traversal adapter
+
+           This adapter just provides traversal to items:
+
+              >>> ob = {'x': 42}
+              >>> adapter = item(ob)
+              >>> adapter.traverse('x', ())
+              42
+           """
+        return self.context[name]
+
+class etc(SimpleHandler):
+
+    def traverse(self, name, ignored):
+        # TODO:
+        # This is here now to allow us to get site managers from a
+        # separate namespace from the content. We add and etc
+        # namespace to allow us to handle misc objects.  We'll apply
+        # YAGNI for now and hard code this. We'll want something more
+        # general later. We were thinking of just calling "get"
+        # methods, but this is probably too magic. In particular, we
+        # will treat returned objects as sub-objects wrt security and
+        # not all get methods may satisfy this assumption. It might be
+        # best to introduce some sort of etc registry.
+
+        ob = self.context
+
+        if (name in ('process', 'ApplicationController')
+            and IRoot.providedBy(ob)):
+            # import the application controller here to avoid circular
+            # import problems
+            try:
+                from zope.app.applicationcontrol.applicationcontrol \
+                     import applicationController
+            except ImportError:
+                pass
+            else:
+                return applicationController
+
+        if name not in ('site',):
+            raise LocationError(ob, name)
+
+        method_name = "getSiteManager"
+        method = getattr(ob, method_name, None)
+        if method is None:
+            raise LocationError(ob, name)
+
+        try:
+            return method()
+        except ComponentLookupError:
+            raise LocationError(ob, name)
+
+
+class view(object):
+
+    zope.interface.implements(ITraversable)
+
+    def __init__(self, context, request):
+        self.context = context
+        self.request = request
+
+    def traverse(self, name, ignored):
+        view = zope.component.queryMultiAdapter((self.context, self.request),
+                                                name=name)
+        if view is None:
+            raise LocationError(self.context, name)
+
+        return view
+
+class resource(view):
+
+    def traverse(self, name, ignored):
+        # The context is important here, since it becomes the parent of the
+        # resource, which is needed to generate the absolute URL.
+        return getResource(self.context, name, self.request)
+
+class lang(view):
+
+    def traverse(self, name, ignored):
+        self.request.shiftNameToApplication()
+        languages = IModifiableUserPreferredLanguages(self.request)
+        languages.setPreferredLanguages([name])
+        return self.context
+
+class skin(view):
+
+    def traverse(self, name, ignored):
+        self.request.shiftNameToApplication()
+        try:
+            skin = zope.component.getUtility(IBrowserSkinType, name)
+        except ComponentLookupError:
+            raise LocationError("++skin++%s" % name)
+        applySkin(self.request, skin)
+        return self.context
+
+class vh(view):
+
+    def traverse(self, name, ignored):
+
+        request = self.request
+
+        traversal_stack = request.getTraversalStack()
+        app_names = []
+
+        name = name.encode('utf8')
+        if name:
+            try:
+                proto, host, port = name.split(":")
+            except ValueError:
+                raise ValueError("Vhost directive should have the form "
+                                 "++vh++protocol:host:port")
+
+            request.setApplicationServer(host, proto, port)
+
+        if '++' in traversal_stack:
+            segment = traversal_stack.pop()
+            while segment != '++':
+                app_names.append(segment)
+                segment = traversal_stack.pop()
+            request.setTraversalStack(traversal_stack)
+        else:
+            raise ValueError(
+                "Must have a path element '++' after a virtual host "
+                "directive.")
+
+        request.setVirtualHostRoot(app_names)
+
+        return self.context
+
+
+class adapter(SimpleHandler):
+
+    def traverse(self, name, ignored):
+        """Adapter traversal adapter
+
+        This adapter provides traversal to named adapters registered
+        to provide IPathAdapter.
+
+        To demonstrate this, we need to register some adapters:
+
+          >>> def adapter1(ob):
+          ...     return 1
+          >>> def adapter2(ob):
+          ...     return 2
+          >>> zope.component.provideAdapter(
+          ...     adapter1, (None,), IPathAdapter, 'a1')
+          >>> zope.component.provideAdapter(
+          ...     adapter2, (None,), IPathAdapter, 'a2')
+
+        Now, with these adapters in place, we can use the traversal adapter:
+
+          >>> ob = object()
+          >>> adapter = adapter(ob)
+          >>> adapter.traverse('a1', ())
+          1
+          >>> adapter.traverse('a2', ())
+          2
+          >>> try:
+          ...     adapter.traverse('bob', ())
+          ... except LocationError:
+          ...     print 'no adapter'
+          no adapter
+
+        Clean up:
+
+          >>> from zope.testing.cleanup import cleanUp
+          >>> cleanUp()
+        """
+        try:
+            return zope.component.getAdapter(self.context, IPathAdapter, name)
+        except ComponentLookupError:
+            raise LocationError(self.context, name)
+
+
+class debug(view):
+
+    def traverse(self, name, ignored):
+        """Debug traversal adapter
+
+        This adapter allows debugging flags to be set in the request.
+        See IDebugFlags.
+
+        Setup for demonstration:
+
+            >>> from zope.publisher.browser import TestRequest
+            >>> request = TestRequest()
+            >>> ob = object()
+            >>> adapter = debug(ob, request)
+
+        in debug mode, ++debug++source enables source annotations
+
+            >>> request.debug.sourceAnnotations
+            False
+            >>> adapter.traverse('source', ()) is ob
+            True
+            >>> request.debug.sourceAnnotations
+            True
+
+        ++debug++tal enables TAL markup in output
+
+            >>> request.debug.showTAL
+            False
+            >>> adapter.traverse('tal', ()) is ob
+            True
+            >>> request.debug.showTAL
+            True
+
+        ++debug++errors enables tracebacks (by switching to debug skin)
+
+            >>> from zope.publisher.interfaces.browser import IBrowserRequest
+
+            >>> class Debug(IBrowserRequest):
+            ...     pass
+            >>> directlyProvides(Debug, IBrowserSkinType)
+            >>> zope.component.provideUtility(
+            ...     Debug, IBrowserSkinType, name='Debug')
+
+            >>> Debug.providedBy(request)
+            False
+            >>> adapter.traverse('errors', ()) is ob
+            True
+            >>> Debug.providedBy(request)
+            True
+
+        You can specify several flags separated by commas
+
+            >>> adapter.traverse('source,tal', ()) is ob
+            True
+
+        Unknown flag names cause exceptions
+
+            >>> try:
+            ...     adapter.traverse('badflag', ())
+            ... except ValueError:
+            ...     print 'unknown debugging flag'
+            unknown debugging flag
+
+        """
+        if __debug__:
+            request = self.request
+            for flag in name.split(','):
+                if flag == 'source':
+                    request.debug.sourceAnnotations = True
+                elif flag == 'tal':
+                    request.debug.showTAL = True
+                elif flag == 'errors':
+                    # TODO: I am not sure this is the best solution.  What
+                    # if we want to enable tracebacks when also trying to
+                    # debug a different skin?
+                    skin = zope.component.getUtility(IBrowserSkinType, 'Debug')
+                    directlyProvides(request, providedBy(request)+skin)
+                else:
+                    raise ValueError("Unknown debug flag: %s" % flag)
+            return self.context
+        else:
+            raise ValueError("Debug flags only allowed in debug mode")
+
+    if not __debug__:
+        # If not in debug mode, we should get an error:
+        traverse.__doc__ = """Disabled debug traversal adapter
+
+        This adapter allows debugging flags to be set in the request,
+        but it is disabled because Python was run with -O.
+
+        Setup for demonstration:
+
+            >>> from zope.publisher.browser import TestRequest
+            >>> request = TestRequest()
+            >>> ob = object()
+            >>> adapter = debug(ob, request)
+
+        in debug mode, ++debug++source enables source annotations
+
+            >>> request.debug.sourceAnnotations
+            False
+            >>> adapter.traverse('source', ()) is ob
+            Traceback (most recent call last):
+            ...
+            ValueError: Debug flags only allowed in debug mode
+
+        ++debug++tal enables TAL markup in output
+
+            >>> request.debug.showTAL
+            False
+            >>> adapter.traverse('tal', ()) is ob
+            Traceback (most recent call last):
+            ...
+            ValueError: Debug flags only allowed in debug mode
+
+        ++debug++errors enables tracebacks (by switching to debug skin)
+
+            >>> Debug.providedBy(request)
+            False
+            >>> adapter.traverse('errors', ()) is ob
+            Traceback (most recent call last):
+            ...
+            ValueError: Debug flags only allowed in debug mode
+
+        You can specify several flags separated by commas
+
+            >>> adapter.traverse('source,tal', ()) is ob
+            Traceback (most recent call last):
+            ...
+            ValueError: Debug flags only allowed in debug mode
+        """

Deleted: zope.traversing/tags/3.5.1/src/zope/traversing/testing.py
===================================================================
--- zope.traversing/trunk/src/zope/traversing/testing.py	2009-02-02 06:01:56 UTC (rev 95956)
+++ zope.traversing/tags/3.5.1/src/zope/traversing/testing.py	2009-02-02 12:25:12 UTC (rev 95965)
@@ -1,59 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2005 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Traversing test fixtures
-
-$Id$
-"""
-__docformat__ = "reStructuredText"
-
-import zope.component
-import zope.interface
-from zope.publisher.interfaces.browser import IDefaultBrowserLayer
-from zope.location.traversing import LocationPhysicallyLocatable
-from zope.traversing.interfaces import ITraverser, ITraversable
-from zope.traversing.interfaces import IPhysicallyLocatable
-from zope.traversing.interfaces import IContainmentRoot
-from zope.traversing.adapters import DefaultTraversable
-from zope.traversing.adapters import Traverser, RootPhysicallyLocatable
-from zope.traversing.browser import SiteAbsoluteURL, AbsoluteURL
-from zope.traversing.browser.interfaces import IAbsoluteURL
-from zope.traversing.namespace import etc
-
-def setUp():
-    zope.component.provideAdapter(Traverser, (None,), ITraverser)
-    zope.component.provideAdapter(DefaultTraversable, (None,), ITraversable)
-    zope.component.provideAdapter(LocationPhysicallyLocatable,
-                                  (None,), IPhysicallyLocatable)
-    zope.component.provideAdapter(RootPhysicallyLocatable,
-                                  (IContainmentRoot,), IPhysicallyLocatable)
-
-    # set up the 'etc' namespace
-    zope.component.provideAdapter(etc, (None,), ITraversable, name="etc")
-    zope.component.provideAdapter(etc, (None, None), ITraversable, name="etc")
-
-    browserView(None, "absolute_url", AbsoluteURL)
-    browserView(IContainmentRoot, "absolute_url", SiteAbsoluteURL)
-
-    browserView(None, '', AbsoluteURL, providing=IAbsoluteURL)
-    browserView(IContainmentRoot, '', SiteAbsoluteURL,
-                providing=IAbsoluteURL)
-
-
-def browserView(for_, name, factory, providing=zope.interface.Interface):
-    zope.component.provideAdapter(factory, (for_, IDefaultBrowserLayer),
-                                  providing, name=name)
-
-def browserResource(name, factory, providing=zope.interface.Interface):
-    zope.component.provideAdapter(factory, (IDefaultBrowserLayer,),
-                                  providing, name=name)

Copied: zope.traversing/tags/3.5.1/src/zope/traversing/testing.py (from rev 95959, zope.traversing/trunk/src/zope/traversing/testing.py)
===================================================================
--- zope.traversing/tags/3.5.1/src/zope/traversing/testing.py	                        (rev 0)
+++ zope.traversing/tags/3.5.1/src/zope/traversing/testing.py	2009-02-02 12:25:12 UTC (rev 95965)
@@ -0,0 +1,55 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Traversing test fixtures
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+
+import zope.component
+import zope.interface
+from zope.publisher.interfaces.browser import IDefaultBrowserLayer
+from zope.location.traversing import LocationPhysicallyLocatable
+from zope.location.interfaces import ILocationInfo, IRoot, ITraverser
+from zope.traversing.interfaces import ITraversable
+from zope.traversing.adapters import DefaultTraversable
+from zope.traversing.adapters import Traverser
+from zope.traversing.browser import SiteAbsoluteURL, AbsoluteURL
+from zope.traversing.browser.interfaces import IAbsoluteURL
+from zope.traversing.namespace import etc
+
+def setUp():
+    zope.component.provideAdapter(Traverser, (None,), ITraverser)
+    zope.component.provideAdapter(DefaultTraversable, (None,), ITraversable)
+    zope.component.provideAdapter(LocationPhysicallyLocatable,
+                                  (None,), ILocationInfo)
+
+    # set up the 'etc' namespace
+    zope.component.provideAdapter(etc, (None,), ITraversable, name="etc")
+    zope.component.provideAdapter(etc, (None, None), ITraversable, name="etc")
+
+    browserView(None, "absolute_url", AbsoluteURL)
+    browserView(IRoot, "absolute_url", SiteAbsoluteURL)
+
+    browserView(None, '', AbsoluteURL, providing=IAbsoluteURL)
+    browserView(IRoot, '', SiteAbsoluteURL, providing=IAbsoluteURL)
+
+
+def browserView(for_, name, factory, providing=zope.interface.Interface):
+    zope.component.provideAdapter(factory, (for_, IDefaultBrowserLayer),
+                                  providing, name=name)
+
+def browserResource(name, factory, providing=zope.interface.Interface):
+    zope.component.provideAdapter(factory, (IDefaultBrowserLayer,),
+                                  providing, name=name)

Deleted: zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_conveniencefunctions.py
===================================================================
--- zope.traversing/trunk/src/zope/traversing/tests/test_conveniencefunctions.py	2009-02-02 06:01:56 UTC (rev 95956)
+++ zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_conveniencefunctions.py	2009-02-02 12:25:12 UTC (rev 95965)
@@ -1,363 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Test traversal convenience functions.
-
-$Id$
-"""
-from unittest import TestCase, main, makeSuite
-
-import zope.component
-from zope.interface import directlyProvides
-from zope.location.traversing import LocationPhysicallyLocatable
-from zope.security.proxy import Proxy
-from zope.security.checker import selectChecker
-from zope.traversing.adapters import Traverser, DefaultTraversable
-from zope.traversing.adapters import RootPhysicallyLocatable
-from zope.traversing.interfaces import ITraverser, ITraversable
-from zope.traversing.interfaces import IContainmentRoot, TraversalError
-from zope.traversing.interfaces import IPhysicallyLocatable
-
-from zope.app.component.testing import PlacefulSetup
-from zope.container.contained import contained
-
-class C(object):
-    __parent__ = None
-    __name__ = None
-    def __init__(self, name):
-        self.name = name
-
-def _proxied(*args):
-    return Proxy(args, selectChecker(args))
-
-
-class Test(PlacefulSetup, TestCase):
-
-    def setUp(self):
-        PlacefulSetup.setUp(self)
-        # Build up a wrapper chain
-        root = C('root')
-        directlyProvides(root, IContainmentRoot)
-        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,),
-                                      IPhysicallyLocatable)
-        zope.component.provideAdapter(RootPhysicallyLocatable,
-                                      (IContainmentRoot,), IPhysicallyLocatable)
-
-    def testTraverse(self):
-        from zope.traversing.api import traverse
-        self.assertEqual(
-            traverse(self.item, '/folder/item'),
-            self.tr.traverse('/folder/item')
-            )
-
-    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')
-            )
-
-        # TODO test that ++names++ and @@names work too
-
-    def testTraverseNameBadValue(self):
-        from zope.traversing.api import traverseName
-        self.assertRaises(
-            TraversalError,
-            traverseName,
-            self.folder, '../root'
-            )
-        self.assertRaises(
-            TraversalError,
-            traverseName,
-            self.folder, '/root'
-            )
-        self.assertRaises(
-            TraversalError,
-            traverseName,
-            self.folder, './item'
-            )
-
-    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 testGetParentFromUnwrapped(self):
-        from zope.traversing.api import getParent
-        self.assertRaises(
-            TypeError,
-            getParent,
-            self.unwrapped_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'/',
-                '/',
-            ),
-        )
-
-        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_suite():
-    return makeSuite(Test)
-
-if __name__=='__main__':
-    main(defaultTest='test_suite')

Copied: zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_conveniencefunctions.py (from rev 95959, zope.traversing/trunk/src/zope/traversing/tests/test_conveniencefunctions.py)
===================================================================
--- zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_conveniencefunctions.py	                        (rev 0)
+++ zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_conveniencefunctions.py	2009-02-02 12:25:12 UTC (rev 95965)
@@ -0,0 +1,360 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Test traversal convenience functions.
+
+$Id$
+"""
+from unittest import TestCase, main, makeSuite
+
+import zope.component
+from zope.interface import directlyProvides
+from zope.location.traversing import LocationPhysicallyLocatable
+from zope.location.interfaces \
+    import ILocationInfo, IRoot, LocationError, ITraverser
+from zope.security.proxy import Proxy
+from zope.security.checker import selectChecker
+from zope.traversing.adapters import Traverser, DefaultTraversable
+from zope.traversing.interfaces import ITraversable
+
+from zope.app.component.testing import PlacefulSetup
+from zope.container.contained import contained
+
+class C(object):
+    __parent__ = None
+    __name__ = None
+    def __init__(self, name):
+        self.name = name
+
+def _proxied(*args):
+    return Proxy(args, selectChecker(args))
+
+
+class Test(PlacefulSetup, TestCase):
+
+    def setUp(self):
+        PlacefulSetup.setUp(self)
+        # Build up a wrapper chain
+        root = C('root')
+        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)
+
+    def testTraverse(self):
+        from zope.traversing.api import traverse
+        self.assertEqual(
+            traverse(self.item, '/folder/item'),
+            self.tr.traverse('/folder/item')
+            )
+
+    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')
+            )
+
+        # 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 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 testGetParentFromUnwrapped(self):
+        from zope.traversing.api import getParent
+        self.assertRaises(
+            TypeError,
+            getParent,
+            self.unwrapped_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'/',
+                '/',
+            ),
+        )
+
+        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_suite():
+    return makeSuite(Test)
+
+if __name__=='__main__':
+    main(defaultTest='test_suite')

Deleted: zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_physicallocationadapters.py
===================================================================
--- zope.traversing/trunk/src/zope/traversing/tests/test_physicallocationadapters.py	2009-02-02 06:01:56 UTC (rev 95956)
+++ zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_physicallocationadapters.py	2009-02-02 12:25:12 UTC (rev 95965)
@@ -1,65 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Physical Location Adapter Tests
-
-$Id$
-"""
-from unittest import TestCase, main, makeSuite
-
-import zope.traversing.testing
-from zope.traversing.interfaces import IContainmentRoot, IPhysicallyLocatable
-from zope.interface import implements
-from zope.testing.cleanup import CleanUp
-
-from zope.app.testing import setup
-from zope.container.contained import contained
-from zope.site.site import SiteManagerContainer
-
-
-class Root(object):
-    implements(IContainmentRoot)
-
-    __parent__ = None
-
-
-class C(object):
-    pass
-
-
-class Test(CleanUp, TestCase):
-
-    def test(self):
-        zope.traversing.testing.setUp()
-
-        root = Root()
-        f1 = contained(C(), root, name='f1')
-        f2 = contained(SiteManagerContainer(), f1, name='f2')
-        f3 = contained(C(), f2, name='f3')
-        
-        adapter = IPhysicallyLocatable(f3)
-
-        self.assertEqual(adapter.getPath(), '/f1/f2/f3')
-        self.assertEqual(adapter.getName(), 'f3')
-        self.assertEqual(adapter.getRoot(), root)
-        self.assertEqual(adapter.getNearestSite(), root)
-
-        setup.createSiteManager(f2)
-        self.assertEqual(adapter.getNearestSite(), f2)
-
-        
-def test_suite():
-    return makeSuite(Test)
-
-if __name__=='__main__':
-    main(defaultTest='test_suite')

Copied: zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_physicallocationadapters.py (from rev 95959, zope.traversing/trunk/src/zope/traversing/tests/test_physicallocationadapters.py)
===================================================================
--- zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_physicallocationadapters.py	                        (rev 0)
+++ zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_physicallocationadapters.py	2009-02-02 12:25:12 UTC (rev 95965)
@@ -0,0 +1,65 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Physical Location Adapter Tests
+
+$Id$
+"""
+from unittest import TestCase, main, makeSuite
+
+import zope.traversing.testing
+from zope.location.interfaces import ILocationInfo, IRoot
+from zope.interface import implements
+from zope.testing.cleanup import CleanUp
+
+from zope.app.testing import setup
+from zope.container.contained import contained
+from zope.site.site import SiteManagerContainer
+
+
+class Root(object):
+    implements(IRoot)
+
+    __parent__ = None
+
+
+class C(object):
+    pass
+
+
+class Test(CleanUp, TestCase):
+
+    def test(self):
+        zope.traversing.testing.setUp()
+
+        root = Root()
+        f1 = contained(C(), root, name='f1')
+        f2 = contained(SiteManagerContainer(), f1, name='f2')
+        f3 = contained(C(), f2, name='f3')
+        
+        adapter = ILocationInfo(f3)
+
+        self.assertEqual(adapter.getPath(), '/f1/f2/f3')
+        self.assertEqual(adapter.getName(), 'f3')
+        self.assertEqual(adapter.getRoot(), root)
+        self.assertEqual(adapter.getNearestSite(), root)
+
+        setup.createSiteManager(f2)
+        self.assertEqual(adapter.getNearestSite(), f2)
+
+        
+def test_suite():
+    return makeSuite(Test)
+
+if __name__=='__main__':
+    main(defaultTest='test_suite')

Deleted: zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_skin.py
===================================================================
--- zope.traversing/trunk/src/zope/traversing/tests/test_skin.py	2009-02-02 06:01:56 UTC (rev 95956)
+++ zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_skin.py	2009-02-02 12:25:12 UTC (rev 95965)
@@ -1,62 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE
-#
-##############################################################################
-"""Test skin traversal.
-
-$Id$
-"""
-from unittest import TestCase, main, makeSuite
-
-import zope.component
-from zope.testing.cleanup import CleanUp
-from zope.interface import Interface, directlyProvides
-from zope.publisher.interfaces.browser import IBrowserSkinType
-
-class FauxRequest(object):
-    def shiftNameToApplication(self):
-        self.shifted = 1
-
-class IFoo(Interface):
-    pass
-directlyProvides(IFoo, IBrowserSkinType)
-
-
-class Test(CleanUp, TestCase):
-
-    def setUp(self):
-        super(Test, self).setUp()
-        zope.component.provideUtility(IFoo, IBrowserSkinType, name='foo')
-
-    def test(self):
-        from zope.traversing.namespace import skin
-
-        request = FauxRequest()
-        ob = object()
-        ob2 = skin(ob, request).traverse('foo', ())
-        self.assertEqual(ob, ob2)
-        self.assert_(IFoo.providedBy(request))
-        self.assertEqual(request.shifted, 1)
-
-    def test_missing_skin(self):
-        from zope.traversing.namespace import skin
-        from zope.traversing.interfaces import TraversalError
-        request = FauxRequest()
-        ob = object()
-        traverser = skin(ob, request)
-        self.assertRaises(TraversalError, traverser.traverse, 'bar', ())
-
-def test_suite():
-    return makeSuite(Test)
-
-if __name__=='__main__':
-    main(defaultTest='test_suite')

Copied: zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_skin.py (from rev 95959, zope.traversing/trunk/src/zope/traversing/tests/test_skin.py)
===================================================================
--- zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_skin.py	                        (rev 0)
+++ zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_skin.py	2009-02-02 12:25:12 UTC (rev 95965)
@@ -0,0 +1,62 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+"""Test skin traversal.
+
+$Id$
+"""
+from unittest import TestCase, main, makeSuite
+
+import zope.component
+from zope.testing.cleanup import CleanUp
+from zope.interface import Interface, directlyProvides
+from zope.publisher.interfaces.browser import IBrowserSkinType
+
+class FauxRequest(object):
+    def shiftNameToApplication(self):
+        self.shifted = 1
+
+class IFoo(Interface):
+    pass
+directlyProvides(IFoo, IBrowserSkinType)
+
+
+class Test(CleanUp, TestCase):
+
+    def setUp(self):
+        super(Test, self).setUp()
+        zope.component.provideUtility(IFoo, IBrowserSkinType, name='foo')
+
+    def test(self):
+        from zope.traversing.namespace import skin
+
+        request = FauxRequest()
+        ob = object()
+        ob2 = skin(ob, request).traverse('foo', ())
+        self.assertEqual(ob, ob2)
+        self.assert_(IFoo.providedBy(request))
+        self.assertEqual(request.shifted, 1)
+
+    def test_missing_skin(self):
+        from zope.traversing.namespace import skin
+        from zope.location.interfaces import LocationError
+        request = FauxRequest()
+        ob = object()
+        traverser = skin(ob, request)
+        self.assertRaises(LocationError, traverser.traverse, 'bar', ())
+
+def test_suite():
+    return makeSuite(Test)
+
+if __name__=='__main__':
+    main(defaultTest='test_suite')

Deleted: zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_traverser.py
===================================================================
--- zope.traversing/trunk/src/zope/traversing/tests/test_traverser.py	2009-02-02 06:01:56 UTC (rev 95956)
+++ zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_traverser.py	2009-02-02 12:25:12 UTC (rev 95965)
@@ -1,262 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Traverser Adapter tests.
-
-$Id$
-"""
-import unittest
-
-import zope.component
-from zope.interface import directlyProvides, implementedBy
-from zope.interface.verify import verifyClass
-from zope.location.traversing import LocationPhysicallyLocatable
-from zope.security.interfaces import Unauthorized
-from zope.security.checker \
-    import ProxyFactory, defineChecker, CheckerPublic, Checker
-from zope.security.management import newInteraction, endInteraction
-
-from zope.traversing.adapters import Traverser, DefaultTraversable
-from zope.traversing.adapters import RootPhysicallyLocatable
-from zope.traversing.interfaces import ITraverser, ITraversable
-from zope.traversing.interfaces import IPhysicallyLocatable
-from zope.traversing.interfaces import IContainmentRoot, TraversalError
-
-from zope.app.component.testing import PlacefulSetup
-from zope.container.contained import Contained, contained
-
-class ParticipationStub(object):
-
-    def __init__(self, principal):
-        self.principal = principal
-        self.interaction = None
-
-class C(Contained):
-    def __init__(self, name):
-        self.name = name
-
-class TraverserTests(PlacefulSetup, unittest.TestCase):
-
-    def setUp(self):
-        PlacefulSetup.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.failUnless(ITraverser.providedBy(self.tr))
-
-    def testVerifyInterfaces(self):
-        for interface in implementedBy(Traverser):
-            verifyClass(interface, Traverser)
-
-class UnrestrictedNoTraverseTests(unittest.TestCase):
-    def setUp(self):
-        self.root = root = C('root')
-        directlyProvides(self.root, IContainmentRoot)
-        self.folder = folder = C('folder')
-        self.item = item = C('item')
-
-        root.folder = folder
-        folder.item = item
-
-        self.tr = Traverser(root)
-
-    def testNoTraversable(self):
-        self.assertRaises(TraversalError, self.tr.traverse,
-                          'folder')
-
-class UnrestrictedTraverseTests(PlacefulSetup, unittest.TestCase):
-    def setUp(self):
-        PlacefulSetup.setUp(self)
-
-        zope.component.provideAdapter(DefaultTraversable, (None,), ITraversable)
-        zope.component.provideAdapter(LocationPhysicallyLocatable, (None,),
-                                      IPhysicallyLocatable)
-        zope.component.provideAdapter(RootPhysicallyLocatable,
-                                      (IContainmentRoot,), IPhysicallyLocatable)
-
-        # Build up a wrapper chain
-        self.root = root = C('root')
-        directlyProvides(self.root, IContainmentRoot)
-        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(TraversalError, 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(TraversalError, tr.traverse, 'foo/baz')
-
-
-class RestrictedTraverseTests(PlacefulSetup, unittest.TestCase):
-    _oldPolicy = None
-    _deniedNames = ()
-
-    def setUp(self):
-        PlacefulSetup.setUp(self)
-
-        zope.component.provideAdapter(DefaultTraversable, (None,), ITraversable)
-        zope.component.provideAdapter(LocationPhysicallyLocatable, (None,),
-                                      IPhysicallyLocatable)
-        zope.component.provideAdapter(RootPhysicallyLocatable,
-                                      (IContainmentRoot,), IPhysicallyLocatable)
-
-        self.root = root = C('root')
-        directlyProvides(root, IContainmentRoot)
-        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(ProxyFactory(root))
-
-    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)
-
-    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)
-
-class DefaultTraversableTests(unittest.TestCase):
-    def testImplementsITraversable(self):
-        self.failUnless(ITraversable.providedBy(DefaultTraversable(None)))
-
-    def testVerifyInterfaces(self):
-        for interface in implementedBy(DefaultTraversable):
-            verifyClass(interface, DefaultTraversable)
-
-    def testAttributeTraverse(self):
-        root = C('root')
-        item = C('item')
-        root.item = item
-        df = DefaultTraversable(root)
-
-        further = []
-        next = df.traverse('item', further)
-        self.failUnless(next is item)
-        self.assertEquals(further, [])
-
-    def testDictionaryTraverse(self):
-        dict = {}
-        foo = C('foo')
-        dict['foo'] = foo
-        df = DefaultTraversable(dict)
-
-        further = []
-        next = df.traverse('foo', further)
-        self.failUnless(next is foo)
-        self.assertEquals(further, [])
-
-    def testNotFound(self):
-        df = DefaultTraversable(C('dummy'))
-
-        self.assertRaises(TraversalError, df.traverse, 'bar', [])
-
-def test_suite():
-    loader = unittest.TestLoader()
-    suite = loader.loadTestsFromTestCase(TraverserTests)
-    suite.addTest(loader.loadTestsFromTestCase(DefaultTraversableTests))
-    suite.addTest(loader.loadTestsFromTestCase(UnrestrictedNoTraverseTests))
-    suite.addTest(loader.loadTestsFromTestCase(UnrestrictedTraverseTests))
-    suite.addTest(loader.loadTestsFromTestCase(RestrictedTraverseTests))
-    return suite
-
-if __name__=='__main__':
-    unittest.TextTestRunner().run(test_suite())

Copied: zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_traverser.py (from rev 95959, zope.traversing/trunk/src/zope/traversing/tests/test_traverser.py)
===================================================================
--- zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_traverser.py	                        (rev 0)
+++ zope.traversing/tags/3.5.1/src/zope/traversing/tests/test_traverser.py	2009-02-02 12:25:12 UTC (rev 95965)
@@ -0,0 +1,257 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Traverser Adapter tests.
+
+$Id$
+"""
+import unittest
+
+import zope.component
+from zope.interface import directlyProvides, implementedBy
+from zope.interface.verify import verifyClass
+from zope.location.traversing import LocationPhysicallyLocatable
+from zope.location.interfaces \
+    import ILocationInfo, IRoot, LocationError, ITraverser
+from zope.security.interfaces import Unauthorized
+from zope.security.checker \
+    import ProxyFactory, defineChecker, CheckerPublic, Checker
+from zope.security.management import newInteraction, endInteraction
+
+from zope.traversing.adapters import Traverser, DefaultTraversable
+from zope.traversing.interfaces import ITraversable
+
+from zope.app.component.testing import PlacefulSetup
+from zope.container.contained import Contained, contained
+
+class ParticipationStub(object):
+
+    def __init__(self, principal):
+        self.principal = principal
+        self.interaction = None
+
+class C(Contained):
+    def __init__(self, name):
+        self.name = name
+
+class TraverserTests(PlacefulSetup, unittest.TestCase):
+
+    def setUp(self):
+        PlacefulSetup.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.failUnless(ITraverser.providedBy(self.tr))
+
+    def testVerifyInterfaces(self):
+        for interface in implementedBy(Traverser):
+            verifyClass(interface, Traverser)
+
+class UnrestrictedNoTraverseTests(unittest.TestCase):
+    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)
+
+    def testNoTraversable(self):
+        self.assertRaises(LocationError, self.tr.traverse,
+                          'folder')
+
+class UnrestrictedTraverseTests(PlacefulSetup, unittest.TestCase):
+    def setUp(self):
+        PlacefulSetup.setUp(self)
+
+        zope.component.provideAdapter(DefaultTraversable, (None,), ITraversable)
+        zope.component.provideAdapter(LocationPhysicallyLocatable, (None,),
+                                      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')
+
+
+class RestrictedTraverseTests(PlacefulSetup, unittest.TestCase):
+    _oldPolicy = None
+    _deniedNames = ()
+
+    def setUp(self):
+        PlacefulSetup.setUp(self)
+
+        zope.component.provideAdapter(DefaultTraversable, (None,), ITraversable)
+        zope.component.provideAdapter(LocationPhysicallyLocatable, (None,),
+                                      ILocationInfo)
+
+        self.root = root = C('root')
+        directlyProvides(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(ProxyFactory(root))
+
+    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)
+
+    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)
+
+class DefaultTraversableTests(unittest.TestCase):
+    def testImplementsITraversable(self):
+        self.failUnless(ITraversable.providedBy(DefaultTraversable(None)))
+
+    def testVerifyInterfaces(self):
+        for interface in implementedBy(DefaultTraversable):
+            verifyClass(interface, DefaultTraversable)
+
+    def testAttributeTraverse(self):
+        root = C('root')
+        item = C('item')
+        root.item = item
+        df = DefaultTraversable(root)
+
+        further = []
+        next = df.traverse('item', further)
+        self.failUnless(next is item)
+        self.assertEquals(further, [])
+
+    def testDictionaryTraverse(self):
+        dict = {}
+        foo = C('foo')
+        dict['foo'] = foo
+        df = DefaultTraversable(dict)
+
+        further = []
+        next = df.traverse('foo', further)
+        self.failUnless(next is foo)
+        self.assertEquals(further, [])
+
+    def testNotFound(self):
+        df = DefaultTraversable(C('dummy'))
+
+        self.assertRaises(LocationError, df.traverse, 'bar', [])
+
+def test_suite():
+    loader = unittest.TestLoader()
+    suite = loader.loadTestsFromTestCase(TraverserTests)
+    suite.addTest(loader.loadTestsFromTestCase(DefaultTraversableTests))
+    suite.addTest(loader.loadTestsFromTestCase(UnrestrictedNoTraverseTests))
+    suite.addTest(loader.loadTestsFromTestCase(UnrestrictedTraverseTests))
+    suite.addTest(loader.loadTestsFromTestCase(RestrictedTraverseTests))
+    return suite
+
+if __name__=='__main__':
+    unittest.TextTestRunner().run(test_suite())



More information about the Checkins mailing list