[Zope3-checkins] CVS: Zope3/src/zope/app/traversing - __init__.py:1.1.2.2
Jim Fulton
jim@zope.com
Mon, 23 Dec 2002 17:50:05 -0500
Update of /cvs-repository/Zope3/src/zope/app/traversing
In directory cvs.zope.org:/tmp/cvs-serv26083/zope/app/traversing
Modified Files:
Tag: NameGeddon-branch
__init__.py
Log Message:
changes to get zope.component tests to pass
=== Zope3/src/zope/app/traversing/__init__.py 1.1.2.1 => 1.1.2.2 ===
--- Zope3/src/zope/app/traversing/__init__.py:1.1.2.1 Mon Dec 23 14:32:33 2002
+++ Zope3/src/zope/app/traversing/__init__.py Mon Dec 23 17:49:34 2002
@@ -1,2 +1,171 @@
#
-# This file is necessary to make this directory a package.
+# 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.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.
+#
+##############################################################################
+"""
+Traversing the object tree.
+"""
+# being careful not to pollute the namespace unnecessarily...
+from zope.component import getAdapter as _getAdapter
+from objectname import IObjectName as _IObjectName
+from zope.app.interfaces.traversing.traverser import ITraverser as _ITraverser
+from zope.app.interfaces.traversing.physicallylocatable \
+ import IPhysicallyLocatable as _IPhysicallyLocatable
+from traverser import WrapperChain as _WrapperChain
+from traverser import Traverser as _Traverser
+from zope.proxy.context.context import getWrapperContext as _getWrapperContext
+from zope.proxy.context.context import isWrapper as _isWrapper
+from types import StringTypes
+_marker = object()
+
+# XXX: this probably shouldn't have "request" in its signature, nor
+# in the arguments of the call to traverser.traverse
+def traverse(place, path, default=_marker, request=None):
+ """Traverse 'path' relative to 'place'
+
+ 'path' can be a string with path segments separated by '/'
+ or a sequence of path segments.
+
+ Raises NotFoundError if path cannot be found
+ Raises TypeError if place is not context wrapped
+
+ 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 = _Traverser(place)
+ if default is _marker:
+ return traverser.traverse(path, request=request)
+ else:
+ return traverser.traverse(path, default=default, request=request)
+
+# XXX This should have an additional optional argument where you
+# can pass an ITraversable to use, otherwise it should get
+# an adapter for ITraversable from the object and use that to
+# traverse one step.
+def traverseName(obj, name, default=_marker):
+ """Traverse a single step 'name' relative to 'place'
+
+ 'name' must be a string. 'name' will be treated as a single
+ path segment, no matter what characters it contains.
+
+ Raises NotFoundError if path cannot be found
+ Raises TypeError if place is not context wrapped
+ """
+ # by passing [name] to traverse (above), we ensure that name is
+ # treated as a single path segment, regardless of any '/' characters
+ return traverse(obj, [name], default=default)
+
+
+def objectName(obj):
+ """Get the name an object was traversed via
+
+ Raises TypeError if the object is not context-wrapped
+ """
+ return _getAdapter(obj, _IObjectName)()
+
+def getParent(obj):
+ """Returns the container the object was traversed via.
+
+ Raises TypeError if the given object is not context wrapped
+ """
+ if not _isWrapper(obj):
+ raise TypeError, "Not enough context information to traverse"
+ return _getWrapperContext(obj)
+
+def getParents(obj):
+ """Returns a list starting with the given object's parent followed by
+ each of its parents.
+
+ Raises TypeError if the given object is not context wrapped
+ """
+ if not _isWrapper(obj):
+ raise TypeError, "Not enough context information to traverse"
+ iterator = _WrapperChain(obj)
+ iterator.next() # send head of chain (current object) to /dev/null
+ return [p for p in iterator]
+
+def getPhysicalPath(obj):
+ """Returns a tuple of names representing the physical path to the object.
+
+ Raises TypeError if the given object is not context wrapped
+ """
+ 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
+ """
+ path = _getAdapter(obj, _IPhysicallyLocatable).getPhysicalPath()
+ return locationAsUnicode(path)
+
+
+def getPhysicalRoot(obj):
+ """Returns the root of the traversal for the given object.
+
+ Raises TypeError if the given object is not context wrapped
+ """
+ return _getAdapter(obj, _IPhysicallyLocatable).getPhysicalRoot()
+
+def locationAsTuple(location):
+ """Given a location as a unicode or ascii string or as a tuple of
+ unicode or ascii strings, returns the location as a tuple of
+ unicode strings.
+
+ Raises a ValueError if a poorly formed location is given.
+ """
+ if not location:
+ raise ValueError, "location must be non-empty: %s" % repr(location)
+ if isinstance(location, StringTypes):
+ if location == u'/': # matches '/' or u'/'
+ return (u'',)
+ t = tuple(location.split(u'/'))
+ elif location.__class__ == tuple:
+ # isinstance doesn't work when tuple is security-wrapped
+ t = tuple(map(unicode, location))
+ else:
+ raise ValueError, \
+ "location %s must be a string or a tuple of strings." % (location,)
+
+ if len(t) > 1 and t[-1] == u'': # matches '' or u''
+ raise ValueError, \
+ "location tuple %s must not end with empty string." % (t,)
+ # don't usually need this, so just an assertion rather than a value error
+ assert '' not in t[1:]
+ return t
+
+def locationAsUnicode(location):
+ """Given a location as a unicode or ascii string or as a tuple of
+ unicode or ascii strings, returns the location as a slash-separated
+ unicode string.
+
+ Raises ValueError if a poorly formed location is given.
+ """
+ if not location:
+ raise ValueError, "location must be non-empty."
+ if isinstance(location, StringTypes):
+ u = unicode(location)
+ elif location.__class__ == tuple:
+ # isinstance doesn't work when tuple is security-wrapped
+ u = u'/'.join(location)
+ if not u: # special case for u''
+ return u'/'
+ else:
+ raise ValueError, \
+ "location %s must be a string or a tuple of strings." % (location,)
+ if u != '/' and u[-1] == u'/':
+ raise ValueError, "location %s must not end with a slash." % u
+ # don't usually need this, so just an assertion rather than a value error
+ assert u.find(u'//') == -1
+ return u