~sidnei/zope3/ztk-1.0a1

« back to all changes in this revision

Viewing changes to src/zope/container/traversal.py

  • Committer: Sidnei da Silva
  • Date: 2010-03-03 03:29:50 UTC
  • mfrom: (12.1.16 trunk)
  • Revision ID: sidnei.da.silva@canonical.com-20100303032950-duivfaoqsxaf9dgg
Merged newer-from-ztk [r=jkakar,bigkevmcd,free][qa=andreas][f=522474].

Update our monolithic Zope 3 tree to a kgs-based, generated,
monolithic Zope 3 tree built from eggs using the
collective.buildout.omelette recipe.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
##############################################################################
 
2
#
 
3
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
 
4
# All Rights Reserved.
 
5
#
 
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.
 
12
#
 
13
##############################################################################
 
14
"""Traversal components for containers
 
15
 
 
16
$Id: traversal.py 97680 2009-03-09 07:32:19Z wosc $
 
17
"""
 
18
__docformat__ = 'restructuredtext'
 
19
 
 
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
 
27
 
 
28
from zope.container.interfaces import ISimpleReadContainer, IItemContainer
 
29
from zope.container.interfaces import IReadContainer
 
30
 
 
31
# Note that the next two classes are included here because they
 
32
# can be used for multiple view types.
 
33
 
 
34
class ContainerTraverser(object):
 
35
    """A traverser that knows how to look up objects by name in a container."""
 
36
 
 
37
    implements(IBrowserPublisher, IXMLRPCPublisher)
 
38
    __used_for__ = ISimpleReadContainer
 
39
 
 
40
    def __init__(self, container, request):
 
41
        self.context = container
 
42
        self.request = request
 
43
 
 
44
    def publishTraverse(self, request, name):
 
45
        """See zope.publisher.interfaces.IPublishTraverse"""
 
46
        subob = self.context.get(name, None)
 
47
        if subob is None:
 
48
            view = queryMultiAdapter((self.context, request), name=name)
 
49
            if view is not None:
 
50
                return view
 
51
 
 
52
            raise NotFound(self.context, name, request)
 
53
 
 
54
        return subob
 
55
 
 
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)
 
62
        if view_name is None:
 
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,)
 
67
 
 
68
 
 
69
class ItemTraverser(ContainerTraverser):
 
70
    """A traverser that knows how to look up objects by name in an item
 
71
    container."""
 
72
 
 
73
    __used_for__ = IItemContainer
 
74
 
 
75
    def publishTraverse(self, request, name):
 
76
        """See zope.publisher.interfaces.IPublishTraverse"""
 
77
        try:
 
78
            return self.context[name]
 
79
        except KeyError:
 
80
            view = queryMultiAdapter((self.context, request), name=name)
 
81
            if view is not None:
 
82
                return view
 
83
 
 
84
        raise NotFound(self.context, name, request)
 
85
 
 
86
 
 
87
_marker = object()
 
88
 
 
89
class ContainerTraversable(object):
 
90
    """Traverses containers via `getattr` and `get`."""
 
91
 
 
92
    implements(ITraversable)
 
93
    __used_for__ = IReadContainer
 
94
 
 
95
    def __init__(self, container):
 
96
        self._container = container
 
97
 
 
98
 
 
99
    def traverse(self, name, furtherPath):
 
100
        container = self._container
 
101
 
 
102
        v = container.get(name, _marker)
 
103
        if v is _marker:
 
104
            try:
 
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)
 
112
            if v is _marker:
 
113
                raise TraversalError(container, name)
 
114
 
 
115
        return v