Remember your in operator

After you have worked with Python for a while you develop a sense that tingles when you are doing something that feels stupid, or wrong, on unaesthetic. I have found that more often than not someone before me apparently felt the same, and there is a more elegant, or Pythonic way of doing it. One of the simplest cases I find is with the in operator. Consider the following code:

if a == 1 or a == 7 or a == 15:
    do_some_cool_stuff()

This might be a personal pet peeve of mine, but that just feels tedious and somewhat prone to errors. Luckily there is a neater way of doing it using the in operator:

if a in (1, 7, 15):
    do_some_cool_stuff()

There, much less typing, and it looks nice, too!

Performance wise there isn’t that big a difference, at least on 32-bit Linux with CPython. Here are some comparisons with the help of ipython and timeit:

In [1]: a=16
 
In [2]: timeit a == 1 or a == 7 or a == 15
10000000 loops, best of 3: 167 ns per loop
 
In [3]: timeit a in (1, 7, 15)
10000000 loops, best of 3: 155 ns per loop
 
In [4]: timeit a in [1, 7, 15]
10000000 loops, best of 3: 157 ns per loop
 
In [5]: a=1
 
In [6]: timeit a == 1 or a == 7 or a == 15
10000000 loops, best of 3: 72.4 ns per loop
 
In [7]: timeit a in (1, 7, 15)
10000000 loops, best of 3: 83.4 ns per loop
 
In [9]: timeit a in [1, 7, 15]
10000000 loops, best of 3: 83.5 ns per loop

Office Resource Locator Ported to Django

After going through the Django tutorial, I decided to try how Django felt with a (small) real life application. I decided to port Solu (Self-service Office Resource Locator) - an application I originally wrote in Werkzeug.

Django-Solu gained two new features compared to the original: an administrator’s interface, and support for multiple maps. Administrators can add, delete and modify maps (as well as other resources), and when you create a resource you can select the map to put it on. There is no installable package, which is a regression from the original, due to the reasons described below.

At some level I was surprised how similar Django was to Werkzeug. For example, I was able to lift some unit tests and make just minor tweaks like changing a property name to get them to work in Django. There were also some very big differences, most notably in the database layer (compared to SQLAlchemy of which I have prior experience) and templates (compared to Mako Templates).

I can see how I can get stuff done in Django, but I was left puzzled with some pieces. Django seems to make a big deal about applications being self contained, so that (theoretically) you could create an app and anyone could download and install your app in their Django environment. Except this seems to fail a little bit with imports and templates, and spectacularly when dealing with static resources. Imports can be fixed by going through some hoops and modifying PYTHONPATH (which feels like a hack to me), templates by moving them inside the app directory (unlike what the tutorial instructs you to do) and calculating site root etc. in settings.py file (which isn’t actually one of the “standard” settings so you can’t rely on it), but I haven’t figured out any decent solutions for static resources. The problem with static resources is that I don’t know how to point to static resources from templates. Currently I just made these absolute paths, which may need to be edited based on deployment situation. Maybe there is a simple solution I am overlooking, since I can’t imagine Django being so popular with this kind of limitation.

The templates themselves kind of force you to not put any code in the templates, but this has in turn resulted in some bizarre constructs to work around the no code limitations. For example, the template language still allows you to do simple arithmetic with tortured syntax: my_variable|add:"-10" adds -10 to my_variable before printing it out.

The database layer was simple to work with, at least in my simple use case, although there was one point where I was stumped for a while. When searching for resources, I wanted to order the search results in certain way. But there does not seem to be a way to do that in the query syntax. Instead, you need to add a Meta class as a child of each model class and add ordering class attribute. I don’t see how this would work if you wanted to change ordering on the fly or if you have joins and want to order by attributes from different tables. It was also a little difficult to find this information about ordering.

All in all I spent 9-10 hours porting the application, which was roughly what I expected. I spent another 2 hours deploying a live demo application on Dreamhost, which was somewhat more involved than I expected.

Django First Impressions: The Tutorial

I finally started looking at Django, after mostly working with Pylons with a little side project in Werkzeug. I spent a couple of hours going through the Django tutorial, and wrote down my impressions while they were still fresh in my mind. The comments are a mix about Django and the tutorial and the Django website.

  • First of all I was surprised that the installation instructions did not mention you can run easy_install django to get going, even though egg files were mentioned.
  • Main tutorial is for SVN “release”. Personally I don’t consider it a release if it is just an svn revision! You need to notice to click a link to go to the latest actual release tutorial. These seem backwards to me; I’d expect the main version to be for the release, with a link to go to the SVN version.
  • Python config file makes me feel uneasy.
  • Absolute path requirement for config file options seems to make deployment a hassle.
  • Settings file location needs to be specified in an environment variable, which feels a little brittle and hacky.
  • Database API feels hacky with double underscore constructs, but on the other hand model creation seemed simpler than with SQLAlchemy.
  • The tutorial flowed smoothly until it was time to change admin templates. I was expecting a manage.py command to write a default admin template, but instead had to manually copy a file from the Django installation.
  • Admin stuff looks good, but why does the tutorial then break it?
  • There does not seem to be an interactive debugger in browser. Pylons and Werkzeug have this and I love it.
  • Development server does not restart automatically when new files are added. I can’t remember if Pylons/Werkzeug had this problem.
  • The term app isn’t properly explained when first used.
  • View term usage different from what I am used to.
  • I find myself preferring Django’s urlconf over routes at this point, seems clearer.
  • After getting used to Mako templates that allow you to run python, Django templates looks limiting and with some arcane constructs (witness forloop.counter).
  • I was surprised there was no sight of the popular “20 minute wiki” guide. Although a little web search shows showmedo video with this topic. After Pylons documentation I was also expecting some links to screencasts, but didn’t notice any. Again, doing some web searches lists several, but for some reason none prominently listed from the Django site (from the pages that I visited).

