Archive for Python

Exporting Delicious Library to the web

I’ve been using Delicious Library for a while now and have been incredibly happy with the results. I even managed to figure out which books I had on loan and more importantly discovered I was missing some books from my collection!

The other thing I’d been playing with was including some books on this site that I like. You may have noticed them down the side. There is a bit of PHP code behind the pictures, but I still need to add in the Amazon id number for each book.

My aim is to use Delicious Library to keep track of my physical media, including rating it, and to publish the highest rated media onto the site. Given that Library is basically a thick client built on top of Amazon, I could even include my referrer link, so if anyone buys anything I get a small commission to feed my book buying habits.

Library supports exporting its catalog as a tab separated file. I had hoped for an ‘Export to XML’ option, so it would be simple XSL transform and tada!

Given the Python focus of this site, it didn’t take long before I had a workable script up and running.

The important bits of the script are included below:


from Kid import *
import sys

def normalizeString(str):
    return str.replace('//', '/').replace('/ ', '<br/>').replace('*','<br/>*')

file = open(sys.argv[1], 'rb')
for line in file:
    lines.append(line[:-1])

headings = lines[0].split('t')

books = [dict(zip(headings, normalizeString(line).split('t'))) for line in lines[1:]]

Template(file='template.kid', books=books).serialize()

The Template object is from the Kid template library, which is responsible for generating the resultant XHTML. The template.kid file that I used iterates through the list of dictionaries of books and displays as links the ones that I’ve given a rating of (5/5).


<?xml version='1.0' encoding='utf-8'?>
<html xmlns='http://www.w3.org/1999/xhtml' xmlns:py='http://purl.org/kid/ns#'>
  <head><title>Delicious Library</title></head>
  <body>
    <ul>
      <li py:for='book in books' py:if="book['rating'] == '5'">
        <a py:attrs="href='http://www.amazon.com/exec/obidos/ASIN/' + book['asin'] + '/pseudofish-20?creative=327641&camp=14573&link_code=as1'">
        ${book['title']}
        </a>
      </li>
    </ul>
  </body>
</html>

The end result, is that I can now add books into Library as I purchase and read them, and if I rate the book highly enough then it will turn up on this blog.

Source code and samples are available here. Requires Delicious Library (full or demo) and Kid.

Pimp My Code, Part 5: In Python

Wil Shipley continues his Pimp My Code series with an article reviewing what should have been a very simple method to return a path inside the Application Support folder.

Well worth a read, both for the stylistic as well as the comedic commentary.

From my perspective, it is also a useful source of learning about Cocoa from one of the better programmers.

In Python, the final example looks something like:


from Foundation import *

def applicationSupportFolder():
    return NSSearchPathForDirectoriesInDomains(
        NSApplicationSupportDirectory, NSUserDomainMask, True
    )[0].stringByAppendingPathComponent_(
        NSProcessInfo.processInfo().processName())

Note: The code has been reformatted to (attempt to) fit your screen.

Saving a file using NSSavePanel

Saving a file was something I’d been avoiding for a while, as I hadn’t been able to find the right control in Interface Builder to make it happen. This had led me to believe it was going to be difficult and was delayed for a long time.

Today, I bit the bullet and spent some time to figure this out. My suspicion was that there existed a control that would do the work for me, as file handling is quite consistent from a UI perspective in Mac OS X. Reading through Cocoa Programming didn’t provide any enlightenment, so I went back to the XCode documentation.

By this stage of my Cocoa learning, I really should have known better. Apple’s documentation has solved too many problems for me to be consulting it as a last resort. Unfortunately, I suspect it is a lesson I will have to keep learning.

Apple provides this information about the NSSavePanel class. Finding this class was my ‘aha!’ moment for the day. No wonder I couldn’t find it in Interface Builder, it isn’t an IB control in the normal sense.

In Python, the simple version looks something like:


from AppKit import *

def saveFile_(self):
    sp = NSSavePanel.savePanel()
    sp.setRequiredFileType_('ics')

    if sp.runModal() < = 0:
        return

    print 'Filename: ' + sp.filename()

