For the past eight days or so, I've been having the absolute pleasure of working on a pure research project, re-implementing FireWatir in Python. The project is known internally as "Whiskey," (FireWatir without the R) and at some 1805 lines is faster and more concise than firewatir's 6522 lines.

The real trick was to stop sending huge masses of javascript back and forth with every operation, but instead to encapsulate all of the javascript FireWatir generates and transmits per transaction into a javascript library, upload that once, and then just issue one-line calls to the JSVM through the library. This skips a very expensive interpretation step and allows context identity to be maintained more explicitly.

Also, on the client (python) side, finding objects became a matter of doing things like:


You'll note that I've seriously overloaded the dot operator (.); in some contexts, it means "get child object of", and in other it means "get attribute of", and in yet a third it means "dereference function attribute of and call function." Yet as you can see from the example, that's not tragically confusing. (And yes, "type" is misspelled "typ", to avoid conflicting with the python keyword type.)

Oh, a fun inner implementation issue: doc.input(name="username").style.background.set("#ffffff"). Here, "Style" has to dereference not to a function, but to value that's not scalable-- it's a reference to a DOM Style object, so I needed an inner class to be instantiated, that knew what object was being manipulated, in order to manipulate it.

And finally, there are alternatives: doc['input[name=username]'].set("user") will do the same as the first line of the first example. And doc[4] will return a handle to the fourth child element (not node!) of the root document object. This can be really useful when doing things like: doc.table("#accounting")[4][4], although to be honest that has a special case handler to skip table headers and go straight for the body.

But what I learned while writing this is that I really do code very much like I write. I wrote a ton of crap, and then when I started to get serious about what I was trying to accomplish, when I started documenting my code, huge amounts of code simply got thrown away. The most common through was "I never did need that." "I never used that." "I haven't implemented that well, let's take it out and see if we need it later."

I also seem to thrive in an Extreme Programming environment. I've known for a long time that I do that well, and this was no exception; the best development periods were when I had my UI partner looking over my shoulder and the two of us leapfrogged each other's thinking patterns to home in on exactly what was needed.

For example, the doc[4] started life as a specialized override of getitem(), with just a numeric handler for Table and TR objects. He suggseted I push it up into the base Element handler and use it everywhere, and make the Table handler a special case if the Table had a Tbody (oh, and push that logic into the Javascript library to avoid round-tripping the conditional), and I immediately saw the utility of putting a type conditional in getitem so that if you passed it a string you could treat it like a CSS selector.

Anyway, I've been having more fun than a programmer should be allowed to have.