diff options
Diffstat (limited to 'google_appengine/lib/webob/docs/wiki-example-code/example.py')
-rwxr-xr-x | google_appengine/lib/webob/docs/wiki-example-code/example.py | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/google_appengine/lib/webob/docs/wiki-example-code/example.py b/google_appengine/lib/webob/docs/wiki-example-code/example.py new file mode 100755 index 0000000..c76ffa7 --- /dev/null +++ b/google_appengine/lib/webob/docs/wiki-example-code/example.py @@ -0,0 +1,200 @@ +import os +import re +from webob import Request, Response +from webob import exc +from tempita import HTMLTemplate + +VIEW_TEMPLATE = HTMLTemplate("""\ +<html> + <head> + <title>{{page.title}}</title> + </head> + <body> +<h1>{{page.title}}</h1> +{{if message}} +<div style="background-color: #99f">{{message}}</div> +{{endif}} + +<div>{{page.content|html}}</div> + +<hr> +<a href="{{req.url}}?action=edit">Edit</a> + </body> +</html> +""") + +EDIT_TEMPLATE = HTMLTemplate("""\ +<html> + <head> + <title>Edit: {{page.title}}</title> + </head> + <body> +{{if page.exists}} +<h1>Edit: {{page.title}}</h1> +{{else}} +<h1>Create: {{page.title}}</h1> +{{endif}} + +<form action="{{req.path_url}}" method="POST"> + <input type="hidden" name="mtime" value="{{page.mtime}}"> + Title: <input type="text" name="title" style="width: 70%" value="{{page.title}}"><br> + Content: <input type="submit" value="Save"> + <a href="{{req.path_url}}">Cancel</a> + <br> + <textarea name="content" style="width: 100%; height: 75%" rows="40">{{page.content}}</textarea> + <br> + <input type="submit" value="Save"> + <a href="{{req.path_url}}">Cancel</a> +</form> +</body></html> +""") + +class WikiApp(object): + + view_template = VIEW_TEMPLATE + edit_template = EDIT_TEMPLATE + + def __init__(self, storage_dir): + self.storage_dir = os.path.abspath(os.path.normpath(storage_dir)) + + def __call__(self, environ, start_response): + req = Request(environ) + action = req.params.get('action', 'view') + page = self.get_page(req.path_info) + try: + try: + meth = getattr(self, 'action_%s_%s' % (action, req.method)) + except AttributeError: + raise exc.HTTPBadRequest('No such action %r' % action).exception + resp = meth(req, page) + except exc.HTTPException, e: + resp = e + return resp(environ, start_response) + + def get_page(self, path): + path = path.lstrip('/') + if not path: + path = 'index' + path = os.path.join(self.storage_dir) + path = os.path.normpath(path) + if path.endswith('/'): + path += 'index' + if not path.startswith(self.storage_dir): + raise exc.HTTPBadRequest("Bad path").exception + path += '.html' + return Page(path) + + def action_view_GET(self, req, page): + if not page.exists: + return exc.HTTPTemporaryRedirect( + location=req.url + '?action=edit') + if req.cookies.get('message'): + message = req.cookies['message'] + else: + message = None + text = self.view_template.substitute( + page=page, req=req, message=message) + resp = Response(text) + if message: + resp.delete_cookie('message') + else: + resp.last_modified = page.mtime + resp.conditional_response = True + return resp + + def action_view_POST(self, req, page): + submit_mtime = int(req.params.get('mtime') or '0') or None + if page.mtime != submit_mtime: + return exc.HTTPPreconditionFailed( + "The page has been updated since you started editing it") + page.set( + title=req.params['title'], + content=req.params['content']) + resp = exc.HTTPSeeOther( + location=req.path_url) + resp.set_cookie('message', 'Page updated') + return resp + + def action_edit_GET(self, req, page): + text = self.edit_template.substitute( + page=page, req=req) + return Response(text) + +class Page(object): + def __init__(self, filename): + self.filename = filename + + @property + def exists(self): + return os.path.exists(self.filename) + + @property + def title(self): + if not self.exists: + # we need to guess the title + basename = os.path.splitext(os.path.basename(self.filename))[0] + basename = re.sub(r'[_-]', ' ', basename) + return basename.capitalize() + content = self.full_content + match = re.search(r'<title>(.*?)</title>', content, re.I|re.S) + return match.group(1) + + @property + def full_content(self): + f = open(self.filename, 'rb') + try: + return f.read() + finally: + f.close() + + @property + def content(self): + if not self.exists: + return '' + content = self.full_content + match = re.search(r'<body[^>]*>(.*?)</body>', content, re.I|re.S) + return match.group(1) + + @property + def mtime(self): + if not self.exists: + return None + else: + return os.stat(self.filename).st_mtime + + def set(self, title, content): + dir = os.path.dirname(self.filename) + if not os.path.exists(dir): + os.makedirs(dir) + new_content = """<html><head><title>%s</title></head><body>%s</body></html>""" % ( + title, content) + f = open(self.filename, 'wb') + f.write(new_content) + f.close() + +if __name__ == '__main__': + import optparse + parser = optparse.OptionParser( + usage='%prog --port=PORT' + ) + parser.add_option( + '-p', '--port', + default='8080', + dest='port', + type='int', + help='Port to serve on (default 8080)') + parser.add_option( + '--wiki-data', + default='./wiki', + dest='wiki_data', + help='Place to put wiki data into (default ./wiki/)') + options, args = parser.parse_args() + print 'Writing wiki pages to %s' % options.wiki_data + app = WikiApp(options.wiki_data) + from wsgiref.simple_server import make_server + httpd = make_server('localhost', options.port, app) + print 'Serving on http://localhost:%s' % options.port + try: + httpd.serve_forever() + except KeyboardInterrupt: + print '^C' |