a convenient way to deeply nest try/finally statements

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

a convenient way to deeply nest try/finally statements

Shannon -jj Behrens
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: [hidden email]
#
# 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
_______________________________________________
Web-SIG mailing list
[hidden email]
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/lists%40nabble.com
Reply | Threaded
Open this post in threaded view
|

Re: a convenient way to deeply nest try/finally statements

Paul Moore
On 10/11/05, Shannon -jj Behrens <[hidden email]> wrote:
> I'm posting this in the hope someone else will find it useful.  If you
> want it, consider it in the public domain.

Hmm, I like it. Thanks - saves me waiting for Python 2.5 and the
"with" statement :-) (It was badly mangled by gmail, but still
possible to understand the principle).

Paul.
_______________________________________________
Web-SIG mailing list
[hidden email]
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/lists%40nabble.com
Reply | Threaded
Open this post in threaded view
|

Re: a convenient way to deeply nest try/finally statements

Shannon -jj Behrens
On 10/11/05, Paul Moore <[hidden email]> wrote:
> On 10/11/05, Shannon -jj Behrens <[hidden email]> wrote:
> > I'm posting this in the hope someone else will find it useful.  If you
> > want it, consider it in the public domain.
>
> Hmm, I like it. Thanks - saves me waiting for Python 2.5 and the
> "with" statement :-) (It was badly mangled by gmail, but still
> possible to understand the principle).

Reposted from the baypiggies mailing list so as not to cross post:

I was following the "with" statement thing for a while, but eventually
gave up on keeping up with the dev mailing list.  Please correct me if
I'm wrong, but the benefit of my library is also that you don't have
to nest things inside each other.  I.e. it's a flat list of (init,
destruct) that is implemented as nested try/finallys but doesn't look
like that.  Hence, it's easy to construct such lists and rearrange
them dynamically [or inject things into them from within subclasses].

Am I mistaken?

--
Hacking is to climbing Mt. Everest as
software engineering is to building a Denny's there.
_______________________________________________
Web-SIG mailing list
[hidden email]
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/lists%40nabble.com
Reply | Threaded
Open this post in threaded view
|

Re: a convenient way to deeply nest try/finally statements

Paul Moore
On 10/14/05, Shannon -jj Behrens <[hidden email]> wrote:
> I was following the "with" statement thing for a while, but eventually
> gave up on keeping up with the dev mailing list.  Please correct me if
> I'm wrong, but the benefit of my library is also that you don't have
> to nest things inside each other.  I.e. it's a flat list of (init,
> destruct) that is implemented as nested try/finallys but doesn't look
> like that.  Hence, it's easy to construct such lists and rearrange
> them dynamically [or inject things into them from within subclasses].
>
> Am I mistaken?

No, you're right, but I had assumed it would be easy enough to write a
"combined" function which allowed you to transform

    with a:
        with b:
            with c:
                whatever

into

    with combined(a,b,c):
        whatever

Having said that, this is probably just what your library does, but
recast to work with the "with" statement...

Paul.
_______________________________________________
Web-SIG mailing list
[hidden email]
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/lists%40nabble.com