August 2004 archive

Book and Game Reviews

Book: The Curious Incident of the Dog in the Night-Time

A week ago, Joel Spolsky wrote some comments regarding a book called The Curious Incident of the Dog in the Night-Time, written by Mark Haddon. I added the book to an order I was placing at Amazon, and Thursday afternoon it arrived at my workplace.

The story is written from the point of view of Christopher Boone, fifteen year old boy who suffers from Asperger’s Syndrome. Young Christopher finds a poodle killed, and sets out to solve the mystery of who killed the Wellington.

This book is very definately going to hold a place near the top of my most favourite novels. It is quite simply an amazing novel.

The use of the first-person perspective pulls you into this novel, and engages you completely. When reading this book, you it truely feels honest and real. The author writes as if the main character is writing this book – as if it’s a novel he wrote during his efforts to solve the mystery. It is an amazingly strong narrative technique. If the author’s name on the cover and the character’s name in the book matched up, a reader would never believe this to be a work of fiction.

I recommend that everyone read this book, especially you geeky types. You’ll probably giggle through the first few chapters, as I did, but it won’t take long before you realize how serious things are.

Game: Tales of Symphonia

Tales of Symphonia is a role-playing game for the GameCube system. It is published by Namco. It is sure to be available at any of your favourite video game stores.

Colette is the Chosen of Regeneration, fated to regenerate the world and save everyone’s existence. Her party, including the inexperienced swordsman (Lloyd, your main character), a young magician (Genis), your school-teacher (Raine) and a mercenary (Kratos) set out to regenerate the world, each for their own reasons. All that stands in their way is an army of half-elfs, a world where humans are harvested in ranches, and just about everything else you can imagine.

This game is basically amazing. It has wonderful elements of some of the best fantasy games ever, such as FF6 and FF7. The story is a beautiful twisting saga. The graphics are beautiful, cell-shaded, and very similar to Wind Waker’s. The voice acting is the best I’ve ever heard in a video game, as it actually adds to the game’s dialogue rather than making my ears cringe. And finally, the characters are deep (for a video game), and subtle (for a video game).

I recommend this game strongly for anyone who has ever liked Final Fantasy games, and who owns a GameCube. Actually, you know what… buy a GameCube for this. It’s worthwhile and relatively cheap anyways.

Roundup

Roundup is some damn beautiful software. It’s a very nice and simple package for software bug tracking (oh, pardon me… issue tracking). It can be customized very easily, and in fact from a minimal ‘tracker’ just about any web-based database application could be built with a minimum of fuss. The mail gateway is a beautiful design too. Oh, and I love the fact that e-mailing the system creates a user “account” for that e-mail address (unless it’s associated with an existing account, of course). No fuss bug tracking.

I’d love if it supported some e-mail security, though. Digitally signed messages, for example. The current complete lack of e-mail security makes me irrationally scared – a bad person couldn’t do much, but they could do some.

Here’s a neat trick – for nice clean URLs, place the roundup.cgi script wherever you want it to be, renamed it to just roundup, and add a couple lines to your Apache configuration:

<Location /blah/roundup>
    SetHandler cgi-script
</Location>

And you’ll magically get the CGI interface of roundup working without the minor annoyance of having ’roundup.cgi’ in your URLs. Go Apache!

DevEnv vs. the Programmer

How can you capture the console output of a program, when it buffers that output if you’re not using a console to view it? This was a problem run into when building an automation tool for MS Visual Studio .NET. In the end, the programmer subjugated his tool (as it should be) by beating it over the head with a pipe.

A few of us programmers with in the unfortunately unfriendly environment of MS Windows. It might look pretty and have lots of applications written for it, but it’s basically an unfriendly environment for a software developer. Even MS Visual Studio .NET can be unfriendly to a developer, which is unfortunate since it’s the one program you’d expect would be really friendly.

Visual Studio allows you to provide command-line options which start a software build. Running inside a command prompt, all you need to do is pass a solution file and a build configuration to the program, and you’re off. In fact, Visual Studio even gives you more command-line flexibility by providing two executables, devenv.com and devenv.exe – the former will tend towards printing console output all the time, while the latter will avoid it if a build log file is provided instead.

In the creation of a complete build tool, I wanted to run devenv.com and capture the output so I could display the progress to a user. That’s when it became tough. Running the executable through os.popen (or any other popen function) didn’t accomplish what I wanted – the output being printed to the console (and now being read through a pipe) was buffered inside the devenv process and only printed after the build was completed. Clearly this didn’t accomplish the goal of providing a progress display for the user.

