Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Switch to using templates to generate the HTML instead

of hardcoded strings inside the program.
  • Loading branch information...
commit 3899e8053932055757bbbcb4d82862f6015a1ba9 1 parent 3bb838b
@mhagander authored
Showing with 129 additions and 113 deletions.
  1. +23 −11 generator.py
  2. +50 −101 planethtml.py
  3. +55 −0 template/index.tmpl
  4. +1 −1  www/css/planet.css
View
34 generator.py
@@ -8,13 +8,15 @@
"""
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 @@ def __init__(self,db):
show_body_only=1,
clean=1,
)
+ self.items = []
+ self.feeds = []
def Generate(self):
@@ -35,34 +39,43 @@ def Generate(self):
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 @@ def TruncateAndCleanDescription(self, txt, title):
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 @@ def __init__(self, maxlen, title = None):
self.trunctxt = ''
self.tagstack = []
self.skiprest = False
- self.title = title
def feed(self, txt):
txt = txt.lstrip()
View
151 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 @@
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="/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">&nbsp;</div>
- <p>Posted by %s on <span class="date">%s at %s</span></p>
- <div class="ppa_bottom">&nbsp;</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()
View
55 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="/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">&nbsp;</div>
+ <p>Posted by <%call expr="coalescelink(post.author, post.blogurl)"></%call> on <span class="date">${post.datetime}</span></p>
+ <div class="ppa_bottom">&nbsp;</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>
View
2  www/css/planet.css
@@ -88,7 +88,7 @@ div.planetPostAuthor {
overflow: hidden;
}
-div.planetPostAuthor a.author {
+div.planetPostAuthor a {
font-style: italic;
}
Please sign in to comment.
Something went wrong with that request. Please try again.