36b37712c670 webpy-sucks

Get a bare Cherrypy server up and running.
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Tue, 02 Mar 2010 20:23:36 -0500
parents 256716e3a3d7
children 8e18e2c40a06
branches/tags webpy-sucks
files review/web_templates/changeset.html review/web_templates/review.html review/web_ui.py

Changes

--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/review/web_templates/changeset.html	Tue Mar 02 20:23:36 2010 -0500
@@ -0,0 +1,135 @@
+$def with (rd, rcset)
+
+$ ctx = rd.target[rcset.node]
+<h2>Changeset ${ ctx.rev() }: ${ ctx.description() }</h2>
+
+$ review_level_comments = rcset.review_level_comments()
+$for comment in review_level_comments:
+    <div class="comment">
+        <div class="avatar"><img height="52" width="52" src="http://www.gravatar.com/avatar/${ md5(email(comment.author)).hexdigest() }?s=52"/></div>
+        <div>
+            <div class="author"><a href="mailto:${ email(comment.author) }">${ templatefilters.person(comment.author) }</a> said:</div>
+            <div class="message">${ comment.message }</div>
+        </div>
+    </div>
+
+<div id="comment-review">
+    <p class="comment-activate"><a href="">Add a comment on this changeset</a></p>
+    <form id="comment-review-form" method="post" action="">
+        <div class="field">
+            <label for="body">Add a comment on this changeset:</label>
+            <textarea cols="60" rows="6" name="body"></textarea>
+        </div>
+         <div class="buttons">
+            <input type="submit" class="button" value="Submit" />
+         </div>
+    </form>
+</div>
+
+<h2>Files</h2>
+
+$for filename, diff in rcset.diffs().iteritems():
+    <div class="file-review">
+        <div class="filename-header">
+            <a class="fold-file" href="">&nbsp;&nbsp;&nbsp;&darr;</a>
+            <h3>${ filename }</h3>
+        </div>
+        
+        <div class="file-review-contents">
+            $ file_level_comments = rcset.file_level_comments(filename)
+            $for comment in file_level_comments:
+                <div class="comment">
+                    <div class="avatar">
+                        <img height="52" width="52" src="http://www.gravatar.com/avatar/${ md5(email(comment.author)).hexdigest() }?s=52"/>
+                    </div>
+                    <div>
+                        <div class="author"><a href="mailto:${ email(comment.author) }">${ templatefilters.person(comment.author) }</a> said:</div>
+                        <div class="message">${ comment.message }</div>
+                    </div>
+                </div>
+                
+            
+            <div id="comment-file">
+                <p class="comment-activate"><a href="">Add a comment on this file</a></p>
+                <form id="comment-file-form" method="post" action="">
+                    <div class="field">
+                        <label for="body">Add a comment on this file:</label>
+                        <textarea cols="60" rows="6" name="body"></textarea>
+                    </div>
+                    <div class="buttons">
+                        <input type="submit" class="button" value="Submit" />
+                    </div>
+                    <input type="hidden" name="filename" value="${ filename }" />
+                </form>
+            </div>
+            
+            <div class="diff">
+                <table>
+                    $ max_line = diff['max']
+                    $ content = diff['content']
+                    $ line_level_comments = rcset.line_level_comments(filename)
+                    $ previous_n = -1
+                    $for n, line in content:
+                        $if n - 1 > previous_n:
+                            $ skipped_count = n - previous_n
+                            $if previous_n == -1:
+                                $ skipped_count -= 1
+                            <tr class="skipped">
+                                <td><code>&hellip; skipped ${ skipped_count } lines &hellip;</code></td>
+                            </tr>
+                        $ skipped_comments = filter(lambda c: max(c.lines) in range(previous_n + 1, n), line_level_comments)
+                        $for comment in skipped_comments:
+                            <tr><td class="comment">
+                                <div class="avatar"><img height="52" width="52" src="http://www.gravatar.com/avatar/${ md5(email(comment.author)).hexdigest() }?s=52"/></div>
+                                <div>
+                                    <div class="author"><a href="mailto:${ email(comment.author) }">${ templatefilters.person(comment.author) }</a> said (on a skipped line):</div>
+                                    <div class="message">${ comment.message }</div>
+                                </div>
+                            </td></tr>
+                        $ kind = 'rem' if line[0] == '-' else 'add' if line[0] == '+' else 'con'
+                        <tr class="${ kind }">
+                            <td class="diff-line"><code>${ line[1:] or ' ' }</code></td>
+                        </tr>
+                        $ line_comments = filter(lambda c: max(c.lines) == n, line_level_comments)
+                        $for comment in line_comments:
+                            <tr><td class="comment">
+                                <div class="avatar"><img height="52" width="52" src="http://www.gravatar.com/avatar/${ md5(email(comment.author)).hexdigest() }?s=52"/></div>
+                                <div>
+                                    <div class="author"><a href="mailto:${ email(comment.author) }">${ templatefilters.person(comment.author) }</a> said:</div>
+                                    <div class="message">${ comment.message }</div>
+                                </div>
+                            </td></tr>
+                        <tr class="comment-line">
+                            <td>
+                                <form id="comment-line-form" method="post" action="">
+                                    <div class="field">
+                                        <label for="body">Add a comment on this line:</label>
+                                        <textarea cols="60" rows="6" name="body"></textarea>
+                                    </div>
+                                    <div class="buttons">
+                                        <input type="submit" class="button" value="Submit" />
+                                    </div>
+                                    <input type="hidden" name="filename" value="${ filename }" />
+                                    <input type="hidden" name="lines" value="${ n }" />
+                                </form>
+                            </td>
+                        </tr>
+                        $ previous_n = n
+                    $if previous_n < max_line:
+                        $ skipped_count = max_line - previous_n
+                        <tr class="skipped">
+                            <td><code>&hellip; skipped ${ skipped_count } lines &hellip;</code></td>
+                        </tr>
+                        $ skipped_comments = filter(lambda c: max(c.lines) in range(previous_n + 1, max_line), line_level_comments)
+                        $for comment in skipped_comments:
+                            <tr><td class="comment">
+                                <div class="avatar"><img height="52" width="52" src="http://www.gravatar.com/avatar/${ md5(email(comment.author)).hexdigest() }?s=52"/></div>
+                                <div>
+                                    <div class="author"><a href="mailto:${ email(comment.author) }">${ templatefilters.person(comment.author) }</a> said (on a skipped line):</div>
+                                    <div class="message">${ comment.message }</div>
+                                </div>
+                            </td></tr>
+                </table>
+            </div>
+        </div>
+    </div>
\ No newline at end of file
--- a/review/web_templates/review.html	Tue Mar 02 19:49:35 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-$def with (rd, rcset)
-
-$ ctx = rd.target[rcset.node]
-<h2>Changeset ${ ctx.rev() }: ${ ctx.description() }</h2>
-
-$ review_level_comments = rcset.review_level_comments()
-$for comment in review_level_comments:
-    <div class="comment">
-        <div class="avatar"><img height="52" width="52" src="http://www.gravatar.com/avatar/${ md5(email(comment.author)).hexdigest() }?s=52"/></div>
-        <div>
-            <div class="author"><a href="mailto:${ email(comment.author) }">${ templatefilters.person(comment.author) }</a> said:</div>
-            <div class="message">${ comment.message }</div>
-        </div>
-    </div>
-
-<div id="comment-review">
-    <p class="comment-activate"><a href="">Add a comment on this changeset</a></p>
-    <form id="comment-review-form" method="post" action="">
-        <div class="field">
-            <label for="body">Add a comment on this changeset:</label>
-            <textarea cols="60" rows="6" name="body"></textarea>
-        </div>
-         <div class="buttons">
-            <input type="submit" class="button" value="Submit" />
-         </div>
-    </form>
-</div>
-
-<h2>Files</h2>
-
-$for filename, diff in rcset.diffs().iteritems():
-    <div class="file-review">
-        <div class="filename-header">
-            <a class="fold-file" href="">&nbsp;&nbsp;&nbsp;&darr;</a>
-            <h3>${ filename }</h3>
-        </div>
-        
-        <div class="file-review-contents">
-            $ file_level_comments = rcset.file_level_comments(filename)
-            $for comment in file_level_comments:
-                <div class="comment">
-                    <div class="avatar">
-                        <img height="52" width="52" src="http://www.gravatar.com/avatar/${ md5(email(comment.author)).hexdigest() }?s=52"/>
-                    </div>
-                    <div>
-                        <div class="author"><a href="mailto:${ email(comment.author) }">${ templatefilters.person(comment.author) }</a> said:</div>
-                        <div class="message">${ comment.message }</div>
-                    </div>
-                </div>
-                
-            
-            <div id="comment-file">
-                <p class="comment-activate"><a href="">Add a comment on this file</a></p>
-                <form id="comment-file-form" method="post" action="">
-                    <div class="field">
-                        <label for="body">Add a comment on this file:</label>
-                        <textarea cols="60" rows="6" name="body"></textarea>
-                    </div>
-                    <div class="buttons">
-                        <input type="submit" class="button" value="Submit" />
-                    </div>
-                    <input type="hidden" name="filename" value="${ filename }" />
-                </form>
-            </div>
-            
-            <div class="diff">
-                <table>
-                    $ max_line = diff['max']
-                    $ content = diff['content']
-                    $ line_level_comments = rcset.line_level_comments(filename)
-                    $ previous_n = -1
-                    $for n, line in content:
-                        $if n - 1 > previous_n:
-                            $ skipped_count = n - previous_n
-                            $if previous_n == -1:
-                                $ skipped_count -= 1
-                            <tr class="skipped">
-                                <td><code>&hellip; skipped ${ skipped_count } lines &hellip;</code></td>
-                            </tr>
-                        $ skipped_comments = filter(lambda c: max(c.lines) in range(previous_n + 1, n), line_level_comments)
-                        $for comment in skipped_comments:
-                            <tr><td class="comment">
-                                <div class="avatar"><img height="52" width="52" src="http://www.gravatar.com/avatar/${ md5(email(comment.author)).hexdigest() }?s=52"/></div>
-                                <div>
-                                    <div class="author"><a href="mailto:${ email(comment.author) }">${ templatefilters.person(comment.author) }</a> said (on a skipped line):</div>
-                                    <div class="message">${ comment.message }</div>
-                                </div>
-                            </td></tr>
-                        $ kind = 'rem' if line[0] == '-' else 'add' if line[0] == '+' else 'con'
-                        <tr class="${ kind }">
-                            <td class="diff-line"><code>${ line[1:] or ' ' }</code></td>
-                        </tr>
-                        $ line_comments = filter(lambda c: max(c.lines) == n, line_level_comments)
-                        $for comment in line_comments:
-                            <tr><td class="comment">
-                                <div class="avatar"><img height="52" width="52" src="http://www.gravatar.com/avatar/${ md5(email(comment.author)).hexdigest() }?s=52"/></div>
-                                <div>
-                                    <div class="author"><a href="mailto:${ email(comment.author) }">${ templatefilters.person(comment.author) }</a> said:</div>
-                                    <div class="message">${ comment.message }</div>
-                                </div>
-                            </td></tr>
-                        <tr class="comment-line">
-                            <td>
-                                <form id="comment-line-form" method="post" action="">
-                                    <div class="field">
-                                        <label for="body">Add a comment on this line:</label>
-                                        <textarea cols="60" rows="6" name="body"></textarea>
-                                    </div>
-                                    <div class="buttons">
-                                        <input type="submit" class="button" value="Submit" />
-                                    </div>
-                                    <input type="hidden" name="filename" value="${ filename }" />
-                                    <input type="hidden" name="lines" value="${ n }" />
-                                </form>
-                            </td>
-                        </tr>
-                        $ previous_n = n
-                    $if previous_n < max_line:
-                        $ skipped_count = max_line - previous_n
-                        <tr class="skipped">
-                            <td><code>&hellip; skipped ${ skipped_count } lines &hellip;</code></td>
-                        </tr>
-                        $ skipped_comments = filter(lambda c: max(c.lines) in range(previous_n + 1, max_line), line_level_comments)
-                        $for comment in skipped_comments:
-                            <tr><td class="comment">
-                                <div class="avatar"><img height="52" width="52" src="http://www.gravatar.com/avatar/${ md5(email(comment.author)).hexdigest() }?s=52"/></div>
-                                <div>
-                                    <div class="author"><a href="mailto:${ email(comment.author) }">${ templatefilters.person(comment.author) }</a> said (on a skipped line):</div>
-                                    <div class="message">${ comment.message }</div>
-                                </div>
-                            </td></tr>
-                </table>
-            </div>
-        </div>
-    </div>
\ No newline at end of file
--- a/review/web_ui.py	Tue Mar 02 19:49:35 2010 -0500
+++ b/review/web_ui.py	Tue Mar 02 20:23:36 2010 -0500
@@ -2,127 +2,145 @@
 from __future__ import with_statement
 
 import sys, os
