[Zope-Checkins] CVS: Zope3/lib/python/Zope/App/Traversing - IContainmentRoot.py:1.1 IPhysicallyLocatable.py:1.1 PhysicalLocationAdapters.py:1.1 EtcNamespace.py:1.3 ITraverser.py:1.3 ObjectName.py:1.2 Traverser.py:1.3 __init__.py:1.7 configure.zcml:1.4

Jim Fulton jim@zope.com
Thu, 11 Jul 2002 14:22:06 -0400


Update of /cvs-repository/Zope3/lib/python/Zope/App/Traversing
In directory cvs.zope.org:/tmp/cvs-serv7355/lib/python/Zope/App/Traversing

Modified Files:
	EtcNamespace.py ITraverser.py ObjectName.py Traverser.py 
	__init__.py configure.zcml 
Added Files:
	IContainmentRoot.py IPhysicallyLocatable.py 
	PhysicalLocationAdapters.py 
Log Message:

Reimplemented service managers to be package based. Service managers
are no longer containers. They have a packages subobject (not a
packages service) that contains packages. TTW components are created
in packages. To register a component, create the appropriate component
directive objects (these should be called configuration objects).

This should be viewed as a prototype to illustrate the idea of
packages. Lots of things can change (especially UI) and many things
aren't done (e.g. visiting created directives).

In the course of this, I fixed a bunch of bugs and problems in
traversal machinery. 

I also renamed Zope.ComponentArchitecture.IServiceManager back to
IServiceService, since this interface doesn't actually specify any
management.  



=== Added File Zope3/lib/python/Zope/App/Traversing/IContainmentRoot.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
# 
##############################################################################
"""
$Id: IContainmentRoot.py,v 1.1 2002/07/11 18:21:34 jim Exp $
"""

from Interface import Interface

class IContainmentRoot(Interface):
    """Marker interface to designate root objects
    """

__doc__ = IContainmentRoot.__doc__ + __doc__


=== Added File Zope3/lib/python/Zope/App/Traversing/IPhysicallyLocatable.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
# 
##############################################################################
"""
$Id: IPhysicallyLocatable.py,v 1.1 2002/07/11 18:21:34 jim Exp $
"""

from Interface import Interface

class IPhysicallyLocatable(Interface):
    """Objects that have a physical location in a containment hierarchy.
    """

    def getPhysicalRoot():
        """Return the physical root object
        """

    def getPhysicalPath():
        """Return the physical path to the object as a sequence of names.
        """

__doc__ = IPhysicallyLocatable.__doc__ + __doc__


=== Added File Zope3/lib/python/Zope/App/Traversing/PhysicalLocationAdapters.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
# 
##############################################################################
"""XXX short summary goes here.

XXX longer description goes here.

$Id: PhysicalLocationAdapters.py,v 1.1 2002/07/11 18:21:34 jim Exp $
"""
__metaclass__ = type

from Zope.App.Traversing.IPhysicallyLocatable import IPhysicallyLocatable
from Zope.App.Traversing.IContainmentRoot import IContainmentRoot
from Zope.ComponentArchitecture import getAdapter
from Zope.Proxy.ContextWrapper import getInnerWrapperData, getWrapperContainer

class WrapperPhysicallyLocatable:
    __doc__ = IPhysicallyLocatable.__doc__

    __implements__ =  IPhysicallyLocatable

    def __init__(self, context):
        self.context = context

    def getPhysicalRoot(self):
        "See Zope.App.Traversing.IPhysicallyLocatable.IPhysicallyLocatable"
        container = getWrapperContainer(self.context)
        if container is None:
            raise TypeError("Not enough context to determine location root")
        return getAdapter(container, IPhysicallyLocatable).getPhysicalRoot()

    def getPhysicalPath(self):
        "See Zope.App.Traversing.IPhysicallyLocatable.IPhysicallyLocatable"
        context = self.context
        container = getWrapperContainer(context)
        if container is None:
            raise TypeError("Not enough context to determine location")
        name = getInnerWrapperData(context)['name']

        container = getAdapter(container, IPhysicallyLocatable)
        container_path = container.getPhysicalPath()

        return container_path + (name, )
        

