About matt

My name is Matt Wilson and I live in Cleveland Heights, Ohio. I love random emails from strangers, so get in touch! [email protected].

Frustration with postfix and sending email to a script

I want to set up an email address that executes a script with every incoming email, so in my /etc/aliases, I did this:

runscript: |/usr/local/bin/email_reading_script.py

Then I rebuilt the postfix alias db with sudo postalias /etc/aliases, and then sent an email to runscript@localhost. That’s when the fun began. The script is run by nobody/nogroup, so it couldn’t log to my logging directory, because I require people to be in the adm unix group.

Then I created a user named runscript, and moved that | /usr/local/bin/email_reading_script.py line into a .forward file. I added adm to runscript’s unix groups.

AND STILL NO JOY.

I don’t know why, but when the script runs, the shell only seems to get the primary group. So, I kept getting permission-denied errors. I finally got stuff to work when I set adm to be the primary group for my runscript user. Now everything is OK.

This ate up the better part of the @#$@#$ing day. Grr.

If this didn’t work, I was going to install procmail and go down that route.

Am using ubuntu hardy heron.

My proposed talk for PyOhio

Here’s what I submitted for a presentation topic for PyOhio:

TITLE: Decorators are fun

EXPERTISE LEVEL: Hopefully, there will be something for everyone. Novices might enjoy the material at the beginning mostly, while experts would likely be more interested in the ruledispatch discussion.

SUMMARY: This talk will start with a friendly walkthrough of decorators for people that have never seen them, then go into some straightforward examples, then finish with a review of how decorators are used in Philip Eby’s ruledispatch package.

OUTLINE:

  • The simplest possible decorator.
  • Pass arguments to a decorator.
  • Write a decorator and still preserve the function signature of the decorated function.
  • Coerce values into a function into types using decorators.
  • Log values coming out of a function.
  • Phillip Eby’s ruledispatch package implements generic functions, aka multimethods, for python. I’ll walk through how he uses decorators, and why they’re such a good idea for this.

Texas techno-ants

Completely unrelated: this set of photos on flickr is really neat. Fashion students at Virginia Commonwealth University were given an assignment to design an abaya. Heard about it on The World on PRI.

Now to the main point. This is why you don’t mess with Texas. We already have fire ants, which can literally breathe fire. And now, we have ants that will eat your iPod while you watch. From the article:

Worse, they, like some other species of ants, are attracted to electrical equipment, for reasons that are not well understood by scientists.

They have ruined pumps at sewage pumping stations, fouled computers and at least one homeowner’s gas meter, and caused fire alarms to malfunction. They have been spotted at NASA’s Johnson Space Center and close to Hobby Airport, though they haven’t caused any major problems there yet.

They’re clearly saving NASA for some darker purpose.

Exterminators say calls from frustrated homeowners and businesses are increasing because the ants — which are starting to emerge by the billions with the onset of the warm, humid season — appear to be resistant to over-the-counter ant killers.

“The population built up so high that typical ant controls simply did no good,” said Jason Meyers, an A&M doctoral student who is writing his dissertation on the one-eighth-inch-long ant.

It’s not enough just to kill the queen. Experts say each colony has multiple queens that have to be taken out.

Hell yeah. I’m rooting for the ants. Let this insectocalypse begin!

The difference between syntactic analysis and code generation

I can parse the text for the paragraph below very quickly. The author uses simple grammar. However, it is taking me hours of study (following footnotes) to make any sense out of it:

The bin_rec function is an example of a hylomorphism (see citeseer.ist.psu.edu/meijer91functional.html)—the composition of an anamorphism (an unfolding function) and a catamorphism (a folding function). Hylomorphisms are interesting because they can be used to eliminate the construction of intermediate data structures (citeseer.ist.psu.edu/launchbury95warm.html).

From the article Cat: A Functional Stack-Based Little Language in the April issue of DDJ.

This experience matches how I imagine programming-language interpreters and compilers work. In the first pass, the interpreter reads in all the text and breaks it down grammatically, mapping chunks of text into nodes that have labels like “IDENTIFIER” or “FUNCTION DEFINITION” or whatever.

Then in the second pass, the system walks through the nodes and gets down to the business of writing out the ones and zeros that tell the little men inside my computer what to do.

I haven’t studied compilers formally (hey, my degree is in economics!) so please let me know how far off base I am. I’m aware that in reality, the first and second passes may not be separate from each other or can be interleaved.

How to use tg-admin sql upgrade

The tg-admin script that is bundled with turbogears is really helpful, but I had a hard time learning how to use it.

Before you read any more, you should know that this only works when you use SQLObject, not SQLAlchemy, for your ORM.

These are my notes on how I use tg-admin to upgrade an existing database.

  • I have a production database that uses prod.cfg;
  • I have a development database that uses dev.cfg;
  • Neither databases have a sqlobject_db_version table initially, because I never payed attention to it yet.

The development database has a bunch of new columns, tables, and indexes that I want to add to the production database. For this example, I’ll pretend that all I want to do is add an index to a table.

First, I made sure that the dev database matches sqlobject classes:

tg-admin -c dev.cfg sql status

If those are out of sync, then do whatever you need to do to make sure your actual dev database matches your classes. Of course, tg-admin sql status is not perfect. For example, it overlooks missing indexes and constraints, at least with postgres.

Next, I recorded the state of the development database:

tg-admin -c dev.cfg sql record --force-db-version=2008-03-21

This will make a new table in the dev database called sqlobject_db_version. I am forcing it to have a value of today’s date (March 21st, 2008).

Now I connect to the production database and set a version on it with yesterday’s date:

tg-admin -c prod.cfg sql record --force-db-version=2008-03-20

Now I run this to try to upgrade the production database to match the development database:

tg-admin -c prod.cfg sql upgrade

Of course, that should fail, and I see some error message sort of like this:

$ tg-admin -c prod.cfg sql upgrade
Using database URI postgres://staffknex:staffknex@localhost/staffknex320
No way to upgrade from 2008-03-20 to 2008-03-21
(you need a 2008-03-20/upgrade_postgres_2008-03-21.sql script)

This is an example of a helpful error message. I need to write a script that will explain how to upgrade from yesterday’s version to today’s version.

That script will be really simple:

BEGIN;
CREATE UNIQUE INDEX majestic12 ON ufo_theorists (first_name, last_name);
END;

I suggest using BEGIN and END so that in case something goes wrong in the middle, your transaction will be rolled back automatically.

Now I can run this:

tg-admin -c prod.cfg sql upgrade

And my production database will be upgraded with the new index.

Now for some complaints:

  • Why isn’t this advertised better? This is a really nice feature.
  • You’re supposed to be able to specify the URI on the command-line with the –connection option, but I could never get it to work.
  • I really wish that tg-admin sql status detected stuff like missing indexes and constraints. I use these things heavily.
  • It would be nice to be able to mix python into the upgrade script, rather than just SQL. For example, I recently dropped a column that had both an employee’s first and last name, and separated this into two columns. I used SQL to make the new columns, then I used python to read data out of the old single column and write it to the two new columns. Then I used SQL again to drop the old column.

Like I said at the beginning, this is a really helpful script and I’m very grateful to whoever wrote it.