Snakes and Cats. Tab-completion in Python and iPython on Leopard

[UPDATE]: The latest builds of iPython have a fix for tab-completion built-in, so the patch mentioned below isn’t necessary.

Python users who are running Mac OS X 10.5, aka Leopard, will be pleased to find that Leopard ships with Python version 2.5.1, and comes with a host of wonderful things.  Especially in the PyObjC realm, something I’ll cover in another post.   Tiger had a rather lame build of Python 2.3 installed by default which had no readline support.
Readline is a gnu library which provides command-line editing, history, and tab-completion services, and it (or something like it) is pretty much essential for doing any real work in the python interpreter.   One of the first things I’d do when setting up a new Tiger system is to install the pythonmac packages from pythonmac.org, which were compiled with that readline support. 

On Leopard,  Python does have command-line editing, courtesy of “editline”, which performs a mostly identical service to readline.  However:  Tab completion in the python interpreter isn’t working.  (if you don’t know, tab-completion is a really handy feature where you type part of a command, hit ‘tab’, and the rest of the word you were trying to type is filled in. It saves you tons of typing and typing errors.  With something like Python, you can use it to help you remember method names in classes:

python
>>> import os

>>> os.<hit tab key here>
Display all 235 possibilities? (y or n)

‘y’ will get you a big ol’ list of all os’s methods and attributes.  It’s _really_ handy.   But it weren’t workin’!   What’s more, I often use iPython, and on Tiger somehow I got tab-completion for free (maybe because I’d built and installed readline?),  but not on Leopard.

Happily, there are user communities for this kind of thing, and Python user communities are active and usually very helpful.  No sooner was Leopard “out in the wild”, then folks on the pythonmac-SIG mailing list had a solution, which I will repeat here in my own weird convoluted way…
Here is the thread: http://mail.python.org/pipermail/pythonmac-sig/2007-October/019289.html

To get this to work with the python interpreter, you could simply add a line to a .pythonstartup file (and set your PYTHONSTARTUP environment variable). If you don’t already have a startup file, create one and set the PYTHONSTARTUP variable in your .profile or .bash_profile or whatever shell rc file you use.   I use bash, so I added the following to my .bash_profile file:

# Special startup .rc file for python
PYTHONSTARTUP=$HOME/.pythonstartup
export PYTHONSTARTUP

Since my PYTHONSTARTUP file is named “.pythonstartup”, I open that file and add:
import rlcompleter
import readline
readline.parse_and_bind("bind ^I rl_complete")

Then I quit and relaunch my terminal (or ‘source .bash_profile’) to pick up the PYTHONSTARTUP environment change, and we have tab-completion in Python’s interpreter. Yay!

But what about iPython? So one way is to patch your local copy of iPython, although I suspect it will be patched fairly soon anyway. If you use iPython on Leopard, check out the link above (pythonmac-SIG mailing list). One of the members of that list posted a patch — I hope he doesn’t mind if I attach it here…iPython patch to fix tab-completion

If you don’t like the idea of patching your iPython install, just add the above 3 code lines to your .ipython/ipy_user_conf.py file, but keep in mind this is only for Leopard.

All in all, Leopard is going to be great for Python coding. The bridge support features with PyObjC are sooo cooool. Most of the really useful frameworks on Mac OS X are “bridged” so you can import them and start using them.

6 Comments

  1. Harish Mallipeddi January 9, 2008

    I don’t know if it’s just me, but apart from tab-completion a lot of other things don’t work me either – auto-indent and up/down history lookup (pressing the Up key just results in garbage). Do you know of any fixes for this? I’m using IPython 0.8.2 and Python 2.5.1 which shipped with Leopard.

  2. michael January 9, 2008

    Yes, I have the same problem with History and auto-indent..drove me crazy the other day! For example when you’re trying to def a function in the interpreter. I’m suprised it hasn’t been fixed yet. Maybe it’s time to mention it on the ipython-dev list? The tab-completion stuff *was* fixed and rolled into iPython, so the above post is probably stale information.

    Thanks!
    -Michael

  3. RichardBronosky January 26, 2008

    @Harish Mallipeddi
    I too was going crazy over the up arrow history garbage. I did find that readline was the problem, but importing readline in python still results in the use of libedit in “readline compatible mode” because /usr/lib/libreadline.dylib is a symlink to /usr/lib/libedit.2.dylib

    The best solution I found is http://ipython.scipy.org/moin/InstallationOSXLeopard

  4. Liz August 26, 2008

    Thanks for the tip! It works great in 10.5 and zsh.

  5. taranaki October 20, 2008

    Great to have tab completion working in the Python interpreter, but one question: how do I indent now that tab is bound to rl_complete, other than pressing space four times?
    Thanks!

  6. michael October 23, 2008

    As I mentioned in the [UPDATE] line at the start of the post, the latest version of iPython fixes the tab-completion problem (at least to my knowledge). However, I have since installed GNU Readline and disabled the system’s links to “libedit.dylib” (e.g. “editline”, the BSD readline compatible lib), since it has some other annoying problems with python. Using “real” GNU Readline requires a different line in the python startup file:
    readline.parse_and_bind(“tab: complete”)

    Or you can just build your own python with readline built in. But that ‘s another story…

    @ taranaki
    As far as doing indents when tab is bound to rl_completer or whatever, I usually just do 2 spaces, unless I’m going to reuse the code I write in the interpreter in an actual program where python standard 4-space tabs are important.

    -Michael

Leave a Reply

Your email address will not be published. Required fields are marked *