+from hashlib import md5
+
+from mercurial import cmdutil, hg, templatefilters
+from mercurial.node import short
+from mercurial.util import email
+
 import api
-from mercurial import cmdutil, hg
 
 package_path = os.path.split(os.path.realpath(__file__))[0]
 template_path = os.path.join(package_path, 'web_templates')
 media_path = os.path.join(package_path, 'web_media')
 top_path = os.path.split(package_path)[0]
 bundled_path = os.path.join(top_path, 'bundled')
-webpy_path = os.path.join(bundled_path, 'webpy')
-
-sys.path.insert(0, webpy_path)
-import web
-
+cherrypy_path = os.path.join(bundled_path, 'cherrypy')
+jinja2_path = os.path.join(bundled_path, 'jinja2')
 
-_rd = None
-urls = (
-    '/', 'index',
-    '/media/([^/]*)', 'media',
-    '/review/([\da-f]{12})/?', 'review',
-    '/push/', 'push',
-    '/pull/', 'pull',
-)
+sys.path.insert(0, cherrypy_path)
+sys.path.insert(0, jinja2_path)
+
+import cherrypy
+from jinja2 import Environment, FileSystemLoader
 
 
-from mercurial.node import short
-from mercurial.util import email
-from mercurial import templatefilters
-from hashlib import md5
-g = {
-    'node_short': short,
-    'basename': os.path.basename,
-    'md5': md5,
-    'email': email,
-    'templatefilters': templatefilters,
-}
-render = web.template.render(template_path, globals=g)
+TEMPLATE_DIR = os.path.join(package_path, 'web_templates')
+jinja_env = Environment(loader=FileSystemLoader(TEMPLATE_DIR))
 