class RootPhysicallyLocatable:
    __doc__ = IPhysicallyLocatable.__doc__

    __implements__ =  IPhysicallyLocatable

    __used_for__ = IContainmentRoot

    def __init__(self, context):
        self.context = context

    def getPhysicalPath(self):
        "See Zope.App.Traversing.IPhysicallyLocatable.IPhysicallyLocatable"
        return ('', )

    def getPhysicalRoot(self):
        "See Zope.App.Traversing.IPhysicallyLocatable.IPhysicallyLocatable"
        return self.context





=== Zope3/lib/python/Zope/App/Traversing/EtcNamespace.py 1.2 => 1.3 ===
     method_name = "getServiceManager"
     method = getattr(ob, method_name, None)
     if method is None: 
-        raise NotFound(ob, pname, request)
+        raise NotFoundError(ob, pname, request)
 
     return method()
 


=== Zope3/lib/python/Zope/App/Traversing/ITraverser.py 1.2 => 1.3 ===
 
 class ITraverser(Interface.Base):
     """Provide traverse features"""
-
-    def getPhysicalRoot():
-        """
-        Returns the top-level Application object, or the base object if it is
-        unwrapped.
-        """
-
-    def getPhysicalPath():
-        """
-        Returns a path (an immutable sequence of strings) from the root.
-        
-        This path can be used to access this object again later, for example
-        in a copy/paste operation. Returns an empty tuple if the base object
-        is not wrapped.
-        """
     
     def traverse(path, default=_RAISE_KEYERROR):
         """


=== Zope3/lib/python/Zope/App/Traversing/ObjectName.py 1.1 => 1.2 ===
 Revision information:
 $Id$
 """
-from Zope.Proxy.ContextWrapper import getWrapperData
+from Zope.Proxy.ContextWrapper import getInnerWrapperData
 
 from Interface import Interface
 
@@ -42,7 +42,7 @@
         self.context = context
 
     def __str__(self):
-        dict = getWrapperData(self.context)
+        dict = getInnerWrapperData(self.context)
         name = dict and dict.get('name') or None
         if name is None:
             raise TypeError, \


=== Zope3/lib/python/Zope/App/Traversing/Traverser.py 1.2 => 1.3 ===
 $Id$
 """
 
-from ITraverser import ITraverser
-from ITraversable import ITraversable
+from Zope.ComponentArchitecture import getAdapter
 from Zope.ContextWrapper.IWrapper import IWrapper
-from Zope.Proxy.ContextWrapper import getWrapperContext, getWrapperData
+from Zope.Proxy.ContextWrapper import getWrapperContainer, getInnerWrapperData
 from Zope.Proxy.ContextWrapper import ContextWrapper
 from Zope.ComponentArchitecture import queryAdapter
 from Zope.Exceptions import NotFoundError, Unauthorized
@@ -27,6 +26,10 @@
 from ParameterParsing import parameterizedNameParse
 from Zope.Security.SecurityManagement import getSecurityManager
 
+from IPhysicallyLocatable import IPhysicallyLocatable
+from ITraverser import ITraverser
+from ITraversable import ITraversable
+
 from types import StringTypes
 
 from __future__ import generators
@@ -35,7 +38,7 @@
 def WrapperChain(w):
     while w is not None:
         yield w
-        w = getWrapperContext(w)
+        w = getWrapperContainer(w)
 
 _marker = object()
 
@@ -47,27 +50,11 @@
     # This adapter can be used for any object.
 
     def __init__(self, wrapper):
-        self._wrapper = wrapper
-
-    def getPhysicalRoot(self):
-        # Loop over all wrappers until the last one, which is the root.
-        for w in WrapperChain(self._wrapper):
-            pass
-        return w
-
-    def getPhysicalPath(self):
-        path = []
-        
-        for w in WrapperChain(self._wrapper):
-            d = getWrapperData(w)
-            if d:
-                path.insert(0, d['name'])
-
-        return tuple(path)
+        self.context = wrapper
     
     def traverse(self, path, default=_marker, request=None):
         if not path:
-            return self._wrapper
+            return self.context
 
         if isinstance(path, StringTypes):
             path = path.split('/')
@@ -80,11 +67,12 @@
         path.reverse()
         pop = path.pop
 
-        curr = self._wrapper
+        curr = self.context
         if not path[-1]:
             # Start at the root
             pop()
-            curr = self.getPhysicalRoot()
+            curr = getAdapter(self.context, IPhysicallyLocatable
+                              ).getPhysicalRoot()
         try:
             while path:
                 name = pop()
@@ -93,7 +81,7 @@
                     continue
 
                 if name == '..':
-                    curr = getWrapperContext(curr) or curr
+                    curr = getWrapperContainer(curr) or curr
                     continue
 
 
@@ -109,7 +97,8 @@
 
                 traversable = queryAdapter(curr, ITraversable, None)
                 if traversable is None:
-                    raise NotFoundError, 'No traversable adapter found'
+                    raise NotFoundError(
+                        'No traversable adapter found', curr)
 
                 next = traversable.traverse(nm, parms, name, path)
                 curr = ContextWrapper(next, curr, name=name)


=== Zope3/lib/python/Zope/App/Traversing/__init__.py 1.6 => 1.7 ===
 from Zope.ComponentArchitecture import getAdapter as _getAdapter
 from ObjectName import IObjectName as _IObjectName
 from ITraverser import ITraverser as _ITraverser
+from IPhysicallyLocatable import IPhysicallyLocatable as _IPhysicallyLocatable
 from Traverser import WrapperChain as _WrapperChain
+from Traverser import Traverser as _Traverser
 from Zope.Proxy.ContextWrapper import getWrapperContext as _getWrapperContext
 from Zope.Proxy.ContextWrapper import isWrapper as _isWrapper
 from types import StringTypes
@@ -41,9 +43,10 @@
           code unexpectedly.
           Consider using traverseName instead.
     """
