07/18: A date to remember

Mark the 18th of July as an important date on your calendar. I certainly have. Let it be remembered as the day that you finally update your feeds and subscribe to my blog over at LiveJournal. (Posted on both LiveJournal and Blogger)

Goodbye, Blogger

Having used Blogger for a while, I've come to hate its interface. Therefore, I'm going to use LiveJournal for a while. My new blog address is kurtmckee.livejournal.com. Remember to subscribe to my new Livejournal feed!

Python's time module

So I've been working like a fiend to import all of my comments from around the internet. It has been a herculean effort because almost everything has to be done manually. One comment here, another there, and no uniform way to extract those comments.

Two sites, however, made comment retrieval easy: Xanga and Slashdot. Both offer fine lists of my old comments. I first scraped Xanga for all of my old comments, but stumbled when converting the dates and times of my comments into a usable format: while Xanga outputs dates and times in the form 1/1/2006 1:22 AM, I need output in the form 2006-01-01 01:22:00 for import into the comment-tracking software I'm writing.

I hacked together some trivial regular expressions and had a solution in about ten minutes. However, I then wondered if there was software that could convert the dates and times for me. Surprise, it's already included in Python! Python's time module includes a function called 'strptime' that does all of the heavy interpretation and standardization of the formats. With that in mind, it'll be no trouble converting Slashdot's comments' dates and times (like Sunday January 01 2006, @01:22AM)!

The moral of the story is, do a little searching before writing your own software; somebody else may have already written a solution for you.

Of molds and such

Once again it's summer in Evanston, and the humidity is wreaking havoc on my perishables. Today I discovered that a uncut pineapple, a pomelo, and a loaf of bread were consumed by mold. Last summer I suffered greatly due to the humidity, including expedited milk expirations, and the loss of potatoes and carrots.

Carrots don't mold, my mother informed me.

That has not been my experience. So, can anyone out there recommend a good dehumidifier?

Hadouken!

Okay, SO, I'm totally throwing myself a party in my honor, and to add pride to pretentiousness, I want everyone to check out the invitation and mark whether you're coming or not so I know how much to pat myself on the back for a party well-thrown.


My birthday party on April 26th went over extremely well. The people meshed well and we had a wonderful time. It all started with Aaron and Allan arriving shortly after 7:00a. We ate at Chipotle, picked up a volleyball, and wandered around campus before heading to the beach.


Desolation


Bow and arrow (Tokuda)


Library (Tokuda)


Laughter (Tokuda)

At the beach, we played foxtail, flew a kite, and when enough people arrived, we played volleyball for a couple of hours. That was a good time, and an inside joke from that time is the source from which the title of this entry originated.


Flight (Tokuda)

As evening came, it was decided that we should go check out the big pile of dirt that was arbitrarily located at the south end of the beach. More fun ensued (primarily for the guys, but we eventually convinced the girls to join us).


Jump


Geronimo (Tsang)


Doubletake (Tsang)


Lemmings (Tsang)


With help (Tsang)


Hug (Tsang)

Some of my crew left, and we headed to Andrea's apartment for pizza. Unfortunately, we experienced a significant delay getting from the first floor to the third floor.

Videos forthcoming, but Youtube is throwing errors right now

Update - There will be no videos for a while; my cell phone is no longer generating videos with playable audio. I mean, there's audio, but no free software nor service supports the audio codec, called QCELP. Thanks for NOTHING, software patents.

Until there are videos, I'll just explain that the elevator was incorrectly rated up to 2,000 pounds, and it ground to a halt just before reaching the third floor. We were rescued after about 45 minutes.



Saved (Tsang)

Eventually we got out of the elevator; the firemen took down our names and told us not to collectively weigh more than 2000 pounds ever again, although we're certain that 10 people, each weighing less than 200 pounds, shouldn't have caused the elevator to stall.

Pizza was awesome, Lock was awesome, and then we went to Prairie Moon. This birthday party was exactly the experience I needed. Thanks everyone!

A group shot of the remnant prior to Prairie Moon:


Huddle (Tokuda)

"Bow and arrow", "Library", "Laughter", "Flight", and "Huddle" are copyright 2008 Allan Tokuda. Used with permission.

"Geronimo", "Doubletake", "Lemmings", "With Help", "Hug", and "Saved" are copyright 2008 Andrea Tsang. Used with permission.

Going for broke

Yesterday, while at Sheil, Tim called out Kurt! and flashed some kind of hand gesture at me.

