This repository has been archived by the owner on Oct 12, 2017. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 15
/
QuixoteQLookup
84 lines (74 loc) · 2.27 KB
/
QuixoteQLookup
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
= Quixote _q_lookup emulation in !CherryPy 2.2 =
Courtesy of cherrypy (at) wojas.vvtp.tudelft.nl
{{{
#!python
def traverse(func):
"""
(Decorator)
Desperate attempt at implementing Quixote's _q_lookup functionality in CherryPy.
Using this decorator a default method can return an object to continue path traversal.
Makes REST style paths like /object/123/ and /object/123/edit possible without big
switch blocks in object's default method..
This decorator also exposes the page.
"""
def wrapper(self, *args, **kwargs):
import types
result = func(self, *args, **kwargs)
if isinstance(result, object) and not isinstance(result, (basestring, types.GeneratorType)):
# do _q_lookup style directory traversal
path = cherrypy.request.path
if len(args)==1:
# this is the end of the traversal
# make sure the path ends with a /
if not path.endswith('/'):
raise cherrypy.HTTPRedirect(path+'/')
# and then just call index
m = getattr(result, 'index', None)
if m and getattr(m, 'exposed', False):
return m(**kwargs)
else:
raise cherrypy.NotFound(cherrypy.request.path+'/'+args[0])
else:
# still some parts to handle
m = getattr(result, args[1], None)
if m and getattr(m, 'exposed', False):
if len(path)>1 and path.endswith('/'):
# make sure the path doesn't end with a /
raise cherrypy.HTTPRedirect(path[:-1])
return m(*args[2:], **kwargs)
else:
# call 'default' method if it exists
m = getattr(result, 'default', None)
if m and getattr(m, 'exposed', False):
return m(*args[1:], **kwargs)
else:
raise cherrypy.NotFound(cherrypy.request.path+'/'+args[1])
else:
# normal result, no traversal
return result
wrapper.exposed = True
return wrapper
}}}
Usage:
{{{
#!python
class TraverseTest(object):
exposed = True
n = None
def __init__(self, n=42):
self.n = n
@expose
def show(self):
yield "Hello from show! %s" % self.n
@expose
def index(self):
yield "Hello from index! %s" % self.n
@traverse
def default(self, *args, **kwargs):
try:
i = int(args[0])
except ValueError:
return "'%s' is not an integer, won't traverse" % args[0]
else:
return TraverseTest(args[0])
}}}