Monday, October 17, 2005

Python: Deeply Nested try/finally Statements

"""This is a convenient way to deeply nest try/finally statements."""

__docformat__ = "restructuredtext"

# Created: Tue Oct 11 08:42:23 PDT 2005
# Author: Shannon -jj Behrens
# Email: jjinux@users.sourceforge.net
#
# Copyright (c) Shannon -jj Behrens. All rights reserved.

from traceback import print_exc


def tryFinally(tasks, handleFinallyException=None):

"""This is a convenient way to deeply nest try/finally statements.

It is appropriate for complicated resource initialization and destruction.
For instance, if you have a list of 50 things that need to get intialized
and later destructed via using try/finally (especially if you need to
create the list dynamically) this function is appropriate.

Given::

tasks = [
((f_enter_0, enter_0_args, enter_0_kargs),
(f_exit_0, exit_0_args, exit_0_kargs)),

((f_enter_1, enter_1_args, enter_1_kargs),
(f_exit_1, exit_1_args, exit_1_kargs)),

((f_enter_2, enter_2_args, enter_2_kargs),
(f_exit_2, exit_2_args, exit_2_kargs))
]

Execute::

f_enter_0(*enter_0_args, **enter_0_kargs)
try:

f_enter_1(*enter_1_args, **enter_1_kargs)
try:

f_enter_2(*enter_2_args, **enter_2_kargs)
try:

pass

finally:
try:
f_exit_2(*exit_2_args, **exit_2_kargs)
except Exception, e:
handleFinallyException(e)

finally:
try:
f_exit_1(*exit_1_args, **exit_1_kargs)
except Exception, e:
handleFinallyException(e)

finally:
try:
f_exit_0(*exit_0_args, **exit_0_kargs)
except Exception, e:
handleFinallyException(e)

tasks
See the example above. Note that you can leave out parts of the tuples
by passing shorter tuples. For instance, here are two examples::

# Second tuple missing.
((f_enter_2, enter_2_args, enter_2_kargs),)

# Leave out args or args and kargs.
((f_enter_2,),
(f_exit_2, exit_2_args))

Don't forget that a tuple of 1 item is written ``(item,)``. This is an
amazingly easy thing to do.

handleFinallyException(e)
This is a callback that gets called if an exception, ``e``, is raised
in a finally block. By default, traceback.print_exc is called.

"""

def defaultFinallyExceptionHandler(e):
print_exc()

def castTwoParts(first):
lenFirst = len(first)
default = ((), ())
max = len(default)
if lenFirst >gt; max:
raise ValueError("""tasks must be a list of tuples of the form (enterTuple, exitTuple).""", first)
return first + default[lenFirst:]

def doNothing(*args, **kargs):
pass

def castFunctionArgsKargs(fTuple):
lenFTuple = len(fTuple)
default = (doNothing, (), {})
max = len(default)
if lenFTuple >gt; max:
raise ValueError("""Each tuple in tasks is a pair of tuples that look like (f, args, kargs).""",
fTuple)
return fTuple + default[lenFTuple:]

if not len(tasks):
return
if not handleFinallyException:
handleFinallyException = defaultFinallyExceptionHandler

first, others = tasks[0], tasks[1:]
first = castTwoParts(first)
first = (castFunctionArgsKargs(first[0]),
castFunctionArgsKargs(first[1]))
((fEnter, fEnterArgs, fEnterKargs),
(fExit, fExitArgs, fExitKargs)) = first

fEnter(*fEnterArgs, **fEnterKargs)
try:
tryFinally(others, handleFinallyException)
finally:
try:
fExit(*fExitArgs, **fExitKargs)
except Exception, e:
handleFinallyException(e)


if __name__ == '__main__':

from cStringIO import StringIO

def printEverything(*args, **kargs): print >gt;>gt;buf, `args`, `kargs`
def refuseArgs(): print >gt;>gt;buf, "refused args"
def raiseValueError(): raise ValueError
def finallyExceptionHandler(e): print >gt;>gt;buf, "caught exception in finally"

tasks = [
((printEverything, ("enter_0_args",), {"in": "in"}),
(printEverything, ("exit_0_args",))),

((printEverything,),
(raiseValueError,)),

((refuseArgs,),)
]

result = """('enter_0_args',) {'in': 'in'}
() {}
refused args
caught exception in finally
('exit_0_args',) {}
"""

buf = StringIO()
tryFinally(tasks, finallyExceptionHandler)
assert buf.getvalue() == result

JavaScript: Quickies

Concerning MochiKit: It's well written. I like the Pythonic feel. I like the docs, the humor, and the heavy regression testing. I even like the code, which is a huge compliment!

Concerning DojoToolkit: I like the fact that it's a community of people who have each given up their own framework to work together. I like the mailing list. I like the event system and the package system (although I haven't used it yet). I don't like the fact that it doesn't feel quite as polished by a perfectionist as MochiKit. I also hate the part of the style guide that says you should not use a space before "{" in:
if (foo){
}
I don't know of any other style guide that suggests this.

Does this mean I'm going to pick one over the other? Nope. Both have good parts. Fortunately, they're compatible. It looks like I'm going to have to use them both. Ideally, the guys from MochiKit would take a bunch of their stuff and shove it into DojoToolkit. Then the guys from DojoToolkit would change their style guide. (Yes, I readily admit I'm a freak. No, my psychologist doesn't think there's anything he can do for me. ;)

You may wonder why I didn't mention Prototype. I've heard that it has no documentation and that it doesn't play nicely with other JavaScript libraries. I'm sure that it's very nice and that it has a lot of cool features, but these are things that I feel are important.

Also, I just read "DHTML Utopia: Modern Web Design Using JavaScript & DOM". I'm really pleased to find a modern JavaScript book. It was short, yet I got a lot out of it. On the other hand, there were many errors. I think the editing left something to be desired. Furthermore, it reinforced my belief that the intersection of good JavaScript programmers and really good software engineers is really small. There were many code snippets where too much code was duplicated instead of put into some utility function. I wish they had a technical editor who suffered from chronic analness like I do. Nonetheless, it was a pretty good book, and I thank the author for writing it.

As a last note, why have I made it through two DHTML books yet never had the prototype system explained as well as this paper explains it?

Friday, October 14, 2005

AJAX: Humor

Have you ever noticed that some of your best work happens in the bathroom?

The other day I was trying to resolve a particularly sticky user interface problem. I thought I'd try out some AJAX, Asynchronous JavaScript and XML. It wasn't really working out, and although they really aren't the same thing, I tried some CLOROX, Common Language Object Reference Over XML. Displeased with that, I fell back to COMET, Common Object Method External Transport. Next I thought I'd try some old fashioned BLEACH, Binary Language Exports And C Headers; however I made sure to remove all the COMET first because I've heard that mixing COMET and BLEACH can have disastrous side effects. I think I was most satisfied with CLOROX, especially thanks to its BLEACH heritage. I found that all of these options were better than SOAP, Simple Object Access Protocol, which leaves a sticky substance behind that is nearly impossible to get rid of.