-LOG_PAGE_LEN = 25
-
-def render_in_base(fn):
-    def _fn(*args, **kwargs):
-        title, content = fn(*args, **kwargs)
-        return render.base(_rd, content, title)
-    return _fn
-
-class index:
-    @render_in_base
-    def GET(self):
-        rev_max = _rd.target['tip'].rev()
-        rev_min = rev_max - LOG_PAGE_LEN if rev_max >= LOG_PAGE_LEN else 0
-        revs = (_rd.target[r] for r in xrange(rev_max, rev_min, -1))
-        return ('', render.index(_rd, revs))
+class ReviewWebUI(object):
+    def __init__(self, datastore):
+        self.datastore = datastore
+    
+    
+    @cherrypy.expose
+    def index(self):
+        return jinja_env.get_template('index.html').render(
+            datastore=self.datastore
+        )
     
 
-class review:
-    @render_in_base
-    def GET(self, node_short):
-        title = '/ %s:%s &ndash; %s' % (
-            _rd[node_short].target[node_short].rev(),
-            node_short,
-            _rd[node_short].target[node_short].description().splitlines()[0])
-        return (title, render.review(_rd, _rd[node_short]))
-    
-    def POST(self, node_short):
-        i = web.input()
-        body = i['body']
-        filename = i['filename'] if 'filename' in i else ''
-        lines = i['lines'].split(',') if 'lines' in i else ''
-        print filename, lines
-        
-        if body:
-            rcset = _rd[node_short]
-            rcset.add_comment(body, filename, lines)
-        
-        raise web.seeother('/review/%s/' % node_short)
-    
 
