[Zope-Checkins] CVS: Zope3/lib/python/Zope/App/Traversing - DefaultTraversable.py:1.1.2.1 ITraversable.py:1.1.2.1 ITraverser.py:1.1.2.2 Traverser.py:1.1.2.2
Martijn Pieters
mj@zope.com
Mon, 3 Dec 2001 17:08:13 -0500
Update of /cvs-repository/Zope3/lib/python/Zope/App/Traversing
In directory cvs.zope.org:/tmp/cvs-serv23382/lib/python/Zope/App/Traversing
Modified Files:
Tag: Zope-3x-branch
ITraverser.py Traverser.py
Added Files:
Tag: Zope-3x-branch
DefaultTraversable.py ITraversable.py
Log Message:
Implementation of unrestrictedTraverse, with new interface and feature
ITraversable. Include a default ITraversable implementation, and one for
containers. Note: No security assertions yet.
=== Added File Zope3/lib/python/Zope/App/Traversing/DefaultTraversable.py ===
# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 1.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.
from ITraversable import ITraversable
from Zope.Exceptions import NotFoundError
class DefaultTraversable:
"""Traverses objects via attribute and dictionary lookup"""
__implements__ = ITraversable
def __init__(self, subject):
self._subject = subject
def traverse(self, name, furtherPath):
if name.startswith('_'):
raise NotFoundError, name
if hasattr(self._subject, name):
return getattr(self._subject, name)
else:
try:
return self._subject[name]
except (KeyError, IndexError, TypeError, AttributeError):
raise NotFoundError, name
=== Added File Zope3/lib/python/Zope/App/Traversing/ITraversable.py ===
# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 1.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.
import Interface
class ITraversable(Interface.Base):
"""To traverse an object, this interface must be provided"""
def traverse(name, furtherPath):
"""Get the next item on the path
furtherPath is a list of names still to be traversed. This method is
allowed to change the contents of furtherPath.
Should return the item corresponding to 'name' or raise
Zope.Exceptions.NotFoundError where appropriate.
"""
=== Zope3/lib/python/Zope/App/Traversing/ITraverser.py 1.1.2.1 => 1.1.2.2 ===
def getPhysicalRoot():
"""
- Returns the top-level Application object, or the bas eobject is it is
+ Returns the top-level Application object, or the base object if it is
unwrapped.
"""
@@ -31,10 +31,14 @@
def unrestrictedTraverse(path, default=_RAISE_KEYERROR):
"""
- Return an object given a path (an immutable sequence of strings).
+ 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, start at
- the root. Otherwise the path is relative to the current context.
+ 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 then the 'default' argument will be returned.
"""
@@ -44,6 +48,8 @@
Return the object obtained by traversing the given path from the object
on which the method was called, performing security checks along the
way.
+
+ The path argument is the same as for unrestrictedTraverse.
If an object is not found then the 'default' argument will be returned.
"""
=== Zope3/lib/python/Zope/App/Traversing/Traverser.py 1.1.2.1 => 1.1.2.2 ===
from ITraverser import ITraverser
+from ITraversable import ITraversable
from Zope.ContextWrapper.IWrapper import IWrapper
from Zope.ContextWrapper import wrapper
+from Zope.ComponentArchitecture import getFeature
+from Zope.Exceptions import NotFoundError
+
+from types import StringType
from __future__ import generators
@@ -48,11 +53,58 @@
return tuple(path)
def unrestrictedTraverse(self, path, default=_marker, restricted=0):
- # stub, never finds.
- if default is not _marker:
- return default
+ if not path: return self._wrapper
+
+ if type(path) is StringType:
+ 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._wrapper
+ if not path[-1]:
+ # Start at the root
+ pop()
+ curr = self.getPhysicalRoot()
+ if restricted: pass
+ # TODO: security restrictions
+
+ try:
+ while path:
+ name = pop()
+
+ if name == '.':
+ continue
+
+ if name == '..':
+ next = wrapper.getcontext(curr) or curr
+ if next is not None:
+ # TODO: security restrictions
+ curr = next
+ continue
+
+ traversable = getFeature(curr, ITraversable, None)
+ if traversable is None:
+ # Cannot be traversed, so we cannot find the next name
+ raise NotFoundError, name
+
+ else:
+ next = traversable.traverse(name, path)
+ next = wrapper.Wrapper(next, curr, name=name)
+ if restricted: pass
+ # TODO: security restrictions
+ curr = next
- raise KeyError
+ return curr
+
+ except:
+ if default == _marker: raise
+ return default
def restrictedTraverse(self, path, default=_marker):
self.unrestrictedTraverse(self, path, default, restricted=1)