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

Dan Korostelev nadako at gmail.com
Mon Feb 2 07:16:54 EST 2009


Log message for revision 95961:
  Tag 3.5.1

Changed:
  A   zope.location/tags/3.5.1/
  D   zope.location/tags/3.5.1/CHANGES.txt
  A   zope.location/tags/3.5.1/CHANGES.txt
  U   zope.location/tags/3.5.1/setup.py
  D   zope.location/tags/3.5.1/src/
  A   zope.location/tags/3.5.1/src/
  D   zope.location/tags/3.5.1/src/zope/location/interfaces.py
  A   zope.location/tags/3.5.1/src/zope/location/interfaces.py
  D   zope.location/tags/3.5.1/src/zope/location/location.txt
  A   zope.location/tags/3.5.1/src/zope/location/location.txt
  D   zope.location/tags/3.5.1/src/zope/location/pickling.py
  A   zope.location/tags/3.5.1/src/zope/location/pickling.py
  D   zope.location/tags/3.5.1/src/zope/location/traversing.py
  A   zope.location/tags/3.5.1/src/zope/location/traversing.py

-=-
Deleted: zope.location/tags/3.5.1/CHANGES.txt
===================================================================
--- zope.location/trunk/CHANGES.txt	2009-02-02 10:59:25 UTC (rev 95958)
+++ zope.location/tags/3.5.1/CHANGES.txt	2009-02-02 12:16:54 UTC (rev 95961)
@@ -1,32 +0,0 @@
-=======
-CHANGES
-=======
-
-3.5.1 (unreleased)
-------------------
-
-- Improve test coverage.
-
-- The new ``getParents`` method was extracted from ``zope.traversing``
-  and added to ILocationInfo interface in the previous release. Custom
-  ILocationInfo implementations should make sure they have this method
-  as well. That method is already used in ``zope.traversing.api.getParents``
-  function.
-
-- Make ``getName`` of ILocationInfo always return empty string for
-  the IRoot object, like RootPhysicallyLocatable from zope.traversing
-  did, making the latter one obsolete.
-
-- Change package mailing list address to zope-dev at zope.org instead
-  of retired zope3-dev at zope.org.
-
-3.5.0 (2009-01-31)
-------------------
-
-- Reverse the dependency between zope.location and zope.traversing. This
-  also causes the dependency to various other packages go away.
-
-3.4.0 (2007-10-02)
-------------------
-
-- Initial release independent of the main Zope tree.

Copied: zope.location/tags/3.5.1/CHANGES.txt (from rev 95960, zope.location/trunk/CHANGES.txt)
===================================================================
--- zope.location/tags/3.5.1/CHANGES.txt	                        (rev 0)
+++ zope.location/tags/3.5.1/CHANGES.txt	2009-02-02 12:16:54 UTC (rev 95961)
@@ -0,0 +1,34 @@
+=======
+CHANGES
+=======
+
+3.5.1 (2009-02-02)
+------------------
+
+- Improve test coverage.
+
+- The new ``getParents`` method was extracted from ``zope.traversing``
+  and added to ILocationInfo interface in the previous release. Custom
+  ILocationInfo implementations should make sure they have this method
+  as well. That method is already used in ``zope.traversing.api.getParents``
+  function.
+
+- Make ``getName`` of LocationPhysicallyLocatable always return empty
+  string for the IRoot object, like RootPhysicallyLocatable from
+  ``zope.traversing`` did. So, now LocationPhysicallyLocatable is
+  fully compatible with RootPhysicallyLocatable, making the latter one
+  obsolete.
+
+- Change package mailing list address to zope-dev at zope.org instead
+  of retired zope3-dev at zope.org.
+
+3.5.0 (2009-01-31)
+------------------
+
+- Reverse the dependency between zope.location and zope.traversing. This
+  also causes the dependency to various other packages go away.
+
+3.4.0 (2007-10-02)
+------------------
+
+- Initial release independent of the main Zope tree.