-class push:
-    def GET(self):
-        path = web.input()['path']
-        dest, revs, checkout = hg.parseurl(_rd.repo.ui.expandpath(path, path), None)
-        other = hg.repository(cmdutil.remoteui(_rd.repo, {}), dest)
-        
-        _rd.repo.push(other, True, revs=revs)
-        
-        raise web.seeother('/')
-    
-
-class pull:
-    def GET(self):
-        path = web.input()['path']
-        source, revs, checkout = hg.parseurl(_rd.repo.ui.expandpath(path, path), None)
-        other = hg.repository(cmdutil.remoteui(_rd.repo, {}), source)
-        
-        modheads = _rd.repo.pull(other, heads=revs, force=True)
-        
-        if modheads:
-            hg.update(_rd.repo, 'tip')
-        
-        raise web.seeother('/')
-    
-
-class media:
-    def GET(self, fname):
-        if '..' in fname:
-            return ''
-        else:
-            with open(os.path.join(media_path, fname)) as f:
-                content = f.read()
-            return content
-    
-
-def load_interface(ui, repo, open=False):
-    global _rd
-    _rd = api.ReviewDatastore(ui, repo)
-    
-    sys.argv = sys.argv[:1]    # Seriously, web.py?  This is such a hack.
-    app = web.application(urls, globals())
-
+def load_interface(ui, repo, open=False, port=8080):
     if open:
         import webbrowser
