PyZine
 


Article Finder
People
Issue 5 - Revision 7  /   April 20, 2004 


 
  Py Links:
Latest Issue
Issue 08
Issue 07
Issue 06
Issue 05
Issue 04
Issue 02
Issue 01
 
 
Downloads
     
  Articles:
Throughout the quarter we cover topics of interest to Python developers.

  RSOAP

  Simple Code Generation

  4ss

  Pyro

  PyCon 2004

  Kaa & Firedrop

  XML-RPC for Python

  Applied XML-RPC

 
 
 
     

Illustration by Lia Avant
article
Kaa & Firedrop

Kaa and Firedrop
- Weblogging and site management with Python
- - - - - - - - - - - -

By Hans Nowak | April 3, 2004

print
Abstract

This is an article in two parts. The first part, which is about Kaa, was written a while ago, and has since been updated. In the meantime, I started developing a new program called Firedrop to maintain my site and weblog,. The second part of the article is about this program, which is still under construction. Of the two, Kaa is more mature, but Firedrop holds more promise for the future.



I. Kaa: Weblogging with Python
What is Kaa?

Kaa is a weblogging tool. What, yet another one you ask? Yes. The reason it was written is that I got fed up with Blogger. Blogger isn't bad: I used it for a long time, but there were annoyances that gradually added up – bugs that weren't fixed in time (and which prevented me from blogging), some irritating "features" in the Web interface, etc. So eventually I decided to roll my own weblogging tool. Coded in Python, of course.

Screenshot 1: Selecting an existing entry for editing.

However, Kaa is not a Blogger clone that happens to be written in Python: it has its own unique features. Some of them are:

  • embedded Python code
  • macros
  • flexible archiving
  • configurable buttons
  • "smart" uploading
  • generation of custom pages

More about these features below.

Screenshot 2: Editing an entry.

Kaa is client-based. Many other blogging tools, like Movable Type and Radio Userland, are server-based, which allows for great flexibility, but there is an obvious drawback: you need a server (duh! ;-). Anno 2004, the Internet may have reached many households, but most people don't have their own server running. A client-based tool brings blogging to everyone. Certainly, there are drawbacks: you will not be able to run server-side code, for example. On the other hand, you can blog offline and upload the changes later.

Technologies and techniques used