Modified: zope.location/tags/3.5.1/setup.py
===================================================================
--- zope.location/trunk/setup.py	2009-02-02 10:59:25 UTC (rev 95958)
+++ zope.location/tags/3.5.1/setup.py	2009-02-02 12:16:54 UTC (rev 95961)
@@ -21,7 +21,7 @@
     return text
 
 setup(name='zope.location',
-      version = '3.5.1dev',
+      version = '3.5.1',
       author='Zope Corporation and Contributors',
       author_email='zope-dev at zope.org',
       description='Zope Location',

Deleted: zope.location/tags/3.5.1/src/zope/location/interfaces.py
===================================================================
--- zope.location/trunk/src/zope/location/interfaces.py	2009-02-02 06:01:56 UTC (rev 95956)
+++ zope.location/tags/3.5.1/src/zope/location/interfaces.py	2009-02-02 12:16:54 UTC (rev 95961)
@@ -1,143 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003-2009 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.
-#
-##############################################################################
-"""Location framework interfaces
-
-$Id$
-"""
-__docformat__ = 'restructuredtext'
-
-import zope.interface
-import zope.schema
-
-_RAISE_KEYERROR = object()
-
-
-class ILocation(zope.interface.Interface):
-    """Objects that can be located in a hierachy.
-
-    Given a parent and a name an object can be located within that parent. The
-    locatable object's `__name__` and `__parent__` attributes store this
-    information.
-
-    Located objects form a hierarchy that can be used to build file-system-like
-    structures. For example in Zope `ILocation` is used to build URLs and to
-    support security machinery.
-
-    To retrieve an object from its parent using its name, the `ISublocation`
-    interface provides the `sublocations` method to iterate over all objects
-    located within the parent. The object searched for can be found by reading
-    each sublocation's __name__ attribute.
-
-    """
-
-    __parent__ = zope.interface.Attribute("The parent in the location hierarchy.")
-
-    __name__ = zope.schema.TextLine(
-        title=u"The name within the parent",
-        description=u"The object can be looked up from the parent's "
-            "sublocations using this name.",
-        required=False,
-        default=None)
-
-
-class ILocationInfo(zope.interface.Interface):
-    """Provides supplemental information for located objects.
-
-    Requires that the object has been given a location in a hierarchy.
-
-    """
-
-    def getRoot():
-        """Return the root object of the hierarchy."""
-
-    def getPath():
-        """Return the physical path to the object as a string.
-
-        Uses '/' as the path segment separator.
-
-        """
-
-    def getName():
-        """Return the last segment of the physical path."""
-
-    def getNearestSite():
-        """Return the site the object is contained in
-
-        If the object is a site, the object itself is returned.
-
-        """
-
-
-class ISublocations(zope.interface.Interface):
-    """Provide access to sublocations of an object.
-
-    All objects with the same parent object are called the ``sublocations`` of
-    that parent.
-
-    """
-
-    def sublocations():
-        """Return an iterable of the object's sublocations."""
-
-
-class IRoot(zope.interface.Interface):
-    """Marker interface to designate root objects within a location hierarchy.
-    """
-
-
-
-
-class ITraverser(zope.interface.Interface):
-    """Provide traverse features"""
-
-    # XXX This is used like a utility but implemented as an adapter: The
-    # traversal policy is only implemented once and repeated for all objects
-    # along the path.
-
-    def traverse(path, default=_RAISE_KEYERROR):
-        """Return an object given a path.
-
-        Path is either an immutable sequence of strings or a slash ('/')
-        delimited string.
-
-        If the first string in the path sequence is an empty string, or the
-        path begins with a '/', start at the root. Otherwise the path is
-        relative to the current context.
-
-        If the object is not found, return 'default' argument.
-
-        """
-
-
-class LocationError(KeyError, LookupError):
-    """There is no object for a given location."""
-
-
-class IPossibleSite(zope.interface.Interface):
-    """An object that could be a site.
-    """
-
-    def setSiteManager(sitemanager):
-        """Sets the site manager for this object.
-        """
-
-    def getSiteManager():
-        """Returns the site manager contained in this object.
-
-        If there isn't a site manager, raise a component lookup.
-        """
-
-
-class ISite(IPossibleSite):
-    """Marker interface to indicate that we have a site"""

Copied: zope.location/tags/3.5.1/src/zope/location/interfaces.py (from rev 95958, zope.location/trunk/src/zope/location/interfaces.py)
===================================================================
--- zope.location/tags/3.5.1/src/zope/location/interfaces.py	                        (rev 0)
+++ zope.location/tags/3.5.1/src/zope/location/interfaces.py	2009-02-02 12:16:54 UTC (rev 95961)
@@ -0,0 +1,152 @@
+##############################################################################
+#
+# Copyright (c) 2003-2009 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.
+#
+##############################################################################
+"""Location framework interfaces
+
+$Id$
+"""
+__docformat__ = 'restructuredtext'
+
+import zope.interface
+import zope.schema
+
+_RAISE_KEYERROR = object()
+
+
+class ILocation(zope.interface.Interface):
+    """Objects that can be located in a hierachy.
+
+    Given a parent and a name an object can be located within that parent. The
+    locatable object's `__name__` and `__parent__` attributes store this
+    information.
+
+    Located objects form a hierarchy that can be used to build file-system-like
+    structures. For example in Zope `ILocation` is used to build URLs and to
+    support security machinery.
+
+    To retrieve an object from its parent using its name, the `ISublocation`
+    interface provides the `sublocations` method to iterate over all objects
+    located within the parent. The object searched for can be found by reading
+    each sublocation's __name__ attribute.
+
+    """
+
+    __parent__ = zope.interface.Attribute("The parent in the location hierarchy.")
+
+    __name__ = zope.schema.TextLine(
+        title=u"The name within the parent",
+        description=u"The object can be looked up from the parent's "
+            "sublocations using this name.",
+        required=False,
+        default=None)
+
+
+class ILocationInfo(zope.interface.Interface):
+    """Provides supplemental information for located objects.
+
+    Requires that the object has been given a location in a hierarchy.
+
+    """
+
+    def getRoot():
+        """Return the root object of the hierarchy."""
+
+    def getPath():
+        """Return the physical path to the object as a string.
+
+        Uses '/' as the path segment separator.
+
+        """
+
+    def getParents():
+        """Returns a list starting with the object's parent followed by
+        each of its parents.
+
+        Raises a TypeError if the object is not connected to a containment
+        root.
+        
+        """
+
+    def getName():
+        """Return the last segment of the physical path."""
+
+    def getNearestSite():
+        """Return the site the object is contained in
+
+        If the object is a site, the object itself is returned.
+
+        """
+
+
+class ISublocations(zope.interface.Interface):
+    """Provide access to sublocations of an object.
+
+    All objects with the same parent object are called the ``sublocations`` of
+    that parent.
+
+    """
+
+    def sublocations():
+        """Return an iterable of the object's sublocations."""
+
+
+class IRoot(zope.interface.Interface):
+    """Marker interface to designate root objects within a location hierarchy.
+    """
+
+
+
+
+class ITraverser(zope.interface.Interface):
+    """Provide traverse features"""
+
+    # XXX This is used like a utility but implemented as an adapter: The
+    # traversal policy is only implemented once and repeated for all objects
+    # along the path.
+
+    def traverse(path, default=_RAISE_KEYERROR):
+        """Return an object given a path.
+
+        Path is either an immutable sequence of strings or a slash ('/')
+        delimited string.
+
+        If the first string in the path sequence is an empty string, or the
+        path begins with a '/', start at the root. Otherwise the path is
+        relative to the current context.
+
+        If the object is not found, return 'default' argument.
+
+        """
+
+
+class LocationError(KeyError, LookupError):
+    """There is no object for a given location."""
+
+
+class IPossibleSite(zope.interface.Interface):
+    """An object that could be a site.
+    """
+
+    def setSiteManager(sitemanager):
+        """Sets the site manager for this object.
+        """
+
+    def getSiteManager():
+        """Returns the site manager contained in this object.
+
+        If there isn't a site manager, raise a component lookup.
+        """
+
+
+class ISite(IPossibleSite):
+    """Marker interface to indicate that we have a site"""

Deleted: zope.location/tags/3.5.1/src/zope/location/location.txt
===================================================================
--- zope.location/trunk/src/zope/location/location.txt	2009-02-02 06:01:56 UTC (rev 95956)
+++ zope.location/tags/3.5.1/src/zope/location/location.txt	2009-02-02 12:16:54 UTC (rev 95961)
@@ -1,153 +0,0 @@
-========
-Location
-========
-
-Location Base Class
--------------------
-
-The `Location` base class is a stupid mix-in that defines `__parent__` and
-`__name__` attributes.
-
-Usage within an Object field:
-
->>> from zope.interface import implements, Interface
->>> from zope.schema import Object
->>> from zope.schema.fieldproperty import FieldProperty
->>> from zope.location.interfaces import ILocation
->>> from zope.location.location import Location
-
->>> class IA(Interface):
-...     location = Object(schema=ILocation, required=False, default=None)
->>> class A(object):
-...     implements(IA)
-...     location = FieldProperty(IA['location'])
-
->>> a = A()
->>> a.location = Location()
-
->>> loc = Location(); loc.__name__ = u'foo'
->>> a.location = loc
-
->>> loc = Location(); loc.__name__ = None
->>> a.location = loc
-
->>> loc = Location(); loc.__name__ = 'foo'
->>> a.location = loc
-Traceback (most recent call last):
-...
-WrongContainedType: [WrongType('foo', <type 'unicode'>)]
-
-
-The `inside` Function
----------------------
-
-The `inside` function tells if l1 is inside l2.  L1 is inside l2 if l2 is an
-ancestor of l1.
-
->>> o1 = Location()
->>> o2 = Location(); o2.__parent__ = o1
->>> o3 = Location(); o3.__parent__ = o2
->>> o4 = Location(); o4.__parent__ = o3
-
->>> from zope.location.location import inside
->>> inside(o1, o1)
-1
->>> inside(o2, o1)
-1
->>> inside(o3, o1)
-1
->>> inside(o4, o1)
-1
-
->>> inside(o1, o4)
-0
-
->>> inside(o1, None)
-0
-
-
-LocationProxy
--------------
-
-The LocationProxy is a non-picklable proxy that can be put around
-objects that don't implement `ILocation`.
-
->>> from zope.location.location import LocationProxy
->>> l = [1, 2, 3]
->>> ILocation.providedBy(l)
-False
->>> p = LocationProxy(l, "Dad", "p")
->>> p
-[1, 2, 3]
->>> ILocation.providedBy(p)
-True
->>> p.__parent__
-'Dad'
->>> p.__name__
-'p'
-
->>> import pickle
->>> p2 = pickle.dumps(p)
-Traceback (most recent call last):
-...
-TypeError: Not picklable
-
-Proxies should get their doc strings from the object they proxy:
-
->>> p.__doc__ == l.__doc__
-True
-
-
-The `located` function
-----------------------
-
-`located` locates an object in another and returns it:
-
->>> from zope.location.location import located
->>> a = Location()
->>> parent = Location()
->>> a_located = located(a, parent, 'a')
->>> a_located is a
-True
->>> a_located.__parent__ is parent
-True
->>> a_located.__name__
-'a'
-
-If we locate the object again, nothing special happens:
-
->>> a_located_2 = located(a_located, parent, 'a')
->>> a_located_2 is a_located
-True
-
-
-If the object does not provide ILocation an adapter can be provided:
-
->>> import zope.interface
->>> import zope.component
->>> sm = zope.component.getGlobalSiteManager()
->>> sm.registerAdapter(LocationProxy, required=(zope.interface.Interface,))
-
->>> l = [1, 2, 3]
->>> parent = Location()
->>> l_located = located(l, parent, 'l')
->>> l_located.__parent__ is parent
-True
->>> l_located.__name__
-'l'
->>> l_located is l
-False
->>> type(l_located)
-<class 'zope.location.location.LocationProxy'>
->>> l_located_2 = located(l_located, parent, 'l')
->>> l_located_2 is l_located
-True
-
-When changing the name, we still do not get a different proxied object:
-
->>> l_located_3 = located(l_located, parent, 'new-name')
->>> l_located_3 is l_located_2
-True
-
->>> sm.unregisterAdapter(LocationProxy, required=(zope.interface.Interface,))
-True

Copied: zope.location/tags/3.5.1/src/zope/location/location.txt (from rev 95958, zope.location/trunk/src/zope/location/location.txt)
===================================================================
--- zope.location/tags/3.5.1/src/zope/location/location.txt	                        (rev 0)
+++ zope.location/tags/3.5.1/src/zope/location/location.txt	2009-02-02 12:16:54 UTC (rev 95961)
@@ -0,0 +1,191 @@
+========
+Location
+========
+
+Location Base Class
+-------------------
+
+The `Location` base class is a stupid mix-in that defines `__parent__` and
+`__name__` attributes.
+
+Usage within an Object field:
+
+  >>> from zope.interface import implements, Interface
+  >>> from zope.schema import Object
+  >>> from zope.schema.fieldproperty import FieldProperty
+  >>> from zope.location.interfaces import ILocation
+  >>> from zope.location.location import Location
+  
+  >>> class IA(Interface):
+  ...     location = Object(schema=ILocation, required=False, default=None)
+  >>> class A(object):
+  ...     implements(IA)
+  ...     location = FieldProperty(IA['location'])
+  
+  >>> a = A()
+  >>> a.location = Location()
+  
+  >>> loc = Location(); loc.__name__ = u'foo'
+  >>> a.location = loc
+  
+  >>> loc = Location(); loc.__name__ = None
+  >>> a.location = loc
+  
+  >>> loc = Location(); loc.__name__ = 'foo'
+  >>> a.location = loc
+  Traceback (most recent call last):
+  ...
+  WrongContainedType: [WrongType('foo', <type 'unicode'>)]
+
+
+The `inside` Function
+---------------------
+
+The `inside` function tells if l1 is inside l2.  L1 is inside l2 if l2 is an
+ancestor of l1.
+
+  >>> o1 = Location()
+  >>> o2 = Location(); o2.__parent__ = o1
+  >>> o3 = Location(); o3.__parent__ = o2
+  >>> o4 = Location(); o4.__parent__ = o3
+  
+  >>> from zope.location.location import inside
+
+  >>> inside(o1, o1)
+  True
+
+  >>> inside(o2, o1)
+  True
+
+  >>> inside(o3, o1)
+  True
+
+  >>> inside(o4, o1)
+  True
+  
+  >>> inside(o1, o4)
+  False
+  
+  >>> inside(o1, None)
+  False
+
+
+LocationProxy
+-------------
+
+The LocationProxy is a non-picklable proxy that can be put around
+objects that don't implement `ILocation`.
+
+  >>> from zope.location.location import LocationProxy
+  >>> l = [1, 2, 3]
+  >>> ILocation.providedBy(l)
+  False
+  >>> p = LocationProxy(l, "Dad", "p")
+  >>> p
+  [1, 2, 3]
+  >>> ILocation.providedBy(p)
+  True
+  >>> p.__parent__
+  'Dad'
+  >>> p.__name__
+  'p'
+  
+  >>> import pickle
+  >>> p2 = pickle.dumps(p)
+  Traceback (most recent call last):
+  ...
+  TypeError: Not picklable
+
+Proxies should get their doc strings from the object they proxy:
+
+  >>> p.__doc__ == l.__doc__
+  True
+
+If we get a "located class" somehow, its doc string well be available
+through proxy as well:
+
+  >>> class LocalClass(object):
+  ...     """This is class that can be located"""
+
+  >>> p = LocationProxy(LocalClass)
+  >>> p.__doc__ == LocalClass.__doc__
+  True
+
+LocationInterator
+-----------------
+
+This function allows us to iterate over object and all its parents.
+
+  >>> from zope.location.location import LocationIterator
+
+  >>> o1 = Location()
+  >>> o2 = Location()
+  >>> o3 = Location()
+  >>> o3.__parent__ = o2
+  >>> o2.__parent__ = o1
+
+  >>> iter = LocationIterator(o3)
+  >>> iter.next() is o3
+  True
+  >>> iter.next() is o2
+  True
+  >>> iter.next() is o1
+  True
+  >>> iter.next()
+  Traceback (most recent call last):
+  ...
+  StopIteration
+
+
+The `located` function
+----------------------
+
+`located` locates an object in another and returns it:
+
+  >>> from zope.location.location import located
+  >>> a = Location()
+  >>> parent = Location()
+  >>> a_located = located(a, parent, 'a')
+  >>> a_located is a
+  True
+  >>> a_located.__parent__ is parent
+  True
+  >>> a_located.__name__
+  'a'
+
+If we locate the object again, nothing special happens:
+
+  >>> a_located_2 = located(a_located, parent, 'a')
+  >>> a_located_2 is a_located
+  True
+
+If the object does not provide ILocation an adapter can be provided:
+
+  >>> import zope.interface
+  >>> import zope.component
+  >>> sm = zope.component.getGlobalSiteManager()
+  >>> sm.registerAdapter(LocationProxy, required=(zope.interface.Interface,))
+  
+  >>> l = [1, 2, 3]
+  >>> parent = Location()
+  >>> l_located = located(l, parent, 'l')
+  >>> l_located.__parent__ is parent
+  True
+  >>> l_located.__name__
+  'l'
+  >>> l_located is l
+  False
+  >>> type(l_located)
+  <class 'zope.location.location.LocationProxy'>
+  >>> l_located_2 = located(l_located, parent, 'l')
+  >>> l_located_2 is l_located
+  True
+
+When changing the name, we still do not get a different proxied object:
+
+  >>> l_located_3 = located(l_located, parent, 'new-name')
+  >>> l_located_3 is l_located_2
+  True
+
+  >>> sm.unregisterAdapter(LocationProxy, required=(zope.interface.Interface,))
+  True

Deleted: zope.location/tags/3.5.1/src/zope/location/pickling.py
===================================================================
--- zope.location/trunk/src/zope/location/pickling.py	2009-02-02 06:01:56 UTC (rev 95956)
+++ zope.location/tags/3.5.1/src/zope/location/pickling.py	2009-02-02 12:16:54 UTC (rev 95961)
@@ -1,238 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003-2009 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.
-#
-##############################################################################
-"""Location copying/pickling support
-
-$Id$
-"""
-__docformat__ = 'restructuredtext'
-
-import cPickle
-import tempfile
-import zope.interface
-import zope.location.interfaces
-
-from zope.location.interfaces import ILocation
-from zope.location.location import Location, inside
-from zope.location.traversing import LocationPhysicallyLocatable
-
-def locationCopy(loc):
-    r"""Return a copy of an object, and anything in it
-
-    If object in the location refer to objects outside of the
-    location, then the copies of the objects in the location refer to
-    the same outside objects.
-
-    For example, suppose we have an object (location) hierarchy like this::
-
-           o1
-          /  \
-        o2    o3
-        |     |
-        o4    o5
-
-    >>> o1 = Location()
-    >>> o1.o2 = Location(); o1.o2.__parent__ = o1
-    >>> o1.o3 = Location(); o1.o3.__parent__ = o1
-    >>> o1.o2.o4 = Location(); o1.o2.o4.__parent__ = o1.o2
-    >>> o1.o3.o5 = Location(); o1.o3.o5.__parent__ = o1.o3
-
-    In addition, o3 has a non-location reference to o4.
-
-    >>> o1.o3.o4 = o1.o2.o4
-
-    When we copy o3, we should get a copy of o3 and o5, with
-    references to o1 and o4.
-
-    >>> c3 = locationCopy(o1.o3)
-    >>> c3 is o1.o3
-    0
-    >>> c3.__parent__ is o1
-    1
-    >>> c3.o5 is o1.o3.o5
-    0
-    >>> c3.o5.__parent__ is c3
-    1
-    >>> c3.o4 is o1.o2.o4
-    1
-
-    """
-    tmp = tempfile.TemporaryFile()
-    persistent = CopyPersistent(loc)
-
-    # Pickle the object to a temporary file
-    pickler = cPickle.Pickler(tmp, 2)
-    pickler.persistent_id = persistent.id
-    pickler.dump(loc)
-
-    # Now load it back
-    tmp.seek(0)
-    unpickler = cPickle.Unpickler(tmp)
-    unpickler.persistent_load = persistent.load
-
-    return unpickler.load()
-
-
-class CopyPersistent(object):
-    """Persistence hooks for copying locations
-
-    See `locationCopy` above.
-
-    We get initialized with an initial location:
-
-    >>> o1 = Location()
-    >>> persistent = CopyPersistent(o1)
-
-    We provide an `id` function that returns None when given a non-location:
-
-    >>> persistent.id(42)
-
-    Or when given a location that is inside the initial location:
-
-    >>> persistent.id(o1)
-    >>> o2 = Location(); o2.__parent__ = o1
-    >>> persistent.id(o2)
-
-    But, if we get a location outside the original location, we assign
-    it an `id` and return the `id`:
-
-    >>> o3 = Location()
-    >>> id3 = persistent.id(o3)
-    >>> id3 is None
-    0
-    >>> o4 = Location()
-    >>> id4 = persistent.id(o4)
-    >>> id4 is None
-    0
-    >>> id4 is id3
-    0
-
-    If we ask for the `id` of an outside location more than once, we
-    always get the same `id` back:
-
-    >> persistent.id(o4) == id4
-    1
-
-    We also provide a load function that returns the objects for which
-    we were given ids:
-
-    >>> persistent.load(id3) is o3
-    1
-    >>> persistent.load(id4) is o4
-    1
-
-    """
-
-    def __init__(self, location):
-        self.location = location
-        self.pids_by_id = {}
-        self.others_by_pid = {}
-        self.load = self.others_by_pid.get
-
-    def id(self, object):
-        if ILocation.providedBy(object):
-            if not inside(object, self.location):
-                if id(object) in self.pids_by_id:
-                    return self.pids_by_id[id(object)]
-                pid = len(self.others_by_pid)
-
-                # The following is needed to overcome a bug
-                # in pickle.py. The pickle checks the boolean value
-                # of the id, rather than whether it is None.
-                pid += 1
-
-                self.pids_by_id[id(object)] = pid
-                self.others_by_pid[pid] = object
-                return pid
-
-        return None
-
-
-class PathPersistent(object):
-    """Persistence hooks for pickling locations
-
-    See `locationCopy` above.
-
-    Unlike copy persistent, we use paths for ids of outside locations
-    so that we can separate pickling and unpickling in time.  We have
-    to compute paths and traverse objects to load paths, but paths can
-    be stored for later use, unlike the ids used by `CopyPersistent`.
-
-    We require outside locations that can be adapted to `ITraversable`.
-    To simplify the example, we'll use a simple traversable location
-    defined in `zope.location.tests`, `TLocation`.
-
-    Normally, general adapters are used to make objects traversable.
-
-    We get initialized with an initial location:
-
-    >>> o1 = Location()
-    >>> persistent = PathPersistent(o1)
-
-    We provide an id function that returns None when given a non-location:
-
-    >>> persistent.id(42)
-
-    Or when given a location that is inside the initial location:
-
-    >>> persistent.id(o1)
-    >>> o2 = Location(); o2.__parent__ = o1
-    >>> persistent.id(o2)
-
-    But, if we get a location outside the original location, we return it's
-    path. To compute it's path, it must be rooted:
-
-    >>> from zope.location.tests import TLocation
-    >>> root = TLocation()
-    >>> zope.interface.directlyProvides(
-    ...     root, zope.location.interfaces.IRoot)
-    >>> o3 = TLocation()
-    >>> o3.__name__ = 'o3'
-    >>> o3.__parent__ = root
-    >>> root.o3 = o3
-    >>> persistent.id(o3)
-    u'/o3'
-
-    >>> o4 = TLocation()
-    >>> o4.__name__ = 'o4'
-    >>> o4.__parent__ = o3
-    >>> o3.o4 = o4
-    >>> persistent.id(o4)
-    u'/o3/o4'
-
-    We also provide a load function that returns objects by traversing
-    given paths.  It has to find the root based on the object given to
-    the constructor.  Therefore, that object must also be rooted:
-
-    >>> o1.__parent__ = root
-    >>> persistent.load(u'/o3') is o3
-    1
-    >>> persistent.load(u'/o3/o4') is o4
-    1
-
-    """
-
-    def __init__(self, location):
-        self.location = location
-
-    def id(self, object):
-        if ILocation.providedBy(object):
-            if not inside(object, self.location):
-                return LocationPhysicallyLocatable(object).getPath()
-        return None
-
-    def load(self, path):
-        if path[:1] != u'/':
-            raise ValueError("ZPersistent paths must be absolute", path)
-        root = LocationPhysicallyLocatable(self.location).getRoot()
-        return zope.location.interfaces.ITraverser(root).traverse(path[1:])

Copied: zope.location/tags/3.5.1/src/zope/location/pickling.py (from rev 95958, zope.location/trunk/src/zope/location/pickling.py)
===================================================================
--- zope.location/tags/3.5.1/src/zope/location/pickling.py	                        (rev 0)
+++ zope.location/tags/3.5.1/src/zope/location/pickling.py	2009-02-02 12:16:54 UTC (rev 95961)
@@ -0,0 +1,245 @@
+##############################################################################
+#
+# Copyright (c) 2003-2009 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.
+#
+##############################################################################
+"""Location copying/pickling support
+
+$Id$
+"""
+__docformat__ = 'restructuredtext'
+
+import cPickle
+import tempfile
+import zope.interface
+import zope.location.interfaces
+
+from zope.location.interfaces import ILocation
+from zope.location.location import Location, inside
+from zope.location.traversing import LocationPhysicallyLocatable
+
+def locationCopy(loc):
+    r"""Return a copy of an object, and anything in it
+
+    If object in the location refer to objects outside of the
+    location, then the copies of the objects in the location refer to
+    the same outside objects.
+
+    For example, suppose we have an object (location) hierarchy like this::
+
+           o1
+          /  \
+        o2    o3
+        |     |
+        o4    o5
+
+    >>> o1 = Location()
+    >>> o1.o2 = Location(); o1.o2.__parent__ = o1
+    >>> o1.o3 = Location(); o1.o3.__parent__ = o1
+    >>> o1.o2.o4 = Location(); o1.o2.o4.__parent__ = o1.o2
+    >>> o1.o3.o5 = Location(); o1.o3.o5.__parent__ = o1.o3
+
+    In addition, o3 has a non-location reference to o4.
+
+    >>> o1.o3.o4 = o1.o2.o4
+
+    When we copy o3, we should get a copy of o3 and o5, with
+    references to o1 and o4.
+
+    >>> c3 = locationCopy(o1.o3)
+    >>> c3 is o1.o3
+    False
+    >>> c3.__parent__ is o1
+    True
+    >>> c3.o5 is o1.o3.o5
+    False
+    >>> c3.o5.__parent__ is c3
+    True
+    >>> c3.o4 is o1.o2.o4
+    True
+
+    """
+    tmp = tempfile.TemporaryFile()
+    persistent = CopyPersistent(loc)
+
+    # Pickle the object to a temporary file
+    pickler = cPickle.Pickler(tmp, 2)
+    pickler.persistent_id = persistent.id
+    pickler.dump(loc)
+
+    # Now load it back
+    tmp.seek(0)
+    unpickler = cPickle.Unpickler(tmp)
+    unpickler.persistent_load = persistent.load
+
+    return unpickler.load()
+
+
+class CopyPersistent(object):
+    """Persistence hooks for copying locations
+
+    See `locationCopy` above.
+
+    We get initialized with an initial location:
+
+    >>> o1 = Location()
+    >>> persistent = CopyPersistent(o1)
+
+    We provide an `id` function that returns None when given a non-location:
+
+    >>> persistent.id(42)
+
+    Or when given a location that is inside the initial location:
+
+    >>> persistent.id(o1)
+    >>> o2 = Location(); o2.__parent__ = o1
+    >>> persistent.id(o2)
+
+    But, if we get a location outside the original location, we assign
+    it an `id` and return the `id`:
+
+    >>> o3 = Location()
+    >>> id3 = persistent.id(o3)
+    >>> id3 is None
+    False
+    >>> o4 = Location()
+    >>> id4 = persistent.id(o4)
+    >>> id4 is None
+    False
+    >>> id4 is id3
+    False
+
+    If we ask for the `id` of an outside location more than once, we
+    always get the same `id` back:
+
+    >> persistent.id(o4) == id4
+    True
+
+    We also provide a load function that returns the objects for which
+    we were given ids:
+
+    >>> persistent.load(id3) is o3
+    True
+    >>> persistent.load(id4) is o4
+    True
+
+    """
+
+    def __init__(self, location):
+        self.location = location
+        self.pids_by_id = {}
+        self.others_by_pid = {}
+        self.load = self.others_by_pid.get
+
+    def id(self, object):
+        if ILocation.providedBy(object):
+            if not inside(object, self.location):
+                if id(object) in self.pids_by_id:
+                    return self.pids_by_id[id(object)]
+                pid = len(self.others_by_pid)
+
+                # The following is needed to overcome a bug
+                # in pickle.py. The pickle checks the boolean value
+                # of the id, rather than whether it is None.
+                pid += 1
+
+                self.pids_by_id[id(object)] = pid
+                self.others_by_pid[pid] = object
+                return pid
+
+        return None
+
+
+class PathPersistent(object):
+    """Persistence hooks for pickling locations
+
+    See `locationCopy` above.
+
+    Unlike copy persistent, we use paths for ids of outside locations
+    so that we can separate pickling and unpickling in time.  We have
+    to compute paths and traverse objects to load paths, but paths can
+    be stored for later use, unlike the ids used by `CopyPersistent`.
+
+    We require outside locations that can be adapted to `ITraversable`.
+    To simplify the example, we'll use a simple traversable location
+    defined in `zope.location.tests`, `TLocation`.
+
+    Normally, general adapters are used to make objects traversable.
+
+    We get initialized with an initial location:
+
+    >>> o1 = Location()
+    >>> persistent = PathPersistent(o1)
+
+    We provide an id function that returns None when given a non-location:
+
+    >>> persistent.id(42)
+
+    Or when given a location that is inside the initial location:
+
+    >>> persistent.id(o1)
+    >>> o2 = Location(); o2.__parent__ = o1
+    >>> persistent.id(o2)
+
+    But, if we get a location outside the original location, we return it's
+    path. To compute it's path, it must be rooted:
+
+    >>> from zope.location.tests import TLocation
+    >>> root = TLocation()
+    >>> zope.interface.directlyProvides(
+    ...     root, zope.location.interfaces.IRoot)
+    >>> o3 = TLocation()
+    >>> o3.__name__ = 'o3'
+    >>> o3.__parent__ = root
+    >>> root.o3 = o3
+    >>> persistent.id(o3)
+    u'/o3'
+
+    >>> o4 = TLocation()
+    >>> o4.__name__ = 'o4'
+    >>> o4.__parent__ = o3
+    >>> o3.o4 = o4
+    >>> persistent.id(o4)
+    u'/o3/o4'
+
+    We also provide a load method that returns objects by traversing
+    given paths.  It has to find the root based on the object given to
+    the constructor.  Therefore, that object must also be rooted:
+
+    >>> o1.__parent__ = root
+    >>> persistent.load(u'/o3') is o3
+    True
+    >>> persistent.load(u'/o3/o4') is o4
+    True
+
+    We must provide an absolute path for the load method:
+
+    >>> persistent.load(u'o3')
+    Traceback (most recent call last):
+    ...
+    ValueError: ('Persistent paths must be absolute', u'o3')
+
+    """
+
+    def __init__(self, location):
+        self.location = location
+
+    def id(self, object):
+        if ILocation.providedBy(object):
+            if not inside(object, self.location):
+                return LocationPhysicallyLocatable(object).getPath()
+        return None
+
+    def load(self, path):
+        if not path.startswith(u'/'):
+            raise ValueError("Persistent paths must be absolute", path)
+        root = LocationPhysicallyLocatable(self.location).getRoot()
+        return zope.location.interfaces.ITraverser(root).traverse(path[1:])

Deleted: zope.location/tags/3.5.1/src/zope/location/traversing.py
===================================================================
--- zope.location/trunk/src/zope/location/traversing.py	2009-02-02 06:01:56 UTC (rev 95956)
+++ zope.location/tags/3.5.1/src/zope/location/traversing.py	2009-02-02 12:16:54 UTC (rev 95961)
@@ -1,219 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003-2009 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.
-#
-##############################################################################
-"""Classes to support implenting IContained
-
-$Id$
-"""
-__docformat__ = 'restructuredtext'
-
-import zope.component
-import zope.interface
-from zope.location.interfaces import ILocationInfo
-from zope.location.interfaces import IRoot, ITraverser
-from zope.location.interfaces import ILocation, ISite
-from zope.location.location import Location
-
-
-class LocationPhysicallyLocatable(object):
-    """Provide location information for location objects
-    """
-
-    zope.component.adapts(ILocation)
-    zope.interface.implements(ILocationInfo)
-
-    def __init__(self, context):
-        self.context = context
-
-    def getRoot(self):
-        """Get the root location for a location.
-
-        See ILocationInfo
-
-        The root location is a location that contains the given
-        location and that implements IContainmentRoot.
-
-        >>> root = Location()
-        >>> zope.interface.directlyProvides(root, IRoot)
-        >>> LocationPhysicallyLocatable(root).getRoot() is root
-        1
-
-        >>> o1 = Location(); o1.__parent__ = root
-        >>> LocationPhysicallyLocatable(o1).getRoot() is root
-        1
-
-        >>> o2 = Location(); o2.__parent__ = o1
-        >>> LocationPhysicallyLocatable(o2).getRoot() is root
-        1
-
-        We'll get a TypeError if we try to get the location fo a
-        rootless object:
-
-        >>> o1.__parent__ = None
-        >>> LocationPhysicallyLocatable(o1).getRoot()
-        Traceback (most recent call last):
-        ...
-        TypeError: Not enough context to determine location root
-        >>> LocationPhysicallyLocatable(o2).getRoot()
-        Traceback (most recent call last):
-        ...
-        TypeError: Not enough context to determine location root
-
-        If we screw up and create a location cycle, it will be caught:
-
-        >>> o1.__parent__ = o2
-        >>> LocationPhysicallyLocatable(o1).getRoot()
-        Traceback (most recent call last):
-        ...
-        TypeError: Maximum location depth exceeded, """ \
-                """probably due to a a location cycle.
-        """
-        context = self.context
-        max = 9999
-        while context is not None:
-            if IRoot.providedBy(context):
-                return context
-            context = context.__parent__
-            max -= 1
-            if max < 1:
-                raise TypeError("Maximum location depth exceeded, "
-                                "probably due to a a location cycle.")
-
-        raise TypeError("Not enough context to determine location root")
-
-    def getPath(self):
-        """Get the path of a location.
-
-        See ILocationInfo
-
-        This is an "absolute path", rooted at a root object.
-
-        >>> root = Location()
-        >>> zope.interface.directlyProvides(root, IRoot)
-        >>> LocationPhysicallyLocatable(root).getPath()
-        u'/'
-
-        >>> o1 = Location(); o1.__parent__ = root; o1.__name__ = 'o1'
-        >>> LocationPhysicallyLocatable(o1).getPath()
-        u'/o1'
-
-        >>> o2 = Location(); o2.__parent__ = o1; o2.__name__ = u'o2'
-        >>> LocationPhysicallyLocatable(o2).getPath()
-        u'/o1/o2'
-
-        It is an error to get the path of a rootless location:
-
-        >>> o1.__parent__ = None
-        >>> LocationPhysicallyLocatable(o1).getPath()
-        Traceback (most recent call last):
-        ...
-        TypeError: Not enough context to determine location root
-
-        >>> LocationPhysicallyLocatable(o2).getPath()
-        Traceback (most recent call last):
-        ...
-        TypeError: Not enough context to determine location root
-
-        If we screw up and create a location cycle, it will be caught:
-
-        >>> o1.__parent__ = o2
-        >>> LocationPhysicallyLocatable(o1).getPath()
-        Traceback (most recent call last):
-        ...
-        TypeError: Maximum location depth exceeded, """ \
-                """probably due to a a location cycle.
-
-        """
-
-        path = []
-        context = self.context
-        max = 9999
-        while context is not None:
-            if IRoot.providedBy(context):
-                if path:
-                    path.append('')
-                    path.reverse()
-                    return u'/'.join(path)
-                else:
-                    return u'/'
-            path.append(context.__name__)
-            context = context.__parent__
-            max -= 1
-            if max < 1:
-                raise TypeError("Maximum location depth exceeded, "
-                                "probably due to a a location cycle.")
-
-        raise TypeError("Not enough context to determine location root")
-
-    def getParents(self):
-        """Returns a list starting with the object's parent followed by
-        each of its parents.
-
-        Raises a TypeError if the object is not connected to a containment
-        root.
-
-        """
-        # XXX Merge this implementation with getPath. This was refactored
-        # from zope.traversing.
-        if IRoot.providedBy(self.context):
-            return []
-
-        parents = []
-        w = self.context
-        while 1:
-            w = w.__parent__
-            if w is None:
-                break
-            parents.append(w)
-
-        if parents and IRoot.providedBy(parents[-1]):
-            return parents
-
-        raise TypeError("Not enough context information to get all parents")
-
-    def getName(self):
-        """Get a location name
-
-        See ILocationInfo
-
-        >>> o1 = Location(); o1.__name__ = 'o1'
-        >>> LocationPhysicallyLocatable(o1).getName()
-        'o1'
-
-        """
-        return self.context.__name__
-
-    def getNearestSite(self):
-        """return the nearest site, see ILocationInfo
-
-        >>> o1 = Location()
-        >>> o1.__name__ = 'o1'
-        >>> LocationPhysicallyLocatable(o1).getNearestSite()
-        Traceback (most recent call last):
-        ...
-        TypeError: Not enough context information to get all parents
-
-        >>> root = Location()
-        >>> zope.interface.directlyProvides(root, IRoot)
-        >>> o1 = Location()
-        >>> o1.__name__ = 'o1'
-        >>> o1.__parent__ = root
-        >>> LocationPhysicallyLocatable(o1).getNearestSite() is root
-        1
-        """
-        if ISite.providedBy(self.context):
-            return self.context
-        for parent in self.getParents():
-            if ISite.providedBy(parent):
-                return parent
-        return self.getRoot()

Copied: zope.location/tags/3.5.1/src/zope/location/traversing.py (from rev 95958, zope.location/trunk/src/zope/location/traversing.py)
===================================================================
--- zope.location/tags/3.5.1/src/zope/location/traversing.py	                        (rev 0)
+++ zope.location/tags/3.5.1/src/zope/location/traversing.py	2009-02-02 12:16:54 UTC (rev 95961)
@@ -0,0 +1,263 @@
+##############################################################################
+#
+# Copyright (c) 2003-2009 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.
+#
+##############################################################################
+"""Classes to support implenting IContained
+
+$Id$
+"""
+__docformat__ = 'restructuredtext'
+
+import zope.component
+import zope.interface
+from zope.location.interfaces import ILocationInfo
+from zope.location.interfaces import IRoot, ITraverser
+from zope.location.interfaces import ILocation, ISite
+from zope.location.location import Location
+
+
+class LocationPhysicallyLocatable(object):
+    """Provide location information for location objects
+    
+    >>> from zope.interface.verify import verifyObject
+    >>> info = LocationPhysicallyLocatable(Location())
+    >>> verifyObject(ILocationInfo, info)
+    True
+    
+    """
+
+    zope.component.adapts(ILocation)
+    zope.interface.implements(ILocationInfo)
+
+    def __init__(self, context):
+        self.context = context
+
+    def getRoot(self):
+        """Get the root location for a location.
+
+        See ILocationInfo
+
+        The root location is a location that contains the given
+        location and that implements IContainmentRoot.
+
+        >>> root = Location()
+        >>> zope.interface.directlyProvides(root, IRoot)
+        >>> LocationPhysicallyLocatable(root).getRoot() is root
+        True
+
+        >>> o1 = Location(); o1.__parent__ = root
+        >>> LocationPhysicallyLocatable(o1).getRoot() is root
+        True
+
+        >>> o2 = Location(); o2.__parent__ = o1
+        >>> LocationPhysicallyLocatable(o2).getRoot() is root
+        True
+
+        We'll get a TypeError if we try to get the location fo a
+        rootless object:
+
+        >>> o1.__parent__ = None
+        >>> LocationPhysicallyLocatable(o1).getRoot()
+        Traceback (most recent call last):
+        ...
+        TypeError: Not enough context to determine location root
+        >>> LocationPhysicallyLocatable(o2).getRoot()
+        Traceback (most recent call last):
+        ...
+        TypeError: Not enough context to determine location root
+
+        If we screw up and create a location cycle, it will be caught:
+
+        >>> o1.__parent__ = o2
+        >>> LocationPhysicallyLocatable(o1).getRoot()
+        Traceback (most recent call last):
+        ...
+        TypeError: Maximum location depth exceeded, """ \
+                """probably due to a a location cycle.
+        """
+        context = self.context
+        max = 9999
+        while context is not None:
+            if IRoot.providedBy(context):
+                return context
+            context = context.__parent__
+            max -= 1
+            if max < 1:
+                raise TypeError("Maximum location depth exceeded, "
+                                "probably due to a a location cycle.")
+
+        raise TypeError("Not enough context to determine location root")
+
+    def getPath(self):
+        """Get the path of a location.
+
+        See ILocationInfo
+
+        This is an "absolute path", rooted at a root object.
+
+        >>> root = Location()
+        >>> zope.interface.directlyProvides(root, IRoot)
+        >>> LocationPhysicallyLocatable(root).getPath()
+        u'/'
+
+        >>> o1 = Location(); o1.__parent__ = root; o1.__name__ = 'o1'
+        >>> LocationPhysicallyLocatable(o1).getPath()
+        u'/o1'
+
+        >>> o2 = Location(); o2.__parent__ = o1; o2.__name__ = u'o2'
+        >>> LocationPhysicallyLocatable(o2).getPath()
+        u'/o1/o2'
+
+        It is an error to get the path of a rootless location:
+
+        >>> o1.__parent__ = None
+        >>> LocationPhysicallyLocatable(o1).getPath()
+        Traceback (most recent call last):
+        ...
+        TypeError: Not enough context to determine location root
+
+        >>> LocationPhysicallyLocatable(o2).getPath()
+        Traceback (most recent call last):
+        ...
+        TypeError: Not enough context to determine location root
+
+        If we screw up and create a location cycle, it will be caught:
+
+        >>> o1.__parent__ = o2
+        >>> LocationPhysicallyLocatable(o1).getPath()
+        Traceback (most recent call last):
+        ...
+        TypeError: Maximum location depth exceeded, """ \
+                """probably due to a a location cycle.
+
+        """
+
+        path = []
+        context = self.context
+        max = 9999
+        while context is not None:
+            if IRoot.providedBy(context):
+                if path:
+                    path.append('')
+                    path.reverse()
+                    return u'/'.join(path)
+                else:
+                    return u'/'
+            path.append(context.__name__)
+            context = context.__parent__
+            max -= 1
+            if max < 1:
+                raise TypeError("Maximum location depth exceeded, "
+                                "probably due to a a location cycle.")
+
+        raise TypeError("Not enough context to determine location root")
+
+    def getParents(self):
+        """Returns a list starting with the object's parent followed by
+        each of its parents.
+
+        Raises a TypeError if the object is not connected to a containment
+        root.
+
+        >>> root = Location()
+        >>> zope.interface.directlyProvides(root, IRoot)
+        >>> LocationPhysicallyLocatable(root).getParents()
+        []
+
+        >>> o1 = Location()
+        >>> o2 = Location()
+        >>> o1.__parent__ = root
+        >>> o2.__parent__ = o1
+        >>> LocationPhysicallyLocatable(o2).getParents() == [o1, root]
+        True
+        
+        If the last parent is not an IRoot object, TypeError will be
+        raised as statet before.
+        
+        >>> zope.interface.noLongerProvides(root, IRoot)
+        >>> LocationPhysicallyLocatable(o2).getParents()
+        Traceback (most recent call last):
+        ...
+        TypeError: Not enough context information to get all parents
+
+        """
+        # XXX Merge this implementation with getPath. This was refactored
+        # from zope.traversing.
+        if IRoot.providedBy(self.context):
+            return []
+
+        parents = []
+        w = self.context
+        while 1:
+            w = w.__parent__
+            if w is None:
+                break
+            parents.append(w)
+
+        if parents and IRoot.providedBy(parents[-1]):
+            return parents
+
+        raise TypeError("Not enough context information to get all parents")
+
+    def getName(self):
+        """Get a location name
+
+        See ILocationInfo
+
+        >>> o1 = Location(); o1.__name__ = u'o1'
+        >>> LocationPhysicallyLocatable(o1).getName()
+        u'o1'
+
+        >>> root = Location()
+        >>> zope.interface.directlyProvides(root, IRoot)
+        >>> LocationPhysicallyLocatable(root).getName()
+        u''
+
+        """
+        if IRoot.providedBy(self.context):
+            return u''
+        return self.context.__name__
+
+    def getNearestSite(self):
+        """return the nearest site, see ILocationInfo
+
+        >>> o1 = Location()
+        >>> o1.__name__ = 'o1'
+        >>> LocationPhysicallyLocatable(o1).getNearestSite()
+        Traceback (most recent call last):
+        ...
+        TypeError: Not enough context information to get all parents
+
+        >>> root = Location()
+        >>> zope.interface.directlyProvides(root, IRoot)
+        >>> o1 = Location()
+        >>> o1.__name__ = 'o1'
+        >>> o1.__parent__ = root
+        >>> LocationPhysicallyLocatable(o1).getNearestSite() is root
+        True
+        
+        >>> zope.interface.directlyProvides(o1, ISite)
+        >>> LocationPhysicallyLocatable(o1).getNearestSite() is o1
+        True
+        
+        >>> o2 = Location()
+        >>> o2.__parent__ = o1
+        >>> LocationPhysicallyLocatable(o2).getNearestSite() is o1
+        True
+        
+        """
+        if ISite.providedBy(self.context):
+            return self.context
+        for parent in self.getParents():
+            if ISite.providedBy(parent):
+                return parent
+        return self.getRoot()



More information about the Checkins mailing list