Archive for February, 2008
blogggg! A blog engine for the ages.
In the past 3 years, blogs have popped up faster than Starbucks locations, and we want to be the first to say: “Me too!” Ok, maybe we’re not the first to be the second, but that’s not going to stop us from cramming the world’s already-full blog hole with yet another blog engine. We’re jumping onto the dog pile… er… “blog pile.”
You might ask, “why?” Because it’s easy; that’s why!! It’s so easy that it seems people just can’t help themselves. We’re no different. Here’s a history lesson:
In the beginning, there was static content. And it was good. But then there was a problem: it was fast and didn’t use enough bandwidth. What good are fat pipes if you’re not going to cram them full of bloat?

Enter: “The blog”
What is it you ask? It’s static content, but served dynamically!!! This is the kind of thing we can get behind. Plus, it has the added bonus of being able to trivially produce eye-rot candy like tag clouds.
Blogggg!
To the point, we’ve written our own blog software: Blogggg! If you’re going to compete with all 100+ other blog engines out there, you need to have a catchy name. Our is super catchy because you say it like “blog” but you say it like you’re on meth. The exclamation point is absolutely mandatory as its emphatic qualities underscore our gratuitous use of the letter: “g”. It’s a recipe for success!!!
Design
We’re living in a database-driven world… no use in trying to change that now. Since SQL can be really hard (and you know how we hate solving hard problems), how will we overcome our debilitating laziness while simultaneously being a sheep in web 2.0 flock? Luckily, we aren’t the first programmers to try and avoid this mysterious and ancient SQL technology. We turn to Object Relational Mapping.
We here at Code Irony worship “The Python” no matter what it ends up costing us in our careers or hygiene. We need an ORM and we have The Snake… That can mean only one thing: sqlalchemy (not true… ORMs grow on trees). Sit back and watch the hits come in. Brilliant!!!!
The Code
There are two parts to blogggg! — submitting a blog post, and viewing it. When you submit the post, it is stored in a database backend using the code below. The first time you run the post code, you’ll need to feed it the command “create_db” — this will set up the magical database backend for you (don’t worry about understanding that part).
>python post.py create_db
Once this is set up, write your text to a file, and run the post command again, only with your post file as the input:
>python post.py mypost.html
Then, when you want to view your static content, you use the view code, as shown below. To get a simple server going, just run:
>python serve.py
And then navigate in your browser to http://localhost:8080/mypost.html. Look, there’s your post!
It’s so simple! And no SQL was necessary! We’re well on our way to serving this static content as fast as the Python interpreter can!

Deployment
Blogggg! will only work locally using the code above. Our blog software needs to be deployed for the real world — how else will thousands of people be able to view our witty static content?!?!?
First, we need to set up our code to run in a served environment. We’ll use Apache to get rid of that silly :8080 after the domain. Then, we’ll need to install mod_fastcgi on Apache. If you don’t know how to do that, use Google — it’ll practically compile itself! Just like that scene in Fantasia.
Then install flup… it’ll do convert the output from our application into something that Apache can use. You can use:
>easy_install flup
Then, at the top of the serve.py file, add this:
#!/usr/bin/python from flup.server.fcgi import WSGIServer
and at the bottom, add this:
app = cherrypy.tree.mount(MyBlog())
cherrypy.engine.start(blocking=False)
try:
WSGIServer(app).run()
finally:
cherrypy.engine.stop()
Then in httpd.conf, add these lines:
FastCgiIpcDir /tmp
FastCgiServer /path/to/serve.py -idle-timeout 120 -processes 4
and in your directory that you’re serving from, add a file named .htaccess with this inside:
AddHandler fastcgi-script .py
ScriptAliasMatch (.*$) /path/to/cherry.py$1
If you’ve been following, you can now go to your domain name, append “myentry.html” and you’ll see your text! It was so simple! If there’s an easier way to serve static content, be sure to let us know (but we’ll be skeptical for sure!)!
post.py
# Filename: post.py # Revision: 0.1 # # Copyright 2008 Christopher Myers and Justin Davis # # blogggg! poster # Load the content, and you’re almost done # # You have unlimited license to use this software however you want. There # is no warranty either expressed nor implied. Actually, we recommend not # using it. It just exists to prove a point. from sqlalchemy import * import datetime db = create_engine(’sqlite:////home/guido/blogg.db’) meta = MetaData(db) blog_entries = Table(‘entries’, meta, Column(‘entry’, String(), primary_key = True), Column(‘url’, String()), Column(‘date’, DateTime, default=datetime.datetime.now()) ) class Entry(object): def __init__(self, text, url): self.entry = text self.url = url orm.mapper(Entry, blog_entries) session = orm.create_session(bind=db) if __name__ == “__main__”: import sys if sys.argv[1] == “create_db”: blog_entries.create(bind=db) else: f = open(sys.argv[1]).read() entry = Entry(f, sys.argv[1]) session.save(entry) session.flush()
serve.py
# Filename: serve.py # Revision: 0.1 # # Copyright 2008 Christopher Myers and Justin Davis # # blogggg! server # Now, watch the hits come in! # # You have unlimited license to use this software however you want. There # is no warranty either expressed nor implied. Actually, we recommend not # using it. It just exists to prove a point. import postimport cherrypy class MyBlog: def default(self, url): my_query = post.session.query(post.Entry) my_entry = my_query.filter_by(url=url).first() return my_entry.entry default.exposed = True cherrypy.quickstart(MyBlog())20 comments
Fastest templating engine ever. Period.
Since web frameworks seem to be the only thing people are doing in Python these days, templating languages have become increasingly important. The problem that we at Code Irony keep running into is that they’re just not fast enough. How slow are they? We ran some profiling across one of our projects and this is what we’ve found:
<h1>Hello %(name)s</h1>
After many usability tests, we found that the %(variable)s syntax is the easiest for people to understand. Furthermore, we want to be sure to separate the logic from the presentation, so we only want to replace strings. Save this file to hello.html Then, in your web framework, just import our template engine and use the code like this:

from contemplate import ConTemplate
mytemplate = ConTemplate("hello.html")
name = "Guido"
print mytemplate.render()
> <h1>Hello Guido</h1>
Look! ConTemplate filled in your name and everything! Now, we all know that speed is the real factor in making a templating language. Check out how ConTemplate stacks up against some of the competition:
| Template | Processing Time |
|---|---|
| Genshi | .110s |
| Mako | .109s |
| ConTemplate | .107s |
Wow! On our first try, we beat the two fastest python templating languages! And Genshi lost by almost 3%! Imagine how fast it’ll be when version 2 comes out! You can get the benchmark test here and download the implementation here, or browse it below.
# Filename: contemplate.py # Revision: 0.1 # # Copyright 2008 Christopher Myers and Justin Davis # # “ConTemplate” # This is by far the fastest python templating language you’ve ever used. # # You have unlimited license to use this software however you want. There # is no warranty either expressed nor implied. Actually, we recommend not # using it. It just exists to prove a point. import inspect class ConTemplate(object): def __init__(self, filename): “”“Load the template”“” try: self.template = open(filename).read() except IOError: raise IOError, “No file at that location” def render(self, locs = None): “”“Render the template”“” if not locs: locs = globals() locs.update(inspect.currentframe(1).f_locals) return self.template % locs32 comments