I was also left with the impression that I could replace pieces of the framework I don’t like with something else, for example the templates. I don’t know how difficult this is in practice, or how many components are meant to be replaceable. But at least the idea is there, which makes someone with Pylons background breath a little easier.

On to coding my first Django app, then.

Minor Update to Caltroid

Since the Android Cupcake version has started rolling out to devices I went through my Android applications to see if any needed updating. While I was most concerned about UI glitches, there were none. However, Caltroid sources included use of the Google Maps API although it was not enabled in the Caltroid UI because it wasn’t fully ready yet. However, the maps API usage is different in Cupcake, and this prevented me from installing Caltroid on images running SDK 1.5 aka Cupcake. Rather than finishing the map activity, I decided to simply rip it out for now.

When I tried to upload the new version to Android Market I was greeted with the dreaded minSdkVersion error. The Android Market now requires you to specify the minimum SDK version in the manifest file. The trouble was I did include it. Luckily the workaround mentioned by many in the forums worked for me: just place the uses-sdk element as first child of manifest element:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="net.heikkitoivonen.android.caltroid"
      android:versionName="1.1.1" android:versionCode="1110">
 
    <uses-sdk android:minSdkVersion="1"></uses-sdk>
...

Simple Website Change Detection System

I happened to read a post on how to detect if someone has changed files on your webserver to serve nebulous scripts and what not. The idea in the post was to compute hashes of the files on your server and then compare periodically that the hashes match. This works against some simple attacks where all the attacker does is modify some of your content files. It won’t work if the attacker has also gotten access to the script doing the checks, or the hashes, and so forth.

As I was reading the post I realized that if you use a version control system like Subversion to publish changes to your site (the live site is a checked out copy), you get this automatically. All you need to do additionally is to set up a cronjob to run svn status (or equivalent if using some other version control system) on the server. svn status does not print anything if there are no changes, but for any added, deleted or changed files or directories it will print one line of output. Of course, this only works for files, not for content coming from databases.

8525 as USB Drive in Ubuntu

I have had an AT&T 8525 cell phone running Windows Mobile 6 for a couple of years now, and one of my remaining issues with it is that I can’t sync it with my Dell Latitude D820 running Ubuntu 8.04. Yesterday I took a picture of a cool license plate with the phone and wanted to put it on my blog, but didn’t feel like booting my other computer running Windows just to extract the photo. A few web searches later I am still no closer to syncing, but I was able to access the SD card via USB cable plugged into the phone, and copy the photo from the card to my hard drive.

If you try to plug in the 8525 via USB cable to Ubuntu, Ubuntu will see this as a new internet connection. There are applications you can install on the 8525 that when running, make the phone appear as storage. At first I tried WM5torage, but Ubuntu did not seem to recognize the phone as storage even then. I even managed to hung WM5torage so bad that I had to reboot the device. After that I read about someone having succeeded with Softick Card Export. I installed it, launched it, then plugged the USB cable in. Success!

Softick Card Export is not free, but it has a free evaluation period. I will probably not end up buying it since I am thinking about getting a new phone soonish.

P♥THON

A few weeks ago I noticed a car at a gas station just as I was pulling out that had one of the best license plate texts I have seen in a while. I wish I had had more time; I would have wanted to ask the driver if the plate really meant what I thought it meant.

Today I saw the same car, and had a bit more time to snap a picture. Unfortunately the driver was nowhere to be seen, so it will still remain somewhat of a mystery. However, given the text around the plate I am pretty sure that the owner of this cool plate likes the Python programming language:

California P♥THON License Plate

California P♥THON License Plate

HP USB Multimedia Keyboard

My Dell Latitude D820 has developed a second hardware problem: the ‘E’ key functions only sporadically, and one day I could not get it to work at all (it has improved a bit since then). The laptop is still under warranty so hopefully I’ll get that fixed.

In the meantime I really needed a backup keyboard, so I went to the nearest Fry’s and and grabbed the cheapest USB keboard that had an unopened box. It happened to be an HP 321AA USB Multimedia keyboard. I just plugged that in, and Ubuntu was happy. All the normal keys work as you would expect. I was surprised that even some of the extras work: Home button takes my browser to my home page, and the volume buttons work too. Sleep, page back and forth, favorite page and email button don’t seem to do anything. I also haven’t tried the play/pause, stop and track changing buttons. All the button presses are recognized, though (I verified with xev), and it seems like I can use System > Preferences > Keyboard Shortcuts to map the special keys to whatever I want (I just tested that I was able to map one key).

I was prepared to pay up to a $100 for an external keyboard to solve this “key-mergency”, so I was really happy when I walked out of the store with a $15 unit. Even though the keyboard feels pretty nice, I think I have gotten too used to laptop keyboards (I’ve used laptops pretty much exclusively since 2003). The full sized keyboard just feels too clunky. The optional wrist support can make it feel a bit more like a laptop, but unfortunately I had no room for it in my setup.