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
|