Tim: There, see? I just put a curse on you.
Me: Oh, hexes are the worst. Can you...is that something I can just wash out?
Tim: No, you're stuck with it.
Me: Shoot, and I got the Black Spot last week, too.
Tim: You know I'm from Salem, where all the witches were? Yeah, from Salem. You could go there and get some potions and stuff to lift the curse. It'll cost you, though.
Me: So, you haven't really given me a curse, but a financial burden.
Tim: That's the curse.

F-Spot problems

I know I've been promising to upload photos and videos from my birthday, but I've been running into a roadblock that I don't have any good way to deal with. Consequently, I've had no incentive to organize and select the best photos to upload.

For over a year I've been running an old version of F-Spot -- version 0.4.0 -- because I've not had access to the internet in order to get updates. I now have internet access, and have updated F-Spot to version 0.4.2. In the intervening time, however, F-Spot has changed significantly: where previously it stored my photos' timestamps in Universal Coordinated Time (previously called Greenwich Mean Time) and interpreted the actual date and time by subtracting hours from the time, I'm now finding that the new version of F-Spot believes that the timestamps are now in local time. As a result, all of my photos' timestamps are wrong by five and six hours.

Needless to say, I'm flipping out, and my stress is exacerbated by the fact that F-Spot has had timestamp problems for several years. Of course, my solution right now is to make sure that I force my new photos' timestamps forward by five hours. If it's going to be wrong, I want it to be consistently wrong, so that it can be fixed consistently in the future.

Sigh.

Possibly-related bug reports: 340899, 340903, 332025

Stay strong!

The other day a mother came into the toy store with her young son, Nicolas. Her son was very well-behaved, and played quietly at the train table when she asked him to. My boss commented how pleasant the boy was, and she informed us that he had been having an awful day, and that this was the first time he had been content.

When it came time to leave, however, her son threw a fit and began disagreeing with everything his mother said. It was an amusing psychological response.

Come on, it's time to go to Mandy's house.
I don't want to go to Mandy's house!
But she's having a birthday party, and you'll get to have ice cream!
I don't want to have ice cream!
And you'll see all of your friends there!
I don't want to see all of my friends there!

And so on. She put him in his stroller and I held the door open for them, encouraging poor Nicolas as he continued crying and carrying on.

Stay strong, Nicolas!
I don't want to stay strong! he wailed.

Theftable

Discussing with Allan the possibility of him bringing his small desktop computer.

Allan: I don't know if I should bring it...it's kind of...
Me: Theftable?
Allan: "THEFTABLE". Good use of bad English.

Cherokee 0.6.0 and Django

In this post, I'll detail how to set up Cherokee with Django using FastCGI.

