#!/usr/bin/python import time class FeedError(Exception): pass def escape_xml(s): """Escape special characters in XML.""" chars = { "<" : "lt", ">" : "gt", "&" : "amp", '"' : "quot", "'" : "apos" } cs = [] for c in s: if chars.has_key(c): cs.append("&" + chars[c] + ";") else: cs.append(c) return "".join(cs) def wrap(name, value): if value is None: return "" else: return "<" + name + ">" + escape_xml(value).encode("UTF-8") + "\n" class Channel: """A summary of a syndicated site.""" def __init__(self, title, link, description): self.title = title self.link = link self.description = description self.items = [] def add_item(self, *args, **keywords): """Add an item to the feed. The arguments to this method are the same as for the Item constructor.""" self.items.append(Item(*args, **keywords)) def rss2(self): """Return the RSS 2.0 representation of this feed.""" bits = [] bits.append('\n') bits.append('\n') bits.append('\n') bits.append(wrap("title", self.title)) bits.append(wrap("link", self.link)) bits.append(wrap("description", self.description)) for item in self.items: bits.append('\n') bits.append(wrap("title", item.title)) bits.append(wrap("link", item.link)) bits.append(wrap("description", item.description)) if item.pubDate is not None: d = item.pubDate if type(d) is not tuple and type(d) is not time.struct_time: d = time.gmtime(d) s = time.strftime("%a, %d %b %Y %H:%M:%S +0000", d) bits.append(wrap("pubDate", s)) bits.append('\n') bits.append('\n\n') return "".join(bits) class Item: """An item in a syndication feed.""" def __init__(self, title = None, link = None, description = None, pubDate = None): if title is None and description is None: raise FeedError("Item must have either title or description") self.title = title self.link = link self.description = description self.pubDate = pubDate if __name__ == "__main__": c = Channel(title = "Test Stuff", link = "http://teststuff.example.com/", description = "Some test items for feedwriter") c.add_item(title = "Title only") try: c.add_item(link = "http://example.com/") except FeedError: pass else: raise "Expected exception here" c.add_item(title = "All of them", link = "http://example.com/", description = "Here's some stuff complete with embedded HTML.", pubDate = time.time()) print c.rss2()