devenv.com provides an option which I thought might have some promise: /out. This writes the build output to a specified file. Great! All I need to do is start it writing to a file, and read through the file at the same time. I wasn’t sure of the implementation details, but it seemed feasible. Unfortunately, the devenv process locks the output file exclusively. Python’s open() was unable to read it, and even trying to find obscure parameters to win32file‘s functions failed to give me the necessary access to the file.

In the UNIX world, the solution would be obvious. Create a pipe, and write the build output into the pipe while reading the pipe. In the Windows world though, a pipe is not a filesystem object. It can’t be created in a specific location, and so devenv wouldn’t be able to open it like a normal file and write to it. I considered for a while that there are a bunch of standard reserved file names, like CON and PRN. Might one of them help me? Could one of them be used to connect to a pipe? Well, no. Not really. They’re ancient history, a relic from years gone past, and they don’t have any concept of a pipe.

I started digging around for more information about named pipes, which seemed to be the prefered mechanism for IPC in Windows software. Could a named pipe be referenced through a file location? Yes, it can! \\%(host)s\pipe\%(name)s refers to the named pipe name on the host host. And as a bonus, the host . refers to the local machine at all times. Now I finally have a plan of action: Create a named pipe, make devenv write to \\.\pipe\buildOutput, and read the output on the fly.

In the end, I wrapped the named pipe code into module, NamedPipe, and the code to read devenv output on the fly was easy:


from NamedPipe import AnonymousNamedPipeReader

pipe = AnonymousNamedPipeReader()

# Application command line...
# (build application cmd line, devenv.com x.sln /build Release, etc..
# {code omitted}
cmd = cmd + r' /out \\.\pipe\%s' % pipe.name

# Okay, one of us needs to loop and accept a pipe connection, read
# data, display it to the user, and so on.
# The other of us needs to run the build command.
class ExecThread(threading.Thread):
    def __init__(self, cmdLine):
        threading.Thread.__init__(self)
        self.cmdLine = cmdLine
    def run(self):
        self.retval = os.system(self.cmdLine)
thread = ExecThread(cmd)
thread.start()

buildLog = ""
line = ""

for data in pipe:
    buildLog += data
    # {code omitted - display output on the fly}

Now, obviously this code snippet has left out all the magic. It’s a bit long and boring, so I thought maybe you’d just like a link to NamedPipe.py instead. Through the magic of functions like CreateNamedPipe and ConnectNamedPipe, you can read data being written to a file on the fly. It even works when the writer is a jerk, locking the file.

Vancouver Python Workshop 2004

I just returned to Calgary from the Vancouver Python Workshop. Cecil and I drove out there last week (Thursday evening/Friday morning). Catsy flew out from Toronto. We all stayed at the Hyatt Regency in downtown Vancouver, where much fun was had watching the Back to The Future trilogy, and making up entertaining stories about elves.

The workshop was reasonably well organized, had a nice venue, and was well attended. The talks varied in quality from okay to excellent – all the speakers were well informed folk with interesting topics, but very few programmers are excellent public speakers. That being said, I have a few specific suggestions for the workshop itself:

  • Some talks could have benefited from the presence of a strict moderator. On a scale from polite to rude, the following things happened:

    • A speaker deferring a question to Guido. This is appropriate, as it is the prerogative of the speaker to defer during his own presentation, and Guido may be an excellent resource for an answer.
    • Guido interjecting a comment like "It’s not happening." while an attendee asks a question (referencing a PEP) is more questionable, but ultimately "polite enough" in the company of geeks.
    • Getting into an audience debate about wxWidgets during a PyObjC talk is not very polite.
    • Nitpicking the usefulness of a contrived optimization example is rude, pointless, and time consuming.
  • An entire track on the second day ended up being dedicated to Plone. I think Plone is cool, but these talks unfortunately ended up being about Plone from the point of view of a user rather than a Python developer. I believe that the workshop did not have quite as many speaker submissions as they wanted, so these Plone talks weighed in based upon how many people were willing to do them. They were good, but badly targeted and abundant.

    I would suggest that the conference organizers be willing to say "no" to speakers if they have an abundance of talks on one such subject. I realize getting submissions for talks must be a difficult process, and the fear of having not enough content at a conference must be pretty big as an organizer.

I enjoyed the workshop greatly. I should have flown out rather than drive 12 hours, but it seemed like a good idea at the time. I picked up a lot of good ideas, started in writing some interesting PyObjC code (a game of interracial life, oooh), enjoyed using SubEthaEdit in public for the first time, and ate a lot of good food. Catsy seems to have had her own kind of fun, too.