Compiling Python 3.2 with readline support on MacOS X 10.7

This post explains how to compile Python v3.2 including support for the GNU Readline Library on MacOS X 10.7 (Lion), not using tools like MacPorts. One of the problems we try to solve is making history work in the interactive Python interpreter.

Pre-requirement is to have Apple’s XCode installed (check the Appstore).

First, you need a fresh copy of the GNU Readline Library and compile it. At the time of writing, readline v6.2 was the latest. Fire up a Terminal and do the following:

shell> tar xzf readline-6.2.tar.gz
shell> cd readline-6.2
shell> MACOSX_DEPLOYMENT_TARGET=10.7 ARCHFLAGS="-arch x86_64" \
       ./configure --prefix=/opt/local
shell> make && sudo make install

Note that you can change the location /opt/local to anything you like, but avoid /usr/lib or other system location.

When readline compiled and installed successfully, compile Python v3.2 as follows:

shell> tar xzf Python-3.2.3.tgz
shell> cd Python-3.2.3
shell> LDFLAGS="-L/opt/local/lib" CFLAGS="-I/opt/local/include" \
       ./configure --prefix=/opt/python/3.2.3
shell> make && sudo make install

Note that you might have more arguments to pass to the ./configure if you have special needs. Note also that /opt/python/3.2.3 is where Python will be installed to avoid clashing with the system provided Python installations.

You should now have history support in the Python interpreter:

shell> /opt/python/3.2.3/bin/python3
>>> import this
>>>

Bootstrapping & Running MySQL server standalone on Windows

Two extra tips when you try to (manually) bootstrap MySQL on Windows from the command line:

  1. When bootstrapping, use --no-defaults or --defaults-file.
  2. Use --standalone when starting the MySQL server.

The first point really bugged me yesterday. I’m used to installing MySQL manually and having no option files available where MySQL would read them by default.

On Windows, however, I used the MySQL installer. So, when I launch unit testing for Connector/Python it bugged me saying log files of InnoDB didn’t match the configuration. This is indeed a newbie error..

Accepting both short and descriptive URLs with WordPress

I was asked whether it was possible to use more descriptive URLs for my blog posts instead of using the post ID only. WordPress permalinks only allow to have one structure active, but that doesn’t mean you can’t change the webserver (lighttpd in my case) to do some redirections.

Until an hour ago, my blog accepted only the following kind of url:


http://example.com/post/871

This was, in my opinion, easier to use since shorter. However, it is not very descriptive. So, we would like to have the following URLs:

    (1) http://example.com/more-descriptive-urls
    (2) http://example.com/post/871

In WordPress v3.3 (and also earlier version), you go to “Settings > Permalinks” and change the “Common Settings” to a custom structure like this:

    Custom Structure: /%postname%/

This makes more descriptive URLs (1) work, but it breaks our existing shorter URLs (2).

Using lighttpd, we have to change the WordPress rules so we are redirecting URLs with a post ID, to the descriptive URLs.

url.rewrite-once += (
    # more rules..
    "^" + wpdir + "post/(\d+)/?$" => wpdir + "index.php/?p=$1",
    "^" + wpdir + "(.+)/?$" => wpdir + "index.php/$1"
)

The above redirects http://example.com/post/871 to /index.php/?p=871.

Restart lighttpd and we’re done. Now both the longer, more descriptive URLs will be default, and the old URLs using only the post ID, will redirect to the new location.

Invalid dates returning None, or raise error using Connector/Python?

In this blog we discuss invalid dates in MySQL, how to retrieve them using Connector/Python and we raise the question: Should Connector/Python raise an error or just keep returning None on invalid dates?

If you run MySQL without proper SQL Modes, you will be able to update and
read invalid dates such as ’2012-06-00′. If you’ve payed attention the past decade, you’ll know that you can prevent this configuring your MySQL server setting SQL Mode to ‘TRADITIONAL’.

Now, the problem if this is allowed, how do we get invalid dates using MySQL Connector/Python?

Lets look at an example inserting an invalid date and trying to read it again using MySQL Connector/Python:

>>> cur = cnx.cursor()
>>> cur.execute("INSERT INTO t1 VALUES ('2012-06-00')")
>>> cnx.commit()
mysql> SELECT * FROM t1;
+------------+
| date       |
+------------+
| 2012-06-00 |
+------------+
>>> cur.execute("SELECT * FROM t1")
>>> cur.fetchall()
[(None,)]

The date ’2012-06-00′ is converted by Connector/Python to Python’s None. This is because datetime.date does not allow invalid dates.

How to get the invalid dates back in your application?

You can use the raw-option for cursors and Connector/Python will return the date as a string instead of trying to convert to datetime.date.

>>> cur = cnx.cursor(raw=True)
>>> cur.execute("SELECT * FROM t1")
>>> cur.fetchall()
[('2012-06-00',)]

You are then responsible of parsing the text and do something usefull with it.

Question: what should Connector/Python do when it can’t convert the invalid dates? Returning a None is actually not really correct because if you would allow NULL in the MySQL table, you would also get None.

Should an invalid DATE value raise an error instead of returning None? Personally, I consider it a bug and I think it indeed should raise an error.