[Zope-Checkins] CVS: Zope3/lib/python/Zope/App/OFS/Container - ContainerTraversable.py:1.1.2.2

Steve Alexander steve@cat-box.net
Wed, 20 Mar 2002 18:11:57 -0500


Update of /cvs-repository/Zope3/lib/python/Zope/App/OFS/Container
In directory cvs.zope.org:/tmp/cvs-serv13451/lib/python/Zope/App/OFS/Container

Modified Files:
      Tag: Zope-3x-branch
	ContainerTraversable.py 
Log Message:
Added a ContainerTraversable that (if enabled in zcml) traverses
containers from path expressions (and such like, not URL traversal),
and searches attributes followed by subobjects.
You can also choose explicitly whether you want attributes or subobjects
by using name;method or name;content respectively.


=== Zope3/lib/python/Zope/App/OFS/Container/ContainerTraversable.py 1.1.2.1 => 1.1.2.2 ===
 
 class ContainerTraversable:
-    """Traverses containers via getObject"""
+    """Traverses containers via getattr and getObject.
+    
+       If the name to traverse to includes a ';', the name
+       will be treated as a name and namespace.
+       
+       The allowed namespaces are:
+       
+           method   traverse using getattr only
+           content  traverse using getObject only
+           
+       If no namespace is given, try getattr and then getObject.
+       
+    """
 
     __implements__ = ITraversable
     __used_for__ = IReadContainer
@@ -21,7 +33,31 @@
         self._container = container
 
     def traverse(self, name, furtherPath):
-        next = self._container.getObject(name, None)
-        if next is None:
-            raise NotFoundError, name
-        return next
+        container = self._container
+        
+        # keep original name to return in a NotFoundError
+        original_name = name
+                     
+        if ';' in original_name:
+            # explicit traversal to a namespace
+            # containers know about "method" and "content"
+
+            name,namespace = original_name.split(';', 1)
+            
+            if namespace not in ('method', 'content'):
+                raise NotFoundError, 'unrecognised namespace "%s" in "%s;%s"' \
+                     % (namespace, name, namespace)            
+        else:
+            # traversal with no namespace given
+            # containers try methods, then if no method if found,
+            # their contents.
+            
+            namespace = None
+            
+        if namespace in (None, 'method') and hasattr(container, name):
+            return getattr(container, name)
+            
+        if namespace in (None, 'content') and container.hasObject(name):
+            return container.getObject(name)
+            
+        raise NotFoundError, original_name