<div class="gmail_quote">On Tue, Oct 11, 2011 at 12:14 PM, Toshio Kuratomi <span dir="ltr">&lt;<a href="mailto:a.badger@gmail.com">a.badger@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div class="im">This may not be the preferred manner to write decorators but it&#39;s fairly</div>
straightforward and easy to remember compared to, say, porting away from the<br>
with statement.<br></blockquote><div><br></div><div>You can emulate &#39;with&#39; using decorators, actually, if you don&#39;t mind a nested function.  Some code from my Contextual library (minus the tests):</div><div><br>
</div><div><pre><b><font color="#a020f0">def</font></b> <b><font color="#0000ff">call_with</font></b>(ctxmgr):
    <b><font color="#bc8f8f">&quot;&quot;&quot;Emulate the PEP 343 &quot;with&quot; statement for Python versions &lt;2.5

    The following examples do the same thing at runtime::

        Python 2.5+          Python 2.4
        ------------         -------------
        with x as y:         @call_with(x)
            print y          def do_it(y):
                                 print y

    ``call_with(foo)`` returns a decorator that immediately invokes the
    function it decorates, passing in the same value that would be bound by
    the ``as`` clause of the ``with`` statement.  Thus, by decorating a
    nested function, you can get most of the benefits of &quot;with&quot;, at a cost of
    being slightly slower and perhaps a bit more obscure than the 2.5 syntax.

    Note: because of the way decorators work, the return value (if any) of the
    ``do_it()`` function above will be bound to the name ``do_it``.  So, this
    example prints &quot;42&quot;::

        @call_with(x)
        def do_it(y):
            return 42

        print do_it

    This is rather ugly, so you may prefer to do it this way instead, which
    more explicitly calls the function and gets back a value::

        def do_it(y):
            return 42

        print with_(x, do_it)
    &quot;&quot;&quot;</font></b>
    <b><font color="#a020f0">return</font></b> with_.__get__(ctxmgr, type(ctxmgr))
</pre><pre><span class="Apple-style-span" style="font-family: arial; white-space: normal; "><pre><b><font color="#a020f0">def</font></b> <b><font color="#0000ff">with_</font></b>(ctx, func):
    <b><font color="#bc8f8f">&quot;&quot;&quot;Perform PEP 343 &quot;with&quot; logic for Python versions &lt;2.5

    The following examples do the same thing at runtime::

        Python 2.5+          Python 2.3/2.4
        ------------         --------------
        with x as y:         z = with_(x,f)
            z = f(y)

    This function is used to implement the ``call_with()`` decorator, but
    can also be used directly.  It&#39;s faster and more compact in the case where
    the function ``f`` already exists.
    &quot;&quot;&quot;</font></b>
    inp = ctx.__enter__()
    <b><font color="#a020f0">try</font></b>:
        retval = func(inp)
    <b><font color="#a020f0">except</font></b>:
        <b><font color="#a020f0">if</font></b> <b><font color="#a020f0">not</font></b> ctx.__exit__(*sys.exc_info()):
            <b><font color="#a020f0">raise</font></b>
    <b><font color="#a020f0">else</font></b>:
        ctx.__exit__(None, None, None)
        <b><font color="#a020f0">return</font></b> retval
<br></pre></span><span class="Apple-style-span" style="font-family: arial; white-space: normal; "><div>This version doesn&#39;t handle the multi-context syntax of newer pythons, but could probably be extended readily enough.</div>
<div><br></div></span></pre></div></div>