-    if not _isWrapper(place):
-        raise TypeError, "Not enough context information to traverse"
-    traverser = _getAdapter(place, _ITraverser)
+    # XXX This made no sense. It would mean you couldn't traverse from root
+    #if not _isWrapper(place):
+    #    raise TypeError, "Not enough context information to traverse"
+    traverser = _Traverser(place)
     if default is _marker:
         return traverser.traverse(path, request=request)
     else:
@@ -92,15 +95,26 @@
     return [p for p in iterator]
     
 def getPhysicalPath(obj):
-    """Returns a tuple of names representing the physical path to the
-    given object.
+    """Returns a tuple of names representing the physical path to the object.
     
     Raises TypeError if the given object is not context wrapped
     """
     if not _isWrapper(obj):
         raise TypeError, "Not enough context information to traverse"
     
-    return _getAdapter(obj, _ITraverser).getPhysicalPath()
+    return _getAdapter(obj, _IPhysicallyLocatable).getPhysicalPath()
+
+def getPhysicalPathString(obj):
+    """Returns a string representing the physical path to the object.
+    
+    Raises TypeError if the given object is not context wrapped
+    """
+    if not _isWrapper(obj):
+        raise TypeError, "Not enough context information to traverse"
+    
+    path = _getAdapter(obj, _IPhysicallyLocatable).getPhysicalPath()
+    return '/'.join(path)
+    
     
 def getPhysicalRoot(obj):
     """Returns the root of the traversal for the given object.
@@ -110,7 +124,7 @@
     if not _isWrapper(obj):
         raise TypeError, "Not enough context information to traverse"
         
-    return _getAdapter(obj, _ITraverser).getPhysicalRoot()
+    return _getAdapter(obj, _IPhysicallyLocatable).getPhysicalRoot()
 
 def locationAsTuple(location):
     """Given a location as a unicode or ascii string or as a tuple of


=== Zope3/lib/python/Zope/App/Traversing/configure.zcml 1.3 => 1.4 ===
     factory=".ObjectName."
     provides=".ObjectName.IObjectName"
     permission='Zope.Public'
-/>
+    />
 
 <adapter
     factory=".ObjectName.SiteObjectName"
     provides=".ObjectName.IObjectName"
     for="Zope.App.OFS.Content.Folder.RootFolder.IRootFolder"
     permission='Zope.Public'
-/>
+    />
+
+<adapter 
+    provides=".IPhysicallyLocatable."
+    factory=".PhysicalLocationAdapters.WrapperPhysicallyLocatable" 
+    />
+
+<adapter 
+    provides=".IPhysicallyLocatable."
+    for=".IContainmentRoot."
+    factory=".PhysicalLocationAdapters.RootPhysicallyLocatable" 
+    />
 
 
 </zopeConfigure>