2009-04-04 02:46:16
0.7.0 Work
I've been doing some work in git (although less, now that I have real work at real work) towards the features for 0.7.0. The first thing that's shown major progress is the new interface_draw hooks. These provide a much simpler way to add content to the interface (reader or gui) than the previous class inheritance method. For example, I moved over the slashdot department information renderer from canto/extra.py.
In < 0.7.0 you had to do this to get the information:
class slashdot_renderer(interface_draw.Renderer): def reader_head(self, dict): title = self.do_regex(dict["story"]["title"], self.story_rgx) return [(u"%1%B" + title, u" ", u" "),\ (u"%bfrom the " + dict["story"]["slash_department"] +\ u" department%B", u" ", u" "),(u"┌",u"─",u"┐%C")] default_renderer(slashdot_renderer())
Which is a total pain in the ass for a number of reasons. First, if you ever wrote two snippets to add content to the reader_head function, then you'd have to really work hard to try and combine the content. So far this hasn't been an issue, but I believe that's because people have no idea how to do this, or it requires too much Python, or people just don't know what's in their feeds (more on this later). Second, if you applied this custom renderer to just a feed or two, this is a needless waste of memory because two Renderers (with their boilerplate code) have been instantiated when you make such a simple change. Lastly, the changes that are made are full of very cryptic garbage that the user doesn't care about 99% of the time.
So, the new syntax is much easier. Instead of editing the format that is convenient to the renderer, you can edit things in either HTML or plaintext. The above can be achieved with the following, much clearer bit of code.
# Define a hook def add_slash_dept(dict): if "slash_department" in dict["story"]: dict["content"] = "%1from the " + dict["story"]["slash_department"]\ + " department%0<br /><br />" + dict["content"] # Register hooks r = get_default_renderer() ... add_hook_pre_reader(r, add_slash_dept, before="reader_convert_html") ...
This is still subject to change, but so far I'm happy with the conventions. Each hook gets a dict with the current state of the data being worked on, particularly dict["content"]. The hook makes it's changes and exits and then the next hook is called, makes its changes and so on. The default renderer comes with a number of basic hooks already included, like a hook to render HTML into normal text. This example is added to the pre_reader hooks before "reader_convert_html" so that it's content is rendered as HTML as well (notice the br tags in the hook). Changing data before conversion makes it simple to add things like links, or formatting like block quotes and strong tags.
This will obviously need to be well documented, but the bottom line is that it's 10x simpler to just add strings together than fuck around with the previous format and it's unnecessary Unicode handling, and undocumented functions.
The above code actually works with the HEAD of the experimental-idraw branch of git.
canto-inspect
As I mentioned above, one of the problems with previous versions of Canto and, in fact, all feed readers, is that's it's hard to take advantage of the great, non-standard content that's in them. For example, Slashdot's got extra content, Digg has all sorts of extras, like getting the current number of digs a particular item has, how many comments. I'm sure there are many more.
This is why 0.7.0 is now going to contain a third binary canto-inspect that will be able to either use feed data already downloaded for canto, or just grab a URL with feedparser and print out the interesting contents, to let users find interesting data that's in their RSS feeds and help them write an interface hook that will exploit that information.
More status
In other news, the proposed speed-ups for larger lists of items has been temporarily put on hold until I can figure out why the code is as fast as it is. I implemented some work on speeding up the rendering process, but after putting some hours in on the "new and improved" code, the profiler says it's actually 5% slower. Which is ridiculous, but I think it may mean that Python is doing something intelligent in the background, or that the rendering task is much more IO bound than I believed. It could also be just that I didn't stress either codebase hard enough. Before 0.7.0 I will figure this out.
Please, feel free to discuss these topics on the ML, I'd love to get some user feedback on the new style syntax.
In the meantime, have fun!