This will throw a standard file save modal dialog box and ask for a filename to save. There are a bunch more options on the NSSavePanel class, which I may explore later. The interesting part will be making the save panel appear in a sheet.

Something to explore later.

Re-opening the main NSWindow

I was faced with what seemed a very simple problem, when I closed the window on my application, I didn’t have a way to open it again. For a document based application, it isn’t too much of an issue, the framework allows you to open or create a new document.

Mac OS X is a bit divided at the moment on this functionality. There are some single window apps that behave this way, and others that close themselves when you close the main window. System Preferences is an example of this.

For my application, I wanted it to have a single main window, and I wanted the user to be able to click on the dock icon and have it re-open if it wasn’t already there. Same as Mail, Address Book, iTunes and others.

The trick to making this happen is the applicationShouldHandleReopen:hasVisibleWindows: method of your application delegate. This method is called with the NSApplication and a flag to indicate whether or not any windows are visible for the application.


def applicationShouldHandleReopen_hasVisibleWindows_(self, theApp, hasVisibleWindows):
    if hasVisibleWindows:
        return True

    for win in theApp.windows():
        # Autosave Name set in .nib
        if win.frameAutosaveName() == 'mainWindow':
            win.makeKeyAndOrderFront_(NSNormalWindowLevel)
            return False

    return True

To be honest, my first version was a bit simpler again, the for loop looked remarkably like:


    win = theApp.windows()[0]

Too many years programming and I couldn’t leave the [0] alone. Given that there could be more than one window in my application, I needed a way to identify the window that I needed to open. Cocoa provides such a feature, the AutoSave name for a window. This property can be set in Interface Builder.

Simply give your main window a name, I chose ‘mainWindow’, and search for a window with that name.

Once you have a handle on the NSWindow, you need to call makeKeyAndOrderFront:. This method makes the window the Key window, which gives it keyboard focus and makes it visible. The method requires a window level and given that the main window isn’t doing anything strange, I used NSNormalWindowLevel.

The test for visible windows is a bit of a shortcut. If there is already a visible window, I don’t want any extra ones showing up, so I return True and let Cocoa deal with the Dock click (or Application open) as it normally would. If I did open a window, then I return False, as there is nothing further for Cocoa to do.

In the end, a simple solution to a simple problem.

Crossroads on Languages

Recently, I’ve been distracted by reading Paul Graham’s essays as a result of a Tim Bray posting.

My interests have been serious piqued as a result of one of his themes of using Lisp to write web applications. As a higher order language, the theory is that programmers will be more productive and that given the types of programmers who learn Lisp, you can attract better programmers.

It is a very interesting argument. Something that I’ve been giving lots of thought. My interests at the moment are in learning to write native Mac OS X applications. Python fell in my lap as an option mostly due to my background in Miranda and then the more popular (and powerful, useful, free) Haskell.

Part of my motivation behind learning Cocoa programming has been to write a native application that talks to a web based back end. For some tasks, I’m still not convinced that a web browser is the Right Thing, regardless of how much AJAX code you put in place. This is why the Cocoa apps I’ve been writing have typically avoided building their own data layer. One is built on regular expressions and the other on Address Book and iCal.

The bit I’ve been avoiding is writing the back end. Past experiences on this have been in Perl, which is useful, but I just don’t like. I’d rather not have to put $ signs everywhere.

Python seems to have the clean aspect and enough libraries for doing things so I’d been assuming that I’d use Python for the back end too. However, most of my thinking in Python is really derived from my Haskell days, so why not write the back end in Haskell?

I also may have been distracted somewhat by a few other developments such as Ruby on Rails and Django, as even with a thick client in Cocoa talking to a back end, in this day and age, an application really should have a web based version too.

Investigation has also gone into using XUL as it is both web based, cross platform and somewhat richer than AJAX.

All in all, it is a happy time to be in where there is such a wide range of equally valid choices. It now comes down to a question of tradeoffs.