Kaa should run out of the box if you have a vanilla Python installation as of version 2.2. Earlier Python versions may or may not work. (At least on Windows; so far it's untested on other systems. Reports are welcome.) Still, it's worth mentioning what it uses under the hood:

  • Tkinter. I chose this GUI over wxPython, for several reasons. First of all, I thought (and think) that it's important that you shouldn't have to download many third-party packages. Tkinter comes with Python, other GUIs don't. No extra download is necessary to run Kaa.

    Another reason was that Kaa's GUI is simple, with a main window and a handful of dialogs. If it had used a more complex GUI with lots of windows and sophisticated widgets, then wxPython would have been a more likely candidate.

    (Note: in future versions of Kaa, I want (and need) to decouple the GUI code from the "business logic", which will make it easier to build a custom front-end using wxPython, PyQt, or some other GUI.)

  • Gadfly. For those who don't know, Gadfly is a relational database written in pure Python. It's licensed under the GPL, just like Kaa, so it was no problem to include all the necessary files with the Kaa distribution. I chose it because it's relatively lightweight, and it doesn't require an additional database to be installed. Some people have suggested that Kaa should be able to use other databases. I'm looking into this.

Some features of Kaa

Here's a list of the features that distinguish Kaa from other weblogging tools.

Embedded Python code: I haven't seen this in any other weblogging tool yet. It's not difficult to use (nor is it difficult to code, for that matter). There are two types of embedded code, which can be used wherever HTML is used. Expressions are used with <% %> tags:

<% name %>

takes the value of the variable name, and puts it into HTML.

You can also embed statements or whole code blocks, using <# #> tags:

  <#
    x = y + z
    print "Hello, world!"
    print x
  #>

This type of embedding works slightly differently: anything that is normally printed to sys.stdout is now "printed" to HTML instead. So, in the example above, you would get the string "Hello, world!" and the value of x embedded in HTML. Alternatively, you can also use the doc object, which is just an alias for sys.stdout... doc.write(s), etc. (By the way, as always, indentation matters...it's still Python, even though it's embedded.)

Embedded Python is used in templates to generate custom pages.

Macros: At this moment, there is only one simple type of macro, also known as "HTML macros". A more sophisticated system will hopefully be added in the near future, possibly using regular expressions, etc. The usage of HTML macros is simple. Make a file called htmlmacros.txt with contents like this:

("GPL", "acronym", "title", "GNU General Public License")
("MT", "acronym", "title", "Movable Type")
("IOW", "acronym", "title", "In Other Words")

Screenshot 3: Editing an entry's categories.

Now, if anywhere in your post the text "GPL" is found, a HTML tag is wrapped around it; in this case, an acronym tag with title "GNU General Public License". Other HTML tags can be wrapped like this, too. As mentioned above, this feature is not very powerful, but a better system is in the works.

Flexible archiving: Most weblogging tools allow creation of archives per day, week, month, or per post. Kaa does all that too, but it allows for more flexibility. You can create archives per N days (where N is basically any number you want), or per N posts.

Categories: Posts can be associated with categories. Special archive pages can be made for each category. This is generally a way of classifying messages. Messages can belong to multiple categories.

Configurable buttons: The second toolbar with buttons is user-configurable. By default, it contains buttons to make text bold, italic or teletype (using HTML tags). By editing the config_actions.py file, you can add custom buttons simply by adding the button text and the function to be called to a list. In this module, you can also define your own shortcut keys.

"Smart" uploading: Kaa has the option to post and/or publish pages that have changed since the last post/publication. This is useful if you have a slow Internet connection: not everything is uploaded, but only what's necessary.

Generating custom pages: This is an experimental feature that allows programmers to add their own classes for making custom pages. For example, this can be used to create a page with a list of all posts, and links to them (which isn't possible in the regular framework).

How to use it

Kaa isn't difficult to use, so I'm not going to do a complete walkthrough. Rather, I will highlight some common actions, and take a look at what happens internally.

Creating a blog: Select Blog | New... from the main menu and type the name of the new weblog, preferably an identifier. (No spaces or funky characters, etc.) If your blog is called foo, then the directories html_foo and db_foo will be made. The former stores HTML for uploading, the latter contains the Gadfly database and some other files.

Be sure to enter the necessary information for the weblog... its title, locations of template files, FTP settings, etc.

Opening a blog: Simply use Blog | Open, or use the blog's name (identifier) on the command line (kaa.py foo).

Now you're ready to enter posts. Simply click the "New entry" button and type away. Kaa accepts pure HTML. At this point, no auto-formatting is done. There are a few buttons and menu options to help you here: for example, to make text bold, you select the text and press the "bold" button, which wraps <b> tags around the text.

Saving, posting and publishing: These are three important terms. Their meanings:

Saving: stores an (updated) entry in the database. (No HTML is generated or uploaded.) .

Posting: generates new HTML based on the current posts, templates and settings. (Nothing is uploaded: see below for a more detailed description.)

Publishing: uploads the most recently generated HTML files.

In recent Kaa versions there's a button "One-click publishing" that does these three things for you at once. However, often it may be useful to save a post but not post it yet, or to post it but not publish it yet.

So what does posting do exactly, and how does it work? It generates all the pages necessary: a "front page" with the N most recent entries (where N is a number you can set, of course); archives; possibly, category archives; and maybe custom pages. Each page is based on the page template. Embedded code in that template is evaluated and replaced with the resulting text. Most importantly, the expression <% blog.messages() %> is evaluated. This embeds a number of posts into HTML. In other words, place blog.messages() in your page template at the position where you want the posts to be.

Here's a very simple example of a page template:

<h1><% blog.title %></h1>
<i><% blog.description %></i>
<hr>
<p>
<% blog.messages() %>
<hr>
Generated by Kaa 0.8.

That's not all, though. There is another template, the "entry" template. This determines which parts of a message/post you want to display, and how. Here's a very simple sample entry template:

<h3><% entry.title %></h3>
<% entry.text %>
<br>
<font face="Tahoma" size="1"><% entry.insert_date %></font>
<p>

This displays the title of the post, its text, and the date and time it was inserted.

Of course, you can make the HTML (and the embedded code) much more sophisticated. The sky is the limit. Also, bear in mind that you can use basically any Python code to make your weblog do whatever you want. (This is left as an exercise for the reader. ;- )

Important objects and attributes

As you can see in the examples above, the embedded code appears to use two objects: blog and entry. These objects hold information about the weblog and separate entries, as is obvious by their names. Here are some of their attributes and methods.

blog.title displays the title of the weblog. (Which is not the same as its name, by the way. The "title" is what is displayed on the web page, e.g. "John's weblog". The "name" is the name of the folder containing the files.)
blog.current_page the name of the current page being generated.
blog.categories a list of all categories for this weblog.
blog.description the description of the weblog. (For example: "This is John's weblog about foobar...")
blog.messages() embed posts for the current page. (Which posts these are depends on the page. The "front page" will have posts that are different from those for archive pages.)
blog.next_page The next page in the archive, if any.
blog.previous_page The previous page in the archive. blog.archive_list() - Produces HTML containing a list of all archives, and links to them.
entry.title The title of the entry.
entry.text The text of the entry. (Both title and text can contain HTML. Entry text can contain embedded code as well.)
entry.insert_date The date and time the entry was added. This is a string in the format YYYY-MM-DD HH:MM:SS.
entry.modified_date The date and time the entry was last updated.
entry.misc A dictionary holding some settings. For example, the categories an entry belongs to can be obtained using entry.misc.get("categories", [ ]). (You can do entry.misc["categories"] as well, but this might be unsafe due to KeyErrors.) More keys may be added in the future.
entry.blogentry_id The id of the current entry, as used in the database. This is used to identify entries uniquely (for example, for an annotation system, or for
permalinks see below for a description of how to do this



Some concrete examples

To give you an idea of what is possible with embedded code, here are a few small real-life examples.

How to include the current Kaa version : As mentioned above, you can use any Python code. This includes standard library modules, your own modules, and Kaa modules. In this case, the Kaa version number is in resource.py. It's simple to use: here's the HTML with embedded code:

Generated by Kaa
<#
import resource
print resource.__version__
#>

How to make permalinks: : This is even simpler, since there is now a standard method to do this. (Older Kaa versions didn't have this.) A permalink points to a message in the archives. In the entry template, you can use entry.anchor. This value is set by calling a different method, blog.get_permalink(id), which can be used to create a permalink for any post, not just the current one.



Where from here?

While Firedrop (see the next section) has become more important than Kaa, this does not mean that Kaa development is dead. There's still room for improvement, and I still accept bug reports. Then there are other issues... documentation, for example; refactoring of existing code; adding a test suite; fixing some bugs; making the GUI more user-friendly; etc. Comments, bug reports, tips, ideas, etc are always welcome.



II. Firedrop: a client-side CMS What is Firedrop?

In many ways, Firedrop is the successor of Kaa. It is a client-based tool that allows the user to create weblogs easily, and more. Some of its key features include:

  • GUI based on wxPython/Wax rather than Tkinter
  • entries are stored in separate files rather than in a database
  • allows for other "content types" besides weblogs
  • entries can be written in pure HTML, or custom formats
  • it has powerful macro system
  • written in, and scriptable from, Python

Firedrop is still under development. Some important features have not been implemented yet, and in some areas it is not as user-friendly as it should be. However, the core functionality is in place: I have been using it for months now to maintain my own weblog.

Screenshot 4: Open a site (weblog, articlecollection, etc).


A quick word about the GUI

As mentioned above, Firedrop uses Wax (a friendly layer on top of wxPython) as its GUI. However, by design it can be used without a GUI as well (or maybe with a different GUI toolkit, like Tkinter, if somebody would want to write such an interface).



How Firedrop works

Firedrop is not unlike Kaa, but there are some crucial differences. Most importantly, it builds a site (weblog, documentation, collection of articles, etc) from a number of nodes. A node is a piece of text that represents a weblog entry, an article, etc., depending on the context. In the current version of Firedrop, each node is stored as a separate file. (This has several benefits. For example, it's easy to view and edit these files, and easy to make backups. However, as this might not be the ideal solution for every situation, there's room to implement different storage mechanisms, if necessary.)

Simplicity counts, and therefore a "site" is just a directory containing nodes. Opening a site in Firedrop means selecting a folder - the nodes in it are read into memory and they can be edited at will in the main program.

A site can be built from the nodes by pressing a button or running a script. What "building" means exactly depends on the type of site selected. At the time this is being written, there are two types of sites: Weblog and ArticleCollection (whose names are pretty much self-explanatory).

Screenshot 5: Editing an entry. (A list of entries is on the left; on the right is the text of the currently selected one.)

For a Weblog, every node is considered to be a weblog post. The date of entries is important, and there are built-in functions for generating archives and RSS. For an ArticleCollection, every node is considered to be an "article", appearing on its own page in the eventual HTML. For other (yet to be written) content types, a node can represent whatever you want it to be. So, what "building" does depends on context, but there are a few properties that every Firedrop site has (or must have):

  • a build.ini file
  • a build.py file
  • a page template
  • an entry template

In recent versions of Firedrop, sample files are generated for you, to give you a starting point. You will have to edit them to suit your needs. Especially important is build.ini, because it contains the settings for the FTP server, among other things. The build.ini file is much like an INI file. It contains a number of variables that Firedrop works with - the site's title, description, author, server data (for uploading), etc.

Screenshot 6: Editing an entry's categories.

The build.py script can be run from the command line, but it will also be imported by the Firedrop client to generate the site. (For this it needs a build() function.)

The page and entry templates work much the same as in Kaa, except that some variables and functions have different names.



Anatomy of a Firedrop node

A node is a text file with a simple format. It typically looks like this:

insert_date='2003-12-31 15:16:12'
modified_date='2003-12-31 17:01:33'
--
Title of entry
Body of entry

The part above the "--" contain the node's attributes. Dates of creation and modification (last update) are always added by Firedrop itself; other attributes can be added by hand (or by the client, when using certain menu options). For example, a weblog post can have categories:

insert_date='2003-12-31 15:16:12'
modified_date='2003-12-31 17:01:33'
categories=['python', 'music']
--
Title of entry
Body of entry

The "categories" variable makes sense for weblogs, but not necessarily for other content types. When writing your own type, you can use custom variables. (You always can, but if there's no code to do something with them, they will have no effect, of course.)

The part below the "--" contains the node's actual text. The first line is the title; everything after that is considered to be the node's body.

That's the whole description of the format. Almost. There are a few more "syntactic rules" that aren't really part of the format.



Write in HTML, Textile, or Sextile

You can always write your entries in pure HTML. However, for convenience, there are two other formats supported. These formats allow you to write in (more or less) plain text, with some markup, which is then translated to HTML.

The first format is Textile. Firedrop uses Mark Pilgrim's implementation, PyTextile. An entry is considered to be in this format if the first line of its body contains a single #. (Nothing more, nothing less.) For example, the following entry is in Textile:

insert_date='2003-12-31 15:16:12'
modified_date='2003-12-31 17:01:33'
--
An entry in Textile (This is the title of the entry)
#
Some *text* here...(This is the body of the entry)

The second format is Sextile. The name is both a parody of and a homage to Textile, and should not be unfamiliar to people interested in astrology. :-) It's my own format, written because I was discontented with certain features of Textile. An entry is considered to be in Sextile if the first line of its body contains a single %.



Writing your own content types

This is a complicated subject that really goes beyond the scope of the present article. On top of that, the Firedrop API is still subject to change. However, it's possible to give a few general hints.

To write a new content type, you must subclass the Publisher class. In this subclass, you can define your own methods - for collecting the nodes you want, doing things with custom variables, writing files, etc. Eventually, all the methods that you want to call when the site is built must go into the all() method. For example, the Weblog class' all() currently looks like this:

    def all(self):
        self.create_archives()
        self.create_front_page()
        self.create_category_archives()
        self.create_all_by_category()
        self.create_all_by_date()
        self.create_rss()

The Publisher class defines a number of attributes that are useful, such as a list of all entries, options, macros, the current directory, a shared namespace, and more. Note, however, that this is still subject to change.



So...how mature is it?

Not as mature as Kaa yet. At this point in time, Firedrop is being used by a few people (including myself). It is relatively stable, just not very user-friendly yet. As said, I am working on this. It has most of Kaa's features (such as flexible archiving, smart uploading, etc) and more. There's also a script that makes it easy to convert a Kaa weblog to Firedrop.

Firedrop is still growing new features. Recently it acquired trackback pinging and Atom support, for example. At the GUI level, it gained user-friendly screens to edit build.ini values and categories, and to show the progress when building/uploading.

Screenshot 7: Uploading the site.

Firedrop has been described as "Kaa on steroids", and that's what it eventually will be... if you liked Kaa, it is very much worth a look. Of course, I am open to any bug reports, feature requests, and the like.

For further Reference:

Kaa :
can be downloaded here.

The Kaa development weblog can be found in a section of my personal weblog, which is about more things than just Kaa)
Kaa Weblog

Firedrop:
download (directory contains the latest version)

Firedrop documentation
http://zephyrfalcon.org/labs/

Mark Pilgrim's PyTextile
http://diveintomark.org/projects/pytextile/

Sextile:
http://zephyrfalcon.org/labs/sextile_intro.html


Hans Nowak (hans@zephyrfalcon.org)


shim
shim

 Py is committed to bringing you great Python Articles.

shim
shim


Home   Subscribe   Migration FAQ   Contact PyZine   Write for PyZine   ZopeMag   opensourcexperts.com  

Reproduction of material from any of PyZine's pages without prior written permission is strictly prohibited. Copyright 2003 - 2005 PyZine Zope/Plone hosting by Nidelven IT