0
|
1 """
|
|
2 request dispatcher:
|
|
3 data persisting across requests should go here
|
|
4 """
|
|
5
|
|
6 import os
|
|
7 import re
|
|
8
|
|
9 from handlers import PostComment
|
|
10 from model import CouchComments, PickleComments
|
|
11 from genshi.template import TemplateLoader
|
|
12 from lxml import etree
|
|
13 from lxmlmiddleware import LXMLMiddleware
|
|
14 from paste.fileapp import FileApp
|
|
15 from pkg_resources import resource_filename
|
|
16 from string import Template
|
|
17 from webob import Request, Response, exc
|
|
18
|
|
19 class LaxTemplate(Template):
|
|
20 idpattern = r'[_a-z0-9]+'
|
|
21
|
|
22 class Commentator(LXMLMiddleware):
|
|
23
|
|
24 ### class level variables
|
|
25 defaults = { 'auto_reload': 'False',
|
|
26 'database': 'commentator',
|
|
27 'template_dirs': '',
|
|
28 'pattern': '.*',
|
|
29 'path': 'html',
|
|
30 'url': '.comment',
|
|
31 'template': 'comment.html' }
|
|
32
|
|
33 def __init__(self, app, **kw):
|
|
34
|
|
35 self.app = app
|
|
36
|
|
37 # set instance parameters from kw and defaults
|
|
38 for key in self.defaults:
|
|
39 setattr(self, key, kw.get(key, self.defaults[key]))
|
|
40 self.auto_reload = self.auto_reload.lower() == 'true'
|
|
41
|
|
42 # request handlers
|
|
43 self.handlers = [ PostComment ]
|
|
44
|
|
45 # template loader
|
|
46 self.template_dirs = self.template_dirs.split()
|
|
47 self.template_dirs.append(resource_filename(__name__, 'templates'))
|
|
48 self.loader = TemplateLoader(self.template_dirs,
|
|
49 auto_reload=self.auto_reload)
|
|
50
|
|
51 # URL,path
|
|
52 assert '#' in self.pattern
|
|
53 self.url_pattern, self.xpath_pattern = self.pattern.split('#', 1)
|
|
54 assert '->' in self.xpath_pattern
|
|
55 self.xpath_pattern, self.mapping = [i.strip() for i in self.xpath_pattern.split('->')]
|
|
56
|
|
57 # string template for URL substitution
|
|
58 self.mapping = LaxTemplate(self.mapping)
|
|
59
|
|
60 # backend: comment storage
|
|
61 self.model = PickleComments(self.database)
|
|
62
|
|
63 def __call__(self, environ, start_response):
|
|
64
|
|
65 # get a request object
|
|
66 request = Request(environ)
|
|
67
|
|
68 # get the path
|
|
69 path = request.path_info.strip('/').split('/')
|
|
70 if path == ['']:
|
|
71 path = []
|
|
72 request.environ['path'] = path
|
|
73
|
|
74 # save the path; not sure why i need to do this
|
|
75 environ['commentator.path_info'] = request.path_info
|
|
76
|
|
77 # match the request to a handler
|
|
78 for h in self.handlers:
|
|
79 handler = h.match(self, request)
|
|
80 if handler is not None:
|
|
81 break
|
|
82 else:
|
|
83 return LXMLMiddleware.__call__(self, environ, start_response)
|
|
84
|
|
85 # get response
|
|
86 res = handler()
|
|
87 return res(environ, start_response)
|
|
88
|
|
89 def manipulate(self, environ, tree):
|
|
90 url_match = re.match(self.url_pattern, environ['commentator.path_info'])
|
|
91 if not url_match:
|
|
92 return tree
|
|
93
|
|
94 # make string template of the groups
|
|
95 groups_dict = dict([(str(index+1), value)
|
|
96 for index, value in enumerate(url_match.groups())])
|
|
97
|
|
98 for element in tree.findall(self.xpath_pattern):
|
|
99
|
|
100 # get url
|
|
101 str_dict = groups_dict.copy()
|
|
102 for key in element.keys():
|
|
103 str_dict[key] = element.get(key)
|
|
104 uri = self.mapping.substitute(str_dict)
|
|
105
|
|
106 # get comments
|
|
107 # TODO
|
|
108
|
|
109 # genshi data
|
|
110 data = {}
|
|
111 data['comments'] = self.model.comments(uri)
|
|
112 data['action'] = '%s/%s' % (uri, self.url)
|
|
113
|
|
114 # render template
|
|
115 template = self.loader.load(self.template)
|
|
116 comments = template.generate(**data).render()
|
|
117 comments = etree.fromstring(comments)
|
|
118 element.append(comments)
|
|
119
|
|
120 return tree
|