-        webbrowser.open(app.browser().url)
+        webbrowser.open('http://localhost:%d/' % port)
+    
+    cherrypy.quickstart(ReviewWebUI(api.ReviewDatastore(ui, repo)))
+
+
 
-    app.run()
+# _rd = None
+# urls = (
+#     '/', 'index',
+#     '/media/([^/]*)', 'media',
+#     '/review/([\da-f]{12})/?', 'review',
+#     '/push/', 'push',
+#     '/pull/', 'pull',
+# )
+# 
+# g = {
+#     'node_short': short,
+#     'basename': os.path.basename,
+#     'md5': md5,
+#     'email': email,
+#     'templatefilters': templatefilters,
+# }
+# render = web.template.render(template_path, globals=g)
+# 
+# LOG_PAGE_LEN = 25
+# 
+# def render_in_base(fn):
+#     def _fn(*args, **kwargs):
+#         title, content = fn(*args, **kwargs)
+#         return render.base(_rd, content, title)
+#     return _fn
+# 
+# class index:
+#     @render_in_base
+#     def GET(self):
+#         rev_max = _rd.target['tip'].rev()
+#         rev_min = rev_max - LOG_PAGE_LEN if rev_max >= LOG_PAGE_LEN else 0
+#         revs = (_rd.target[r] for r in xrange(rev_max, rev_min, -1))
+#         return ('', render.index(_rd, revs))
+#     
+# 
+# class review:
+#     @render_in_base
+#     def GET(self, node_short):
+#         title = '/ %s:%s &ndash; %s' % (
+#             _rd[node_short].target[node_short].rev(),
+#             node_short,
+#             _rd[node_short].target[node_short].description().splitlines()[0])
+#         return (title, render.review(_rd, _rd[node_short]))
+#     
+#     def POST(self, node_short):
+#         i = web.input()
+#         body = i['body']
+#         filename = i['filename'] if 'filename' in i else ''
+#         lines = i['lines'].split(',') if 'lines' in i else ''
+#         print filename, lines
+#         
+#         if body:
+#             rcset = _rd[node_short]
+#             rcset.add_comment(body, filename, lines)
+#         
+#         raise web.seeother('/review/%s/' % node_short)
+#     
+# 
+# class push:
+#     def GET(self):
+#         path = web.input()['path']
+#         dest, revs, checkout = hg.parseurl(_rd.repo.ui.expandpath(path, path), None)
+#         other = hg.repository(cmdutil.remoteui(_rd.repo, {}), dest)
+#         
+#         _rd.repo.push(other, True, revs=revs)
+#         
+#         raise web.seeother('/')
+#     
+# 
+# class pull:
+#     def GET(self):
+#         path = web.input()['path']
+#         source, revs, checkout = hg.parseurl(_rd.repo.ui.expandpath(path, path), None)
+#         other = hg.repository(cmdutil.remoteui(_rd.repo, {}), source)
+#         
+#         modheads = _rd.repo.pull(other, heads=revs, force=True)
+#         
+#         if modheads:
+#             hg.update(_rd.repo, 'tip')
+#         
+#         raise web.seeother('/')
+#     
+# 
+# class media:
+#     def GET(self, fname):
+#         if '..' in fname:
+#             return ''
+#         else:
+#             with open(os.path.join(media_path, fname)) as f:
+#                 content = f.read()
+#             return content
+#     
+# 
+