summaryrefslogtreecommitdiff
path: root/pypers/europython05/Quixote-2.0/directory.py
blob: e3a88164c40239104abce05178e6ebcb5f5a5e39 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
"""$HeadURL: svn+ssh://svn.mems-exchange.org/repos/trunk/quixote/directory.py $
$Id: directory.py 26327 2005-03-10 11:30:45Z dbinger $

Logic for traversing directory objects and generating output.
"""
import quixote
from quixote.errors import TraversalError

class Directory(object):
    """
    Instance attributes: none
    """

    # A list containing strings or 2-tuples of strings that map external
    # names to internal names.  Note that the empty string will be
    # implicitly mapped to '_q_index'.
    _q_exports = []

    def _q_translate(self, component):
        """(component : string) -> string | None

        Translate a path component into a Python identifier.  Returning
        None signifies that the component does not exist.
        """
        if component in self._q_exports:
            if component == '':
                return '_q_index' # implicit mapping
            else:
                return component
        else:
            # check for an explicit external to internal mapping
            for value in self._q_exports:
                if isinstance(value, tuple):
                    if value[0] == component:
                        return value[1]
            else:
                return None

    def _q_lookup(self, component):
        """(component : string) -> object

        Lookup a path component and return the corresponding object (usually
        a Directory, a method or a string).  Returning None signals that the
        component does not exist.
        """
        return None

    def _q_traverse(self, path):
        """(path: [string]) -> object

        Traverse a path and return the result.
        """
        assert len(path) > 0
        component = path[0]
        path = path[1:]
        name = self._q_translate(component)
        if name is not None:
            obj = getattr(self, name)
        else:
            obj = self._q_lookup(component)
        if obj is None:
            raise TraversalError(private_msg=('directory %r has no component '
                                              '%r' % (self, component)))
        if path:
            return obj._q_traverse(path)
        elif callable(obj):
            return obj()
        else:
            return obj

    def __call__(self):
        if "" in self._q_exports and not quixote.get_request().form:
            # Fix missing trailing slash.
            path = quixote.get_path()
            print "Adding slash to: %r " % path
            return quixote.redirect(path + "/", permanent=True)
        else:
            raise TraversalError(private_msg=('directory %r is not '
                                              'callable' % self))

class AccessControlled(object):
    """
    A mix-in class that calls the _q_access() method before traversing
    into the directory.
    """
    def _q_access(self):
        pass

    def _q_traverse(self, path):
        self._q_access()
        return super(AccessControlled, self)._q_traverse(path)


class Resolving(object):
    """
    A mix-in class that provides the _q_resolve() method.  _q_resolve()
    is called if a component name appears in the _q_exports list but is
    not an instance attribute.  _q_resolve is expected to return the
    component object.
    """
    def _q_resolve(self, name):
        return None

    def _q_translate(self, component):
        name = super(Resolving, self)._q_translate(component)
        if name is not None and not hasattr(self, name):
            obj = self._q_resolve(name)
            setattr(self, name, obj)
        return name