<div class="gmail_quote">On Tue, Oct 11, 2011 at 12:14 PM, Toshio Kuratomi <span dir="ltr"><<a href="mailto:a.badger@gmail.com">a.badger@gmail.com</a>></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'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 'with' using decorators, actually, if you don'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">"""Emulate the PEP 343 "with" statement for Python versions <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 "with", 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 "42"::
@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)
"""</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">"""Perform PEP 343 "with" logic for Python versions <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's faster and more compact in the case where
the function ``f`` already exists.
"""</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't handle the multi-context syntax of newer pythons, but could probably be extended readily enough.</div>
<div><br></div></span></pre></div></div>