Commit 9c8f4d5e authored by Lennart Regebro's avatar Lennart Regebro

Merge of the traversal refactoring branch.

parent c4cceb84
......@@ -49,6 +49,17 @@ Zope Changes
Features added
- The traversal has been refactored to take heed of Zope3s
IPublishTraverse adapter interfaces. The ZCML directives
five:traversable and five:defaultViewable are therefore no
longer needed, as everything now is five:traversable and
five:defaultViewable.
There was a bug in earlier versions of Five that allowed you
to do custom publishing traversal with ITraversable adapters.
This bug has been corrected. Anybody using ITraversable
adapters need to convert them to IPublishTraversal adapters.
- Testing.makerequest: Added an 'environ' argument so
clients can use mappings other than os.environ.
......
......@@ -25,9 +25,14 @@ from AccessControl.ZopeGuards import guarded_getattr
from Acquisition import Acquired, aq_inner, aq_parent, aq_base
from zExceptions import NotFound
from ZODB.POSException import ConflictError
from zope.interface import implements
from zope.interface import implements, Interface
from interfaces import ITraversable
from zope.app.traversing.interfaces import ITraversable as IZope3Traversable
from zope.component import queryMultiAdapter
from zope.app.traversing.interfaces import TraversalError
from zope.app.traversing.namespace import nsParse
from zope.app.traversing.namespace import namespaceLookup
_marker = object()
......@@ -59,6 +64,7 @@ class Traversable:
return self.virtual_url_path()
spp = self.getPhysicalPath()
try:
toUrl = self.REQUEST.physicalPathToURL
except AttributeError:
......@@ -133,7 +139,6 @@ class Traversable:
If true, then all of the objects along the path are validated with
the security machinery. Usually invoked using restrictedTraverse().
"""
if not path:
return self
......@@ -188,7 +193,19 @@ class Traversable:
continue
bobo_traverse = _getattr(obj, '__bobo_traverse__', _none)
if bobo_traverse is not _none:
if name and name[:1] in '@+':
# Process URI segment parameters.
ns, nm = nsParse(name)
if ns:
try:
next = namespaceLookup(ns, nm, obj,
self.REQUEST).__of__(obj)
if restricted and not securityManager.validate(
obj, obj, name, next):
raise Unauthorized, name
except TraversalError:
raise AttributeError(name)
elif bobo_traverse is not _none:
next = bobo_traverse(REQUEST, name)
if restricted:
if aq_base(next) is not next:
......@@ -227,12 +244,21 @@ class Traversable:
else:
next = _getattr(obj, name, marker)
if next is marker:
try:
try:
next=obj[name]
except AttributeError:
# Raise NotFound for easier debugging
# instead of AttributeError: __getitem__
raise NotFound, name
except (NotFound, KeyError):
# Try to look for a view
next = queryMultiAdapter((obj, self.REQUEST),
Interface, name)
if next is None:
# Didn't find one, reraise the error:
raise
next = next.__of__(obj)
if restricted and not securityManager.validate(
obj, obj, _none, next):
raise Unauthorized, name
......
......@@ -248,12 +248,28 @@ class NotExpr:
def __repr__(self):
return 'not:%s' % `self._s`
from zope.interface import Interface, implements
from zope.component import queryMultiAdapter
from zope.app.traversing.namespace import nsParse
from zope.app.traversing.namespace import namespaceLookup
from zope.app.traversing.interfaces import TraversalError
from zope.publisher.interfaces.browser import IBrowserRequest
from zope.app.publication.browser import setDefaultSkin
class FakeRequest(dict):
implements(IBrowserRequest)
def getURL(self):
return "http://codespeak.net/z3/five"
def restrictedTraverse(object, path, securityManager,
get=getattr, has=hasattr, N=None, M=[],
TupleType=type(()) ):
REQUEST = {'path': path}
REQUEST = FakeRequest()
REQUEST['path'] = path
REQUEST['TraversalRequestNameStack'] = path = path[:] # Copy!
setDefaultSkin(REQUEST)
path.reverse()
validate = securityManager.validate
__traceback_info__ = REQUEST
......@@ -282,7 +298,20 @@ def restrictedTraverse(object, path, securityManager,
continue
t=get(object, '__bobo_traverse__', N)
if t is not N:
if name and name[:1] in '@+':
import pdb
pdb.set_trace()
# Process URI segment parameters.
ns, nm = nsParse(name)
if ns:
try:
o = namespaceLookup(ns, nm, object,
REQUEST).__of__(object)
if not validate(object, object, name, o):
raise Unauthorized, name
except TraversalError:
raise AttributeError(name)
elif t is not N:
o=t(REQUEST, name)
container = None
......@@ -305,7 +334,16 @@ def restrictedTraverse(object, path, securityManager,
# XXX maybe in Python 2.2 we can just check whether
# the object has the attribute "__getitem__"
# instead of blindly catching exceptions.
try:
o = object[name]
except (AttributeError, KeyError):
# Try to look for a view
o = queryMultiAdapter((object, REQUEST),
Interface, name)
if o is None:
# Didn't find one, reraise the error:
raise
o = o.__of__(object)
except AttributeError, exc:
if str(exc).find('__getitem__') >= 0:
# The object does not support the item interface.
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment