diff options
author | Magnus Hagander | 2008-10-23 11:15:29 +0000 |
---|---|---|
committer | Magnus Hagander | 2008-10-23 11:15:29 +0000 |
commit | 1f38b19a00b9f23192ce886934b94502a8e2b36a (patch) | |
tree | 61303663e7fb6af1ac8119afdcbdbcf36d6b4925 | |
parent | dd7d45b4c8e6a30ea757e5056a20ba61dab7cefa (diff) |
Switch to using templates to generate the HTML instead
of hardcoded strings inside the program.
git-svn-id: file:///Users/dpage/pgweb/svn-repo/trunk@2229 8f5c7a92-453e-0410-a47f-ad33c8a6b003
-rwxr-xr-x | planet/generator.py | 34 | ||||
-rw-r--r-- | planet/planethtml.py | 151 | ||||
-rw-r--r-- | planet/template/index.tmpl | 55 | ||||
-rw-r--r-- | planet/www/css/planet.css | 2 |
4 files changed, 129 insertions, 113 deletions
diff --git a/planet/generator.py b/planet/generator.py index 5fb4d3e0..51b67281 100755 --- a/planet/generator.py +++ b/planet/generator.py @@ -8,13 +8,15 @@ Copyright (C) 2008 PostgreSQL Global Development Group """ import psycopg2 +import psycopg2.extensions import PyRSS2Gen import datetime import sys import tidy import urllib +from mako.template import Template from HTMLParser import HTMLParser -from planethtml import PlanetHtml +from planethtml import * class Generator: def __init__(self,db): @@ -26,6 +28,8 @@ class Generator: show_body_only=1, clean=1, ) + self.items = [] + self.feeds = [] def Generate(self): @@ -35,34 +39,43 @@ class Generator: description = 'Planet PostgreSQL', generator = 'Planet PostgreSQL', lastBuildDate = datetime.datetime.utcnow()) - html = PlanetHtml() + psycopg2.extensions.register_type(psycopg2.extensions.UNICODE) + self.db.set_client_encoding('UTF8') c = self.db.cursor() c.execute("SET TIMEZONE=GMT") c.execute("SELECT guid,link,dat,title,txt,name,blogurl,guidisperma FROM planet.posts INNER JOIN planet.feeds ON planet.feeds.id=planet.posts.feed ORDER BY dat DESC LIMIT 30") for post in c.fetchall(): - desc = self.TruncateAndCleanDescription(post[4], post[3]) + desc = self.TruncateAndCleanDescription(post[4]) rss.items.append(PyRSS2Gen.RSSItem( title=post[5] + ': ' + post[3], link=post[1], guid=PyRSS2Gen.Guid(post[0],post[7]), pubDate=post[2], description=desc)) - html.AddItem(post[0], post[1], post[2], post[3], post[5], post[6], desc) + self.items.append(PlanetPost(post[0], post[1], post[2], post[3], post[5], post[6], desc)) c.execute("SELECT name,blogurl,feedurl FROM planet.feeds ORDER BY name") for feed in c.fetchall(): - html.AddFeed(feed[0], feed[1], feed[2]) + self.feeds.append(PlanetFeed(feed[0], feed[1], feed[2])) rss.write_xml(open("www/rss20.xml","w"), encoding='utf-8') - html.WriteFile("www/index.html") - def TruncateAndCleanDescription(self, txt, title): + self.WriteFromTemplate('template/index.tmpl', 'www/index.html') + + def WriteFromTemplate(self, templatename, outputname): + tmpl = Template(filename=templatename, output_encoding='utf-8', input_encoding='utf-8') + f = open(outputname, "w") + f.write(tmpl.render_unicode(feeds=self.feeds, posts=self.items).encode('utf-8')) + f.close() + + + def TruncateAndCleanDescription(self, txt): # First apply Tidy - txt = str(tidy.parseString(txt, **self.tidyopts)) + txt = unicode(tidy.parseString(txt.encode('utf-8'), **self.tidyopts)) # Then truncate as necessary - ht = HtmlTruncator(1024, title) + ht = HtmlTruncator(1024) ht.feed(txt) out = ht.GetText() @@ -73,7 +86,7 @@ class Generator: return out class HtmlTruncator(HTMLParser): - def __init__(self, maxlen, title = None): + def __init__(self, maxlen): HTMLParser.__init__(self) self.len = 0 self.maxlen = maxlen @@ -81,7 +94,6 @@ class HtmlTruncator(HTMLParser): self.trunctxt = '' self.tagstack = [] self.skiprest = False - self.title = title def feed(self, txt): txt = txt.lstrip() diff --git a/planet/planethtml.py b/planet/planethtml.py index dff287d8..89120860 100644 --- a/planet/planethtml.py +++ b/planet/planethtml.py @@ -1,9 +1,8 @@ #!/usr/bin/env python """PostgreSQL Planet Aggregator -This file contains the functions to generate HTML format output. -It's a fairly ugly hack compared to using a real template -system, but... +This file contains helper classes used to store the data when +"communicating" with the templates to generate HTML output. Copyright (C) 2008 PostgreSQL Global Development Group """ @@ -11,102 +10,52 @@ Copyright (C) 2008 PostgreSQL Global Development Group import datetime import urllib -class PlanetHtml: - def __init__(self): - self.items = [] - self.feeds = [] - self.str = """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" dir="ltr"> - <head> - <title>Planet PostgreSQL</title> - <meta http-equiv="Content-Type" content="text/xhtml; charset=utf-8" /> - <link rel="shortcut icon" href="/https/git.postgresql.org/favicon.ico" /> - <link rel="alternate" type="application/rss+xml" title="Planet PostgreSQL" href="http://planet.postgresql.org/rss20.xml" /> - <style type="text/css" media="screen" title="Normal Text">@import url("css/planet.css");</style> - </head> - <body> - <div id="planetWrap"> - <div id="planetHeader"> - <div class="fl"><img src="http://www.postgresql.org/layout/images/hdr_left.png" alt="PostgreSQL" /></div> - <div class="fr"><img width="210" height="80" src="http://www.postgresql.org/layout/images/hdr_right.png" alt="The world's most advanced open source database" /></div> - <div class="cb"></div> - </div> - <div id="planetMain"> -""" - - def AddItem(self,guid,link,dat,title,author,blogurl,txt): - self.items.append((guid,link,dat,title,author,blogurl,txt)) - - def AddFeed(self,name,blogurl,feedurl): - self.feeds.append((name,blogurl,feedurl)) - - def BuildPosts(self): - self.str += """ <div id="planetLeft">""" - lastdate = None - for post in self.items: - if post[6].endswith('[...]'): - txt = post[6][:len(post[6])-5] + """<p>[<a href="%s">continue reading...</a>]</p>""" % (post[1]) - else: - txt = post[6] - - if lastdate == None or lastdate != post[2].date(): - self.str += """ - <div class="planetNewDate">%s</div>""" % (post[2].date()) - lastdate = post[2].date() - - if post[5]: - posterstr = """<a class="author" href="%s">%s</a>""" % (post[5], post[4]) - else: - posterstr = post[4] - - self.str += """ - <div class="planetPost"> - <div class="planetPostTitle"><a href="%s">%s</a></div> - <div class="planetPostAuthor"> - <div class="ppa_top"> </div> - <p>Posted by %s on <span class="date">%s at %s</span></p> - <div class="ppa_bottom"> </div> - </div> - <div class="planetPostContent">%s</div> - <div class="cl"></div> - </div>""" % (post[1], post[3], posterstr, post[2].date(), post[2].time(), txt) +# Yes, a global function (!) +def quoteurl(str): + if str=="": return "" + p = str.split(":",2) + return p[0] + ":" + urllib.quote(p[1]) + +class PlanetPost: + def __init__(self, guid,link,dat,title,author,blogurl,txt): + self.guid = guid + self.link = link + self.dat = dat + self.posttitle = title + self.author = author + self._blogurl = blogurl + self.txt = txt + + + def _get_blogurl(self): + return quoteurl(self._blogurl) + blogurl = property(_get_blogurl) + + def _get_datetime(self): + return self.dat.strftime("%Y-%m-%d at %H:%M:%S") + datetime = property(_get_datetime) + + def _get_contents(self): + if self.txt.endswith("[...]"): + self.txt = '%s<p>[<a href="%s">continue reading</a>]</p>' % (self.txt[:len(self.txt)-5], self.link) + return self.txt + contents = property(_get_contents) + + def _get_title(self): + return self.posttitle + title = property(_get_title) + +class PlanetFeed: + def __init__(self,name,blogurl,feedurl): + self.name = name + self._blogurl = blogurl + self._feedurl = feedurl + + def _get_blogurl(self): + return quoteurl(self._blogurl) + blogurl = property(_get_blogurl) + + def _get_feedurl(self): + return quoteurl(self._feedurl) + feedurl = property(_get_feedurl) - self.str += """ </div>""" - - def quoteurl(self, str): - p = str.split(":",2) - return p[0] + ":" + urllib.quote(p[1]) - - def BuildRight(self): - self.str += """ <div id="planetRight"> -<div class="planetRightTitle">Subscriptions</div> -<ul>""" - for feed in self.feeds: - self.str += "<li>" - if feed[1] != '': - self.str += """<a href="%s">%s</a>""" % (self.quoteurl(feed[1]), feed[0]) - else: - self.str += feed[0] - self.str += """ -<a href="%s"><img src="http://www.postgresql.org/layout/images/ico_rss.png" alt="rss" /></a></li>""" % (feed[2]) - self.str += """ - </ul> - <div class="planetRightTitle">Feeds</div> - <ul> - <li><a href="rss20.xml">Planet PostgreSQL</a> <a href="rss20.xml"><img src="http://www.postgresql.org/layout/images/ico_rss.png" alt="rss" /></a></li> - </ul> - </div> -""" - def WriteFile(self,filename): - self.BuildRight() - self.BuildPosts() - self.str += """ - </div> - </div> -</body> -</html> -""" - f = open(filename,"w") - f.write(self.str) - f.close() diff --git a/planet/template/index.tmpl b/planet/template/index.tmpl new file mode 100644 index 00000000..ae9dff46 --- /dev/null +++ b/planet/template/index.tmpl @@ -0,0 +1,55 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" dir="ltr"> + <head> + <title>Planet PostgreSQL</title> + <meta http-equiv="Content-Type" content="text/xhtml; charset=utf-8" /> + <link rel="shortcut icon" href="/https/git.postgresql.org/favicon.ico" /> + <link rel="alternate" type="application/rss+xml" title="Planet PostgreSQL" href="http://planet.postgresql.org/rss20.xml" /> + <style type="text/css" media="screen" title="Normal Text">@import url("css/planet.css");</style> + </head> + <body> + <div id="planetWrap"> + <div id="planetHeader"> + <div class="fl"><img src="http://www.postgresql.org/layout/images/hdr_left.png" alt="PostgreSQL" /></div> + <div class="fr"><img width="210" height="80" src="http://www.postgresql.org/layout/images/hdr_right.png" alt="The world's most advanced open source database" /></div> + <div class="cb"></div> + </div> <!-- planetHeader --> + <div id="planetMain"> + <div id="planetRight"> + <div class="planetRightTitle">Subscriptions</div> + <ul> +% for feed in feeds: + <li><%call expr="coalescelink(feed.name, feed.blogurl)"></%call><a href="${feed.feedurl}"><img src="http://www.postgresql.org/layout/images/ico_rss.png" alt="RSS"/></a></li> +% endfor + </ul> + <div class="planetRightTitle">Feeds</div> + <ul> + <li><a href="rss20.xml">Planet PostgreSQL</a><a href="rss20.xml"><img src="http://www.postgresql.org/layout/images/ico_rss.png" alt="rss" /></a></li> + </ul> + </div> <!-- planetRight --> + <div id="planetLeft"> +% for post in posts: + <div class="planetPost"> + <div class="planetPostTitle"><a href="${post.link}">${post.title}</a></div> + <div class="planetPostAuthor"> + <div class="ppa_top"> </div> + <p>Posted by <%call expr="coalescelink(post.author, post.blogurl)"></%call> on <span class="date">${post.datetime}</span></p> + <div class="ppa_bottom"> </div> + </div> + <div class="planetPostContent">${post.contents}</div> + <div class="cl"></div> + </div> +% endfor + </div> <!-- planetLeft --> + </div> <!-- planetMain --> + </div> <!-- planetWrap --> + </body> +</html> +<%def name="coalescelink(txt, link)"> +%if link=='': +${txt} +%else: +<a href="${link}">${txt}</a> +%endif +</%def> diff --git a/planet/www/css/planet.css b/planet/www/css/planet.css index b21bd6ae..5a3ae080 100644 --- a/planet/www/css/planet.css +++ b/planet/www/css/planet.css @@ -88,7 +88,7 @@ div.planetPostAuthor { overflow: hidden; } -div.planetPostAuthor a.author { +div.planetPostAuthor a { font-style: italic; } |