I'll be working under the following assumptions:

  • Python, Django, and flup are properly installed on your system (I'm currently running Python 2.5.1, Django 0.96.1, and flup 1.0)
  • You don't have root, and/or want to run Cherokee only in a development environment
So then, let's begin!

Installing Cherokee

In a terminal, change to the directory to which you downloaded Cherokee 0.6.0, and run these commands to install Cherokee in ~/apps:
    $ tar -xzf cherokee-0.6.0.tar.gz
$ cd cherokee-0.6.0/
$ ./configure --prefix=$HOME/apps
$ make
$ make install
$ mkdir ~/apps/var/log
$ mkdir ~/apps/var/run
We made those two directories at the end so that Cherokee can write to access and error logs, and start and stop Cherokee from our web browser.

Starting a Django project

We'll need a Django project to work with. Let's create one in ~/project.
    $ cd ~
$ django-admin.py startproject project
Couldn't be simpler. Of course, if you already have a Django project, take note of its path (and especially the path leading up to the project; in our case we need to remember the path of our home directory: /home/user).

Configuring Cherokee


Alright, time to try out the new Cherokee admin console!
    $ ~/apps/sbin/cherokee-admin
Now open a web browser and go to http://localhost:9090/. You'll see something like this:



Let's first customize the settings in the "General" page:
  • Port: 8080 (must be above 1023, since we don't have root)
  • Port TLS: 8443 (in case we set up HTTPS later)
Click "Submit". Note that this does not save our changes to Cherokee's configuration file! This merely saves our changes temporarily. You must click "Apply" to permanently save your changes.

Next, open the "Virtual Servers" page:



Cherokee requires that the "default" virtual server (or "vserver") always exist as a fall back, but it is possible to create other virtual servers. Thus, you could create a second vserver, bound to a particular domain (like "beta.kurtmckee.org"), that functions under a completely separate set of rules. We won't explore that here, but I recommend exploring it further. For now, let's focus on customizing the "default" vserver. First click on its name in the "Virtual Server List".

You'll be presented with six different sections, starting with "Basics". Let's skip directly to "Behavior":



You see that there are a number of rules already defined for us. By default, Cherokee is configured to run PHP applications like Wordpress or Gallery, but we want a comprehensive Django-based solution! Be sure to study the default rules before continuing, as these rules are very informative, and you'll surely want to customize things later (perhaps by running other software alongside your Django project). For instance, you should notice the "Priority" column -- the larger the number, the sooner the rule is applied.

OK, so go ahead and delete every rule except the first (the '/' directory rule, priority 1). Then, click on the '/' link (it's very small). You'll be presented with this screen:



Change the "Handler" to "FastCGI", and you'll be presented with this screen:



Make absolutely sure to uncheck "Check file"! I have yet to figure out why, but if this is left checked, the variables that your Django application will see will be seriously b0rked up. You should also check "Error handler", which will prevent Cherokee from intercepting the pretty Django debug output and replacing it with terse HTTP error codes. Next, enter the following for the "Host" and "Interpreter":
  • Host: 127.0.0.1:8070 (or whatever port you want, but remember that port)
  • Interpreter: django-admin.py runfcgi host=localhost port=8070 --pythonpath=/home/user

There are two things to note here. Number one, if you set the "Interpreter", Cherokee will be able to automatically start the Django FastCGI server if it's not already running. This is a Good Thing (TM). Second, remember how I told you to keep note of the path to your Django project? You need to change the "pythonpath" argument to the "Interpreter". Since we created the Django project in /home/user/project/, we entered /home/user. Change the argument
accordingly, and then click "Add".

After clicking add, you will see a new line which will allow you to set environment variables for the "Host" and "Interpreter" you just entered. Enter these values:
  • Variable: DJANGO_SETTINGS_MODULE
  • Value: project.settings
Click "Add" at the end of the line. Then, click "Submit Query". You'll see something similar to this screen:



Now click "Apply", which will save our changes to the Cherokee configuration file. You will be taken back to the Cherokee admin welcome screen, which will inform you that the server is not running. Click "Launch" and cross your fingers, because we're about to test our setup! Assuming you see the following screen, then Cherokee is now listening on localhost, port 8080.



So let's visit our new Django project, which is running at http://localhost:8080/! If everything goes well, you should be presented with the following screen:



Congratulations, you've got a functioning Django FastCGI server connected to your brand-new Cherokee installation. There's just one last thing, which I'll leave as a screenshot-less exercise for the reader: when you enable Django's built-in administration, you'll find that things aren't working so well. That will be because Django is requesting media from a (surprise) /media URL. Cherokee is in turn passing this /media URL right back to Django, which doesn't help us at all. You'll need to add a second rule to the "default" vserver with a higher priority than the '/' directory rule. Here's the relevant information:
  • Entry: /media
  • Type: Directory (already selected)
  • Handler: List & Send (already selected)
  • Priority: 100 (or 2, or anything greater than the '/' directory rule's priority)
You'll click "Submit Query" and then edit your new rule, changing the "Document Root" to the Django admin media directory on your filesystem (in my case, that directory is located at /usr/lib/python2.5/site-packages/django/contrib/admin/media/.

Prince of Peace


Prince of Peace

At the 2005 Crusade men's retreat

Announcing Tricycle

When Mat Honan's website Barack Obama is your new bicycle launched, it spawned a number of copycat and parody websites. I thought, "Hey, there might be people who don't have the ability to write their own software, but would enjoy having their own is-your-new-bicycle site." Thus, I wrote Tricycle.

Tricycle is a simple way for anyone to host their own "is your new bicycle" site. Just download and copy index.php into your directory. Modify the settings and you'll be all set.

Tricycle is licensed under the GNU AGPL version 3, so it is 100% free software. Check it out!

Update - Check out Tricycle in action over at Dave Woods is your new bicycle!

Unit testing

I just committed basic unit testing support to Renquist, implemented using Python's unittest framework. The results were quite pleasing. Now I can quickly run multiple automated tests to ensure correct behavior and avoid regressions! Huzzah!

For my first two tests I decided to try using a blank file as both a Feed and as a List. The blank Feed test uncovered a bug I hadn't considered, while the blank List test made me fix a problem I had already tagged as a failure point in the comments of the source code. Both bugs are fixed now, but there's surely still a lot of code that isn't being touched by these tests. But how can I identify those untested lines of code?

The first thing I thought after writing those two test cases was, There should be a way to visually identify the untested code. After looking through the Python documentation, the first thing I found was the "trace" module, which can output every single line that gets run. It would take almost no work at all to generate a very simple HTML file, highlighting tested code (or untested code).

Before I write that software, though, I'm going to search a little online. I can't imagine that someone else hasn't had that idea, too.

Here's to automated testing!