[Web-SIG] a convenient way to deeply nest try/finally statements
Shannon -jj Behrens
jjinux at gmail.com
Tue Oct 11 19:01:33 CEST 2005
I'm posting this in the hope someone else will find it useful. If you
want it, consider it in the public domain.
"""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 at users.sourceforge.net
#
# Copyright (c) Shannon -jj Behrens. All rights reserved.
def tryFinally(lst):
"""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::
lst = [
((f_enter_0, f_enter_0_args, f_enter_0_kargs),
(f_exit_0, f_exit_0_args, f_exit_0_kargs)),
((f_enter_1, f_enter_1_args, f_enter_1_kargs),
(f_exit_1, f_exit_1_args, f_exit_1_kargs)),
((f_enter_2, f_enter_2_args, f_enter_2_kargs),
(f_exit_2, f_exit_2_args, f_exit_2_kargs))
]
Execute::
f_enter_0(*f_enter_0_args, **f_enter_0_kargs)
try:
f_enter_1(*f_enter_1_args, **f_enter_1_kargs)
try:
f_enter_2(*f_enter_2_args, **f_enter_2_kargs)
try:
pass
finally:
f_exit_2(*f_exit_2_args, **f_exit_2_kargs)
finally:
f_exit_1(*f_exit_1_args, **f_exit_1_kargs)
finally:
f_exit_0(*f_exit_0_args, **f_exit_0_kargs)
lst
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, f_enter_2_args, f_enter_2_kargs),)
# Leave out args or args and kargs.
((f_enter_2,),
(f_exit_2, f_exit_2_args))
"""
def castTwoParts(first):
lenFirst = len(first)
default = ((), ())
max = len(default)
if lenFirst > max:
raise ValueError("""\
The lst 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 > max:
raise ValueError("""\
Each tuple in the lst is a pair of tuples that look like (f, args, kargs).""",
fTuple)
return fTuple + default[lenFTuple:]
if not len(lst):
return
first, others = lst[0], lst[1:]
first = castTwoParts(first)
first = (castFunctionArgsKargs(first[0]),
castFunctionArgsKargs(first[1]))
((fEnter, fEnterArgs, fEnterKargs),
(fExit, fExitArgs, fExitKargs)) = first
fEnter(*fEnterArgs, **fEnterKargs)
try:
tryFinally(others)
finally:
fExit(*fExitArgs, **fExitKargs)
if __name__ == '__main__':
from cStringIO import StringIO
def printEverything(*args, **kargs): print >>buf, `args`, `kargs`
def refuseArgs(): print >>buf, "refused args"
lst = [
((printEverything, ("f_enter_0_args",), {"in": "in"}),
(printEverything, ("f_exit_0_args",))),
((printEverything,),
()),
((refuseArgs,),)
]
result = """\
('f_enter_0_args',) {'in': 'in'}
() {}
refused args
('f_exit_0_args',) {}
"""
buf = StringIO()
tryFinally(lst)
assert buf.getvalue() == result
More information about the Web-SIG
mailing list