1
##############################################################################
3
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
6
# This software is subject to the provisions of the Zope Public License,
7
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11
# FOR A PARTICULAR PURPOSE.
13
##############################################################################
14
"""Traversal components for containers
16
$Id: traversal.py 97680 2009-03-09 07:32:19Z wosc $
18
__docformat__ = 'restructuredtext'
20
from zope.interface import implements, providedBy
21
from zope.component import queryMultiAdapter, getSiteManager
22
from zope.component import ComponentLookupError
23
from zope.traversing.interfaces import TraversalError, ITraversable
24
from zope.publisher.interfaces.browser import IBrowserPublisher
25
from zope.publisher.interfaces.xmlrpc import IXMLRPCPublisher
26
from zope.publisher.interfaces import IDefaultViewName, NotFound
28
from zope.container.interfaces import ISimpleReadContainer, IItemContainer
29
from zope.container.interfaces import IReadContainer
31
# Note that the next two classes are included here because they
32
# can be used for multiple view types.
34
class ContainerTraverser(object):
35
"""A traverser that knows how to look up objects by name in a container."""
37
implements(IBrowserPublisher, IXMLRPCPublisher)
38
__used_for__ = ISimpleReadContainer
40
def __init__(self, container, request):
41
self.context = container
42
self.request = request
44
def publishTraverse(self, request, name):
45
"""See zope.publisher.interfaces.IPublishTraverse"""
46
subob = self.context.get(name, None)
48
view = queryMultiAdapter((self.context, request), name=name)
52
raise NotFound(self.context, name, request)
56
def browserDefault(self, request):
57
"""See zope.publisher.browser.interfaces.IBrowserPublisher"""
58
# XXX this re-implements zope.app.publisher.browser.getDefaultViewName()
59
# to break our only dependency on it.
60
view_name = getSiteManager(None).adapters.lookup(
61
map(providedBy, (self.context, request)), IDefaultViewName)
63
raise ComponentLookupError("Couldn't find default view name",
64
self.context, request)
65
view_uri = "@@%s" %view_name
66
return self.context, (view_uri,)
69
class ItemTraverser(ContainerTraverser):
70
"""A traverser that knows how to look up objects by name in an item
73
__used_for__ = IItemContainer
75
def publishTraverse(self, request, name):
76
"""See zope.publisher.interfaces.IPublishTraverse"""
78
return self.context[name]
80
view = queryMultiAdapter((self.context, request), name=name)
84
raise NotFound(self.context, name, request)
89
class ContainerTraversable(object):
90
"""Traverses containers via `getattr` and `get`."""
92
implements(ITraversable)
93
__used_for__ = IReadContainer
95
def __init__(self, container):
96
self._container = container
99
def traverse(self, name, furtherPath):
100
container = self._container
102
v = container.get(name, _marker)
105
# Note that if name is a unicode string, getattr will
106
# implicitly try to encode it using the system
107
# encoding (usually ascii). Failure to encode means
108
# invalid attribute name.
109
v = getattr(container, name, _marker)
110
except UnicodeEncodeError:
111
raise TraversalError(container, name)
113
raise TraversalError(container, name)