decorators only when __debug__ == True

LX lxkain at gmail.com
Wed Mar 31 20:01:05 EDT 2010


On Mar 31, 2:28 pm, Stephen Hansen <apt.shan... at gmail.invalid> wrote:
> On 2010-03-31 13:59:01 -0700, LX said:
>
>
>
>
>
> >> pass_decorator will be called when the decorated function is _defined_,
> >> but not when the decorated function is _called_.
>
> > Why is it then that during runtime, with a breakpoint in some
> > arbitrary main() in main.py, I get something similar to the following
> > call stack:
>
> > main.py, line xxx, in <module>
> >  main()
>
> > <string>, line 2, in main
>
> >decorator.py, line 261, in pass_decorator
> >  return f(*args, **kw)
>
> > main.py, line yyy, in main()
> >  * breakpoint line here *
>
> > It looks to me the call stack still includes the additional level of
> > thedecorator... what am I missing? Thank you for your time.
>
> You're not defining pass_decorator correctly. Always show us the actual
> code when you're showing results.
>
> Your pass_decorator should just return the original function,
> undecorated, unmodified if you're not in debug. It should only return a
> decorated function otherwise.
>
> Consider:
>
> -----
> fromdecoratorimportdecorator
>
> def debug_decorator(fn):
>     if __debug__:
>         def wrapper(fn, *args, **kwargs):
>             # insert pre-condition testing here
>             if len(args) != 1:
>                 raise ValueError("Incorrect number of arguments")
>
>             result = fn(*args, **kwargs)
>
>             # insert post-condition testing here
>             if result not in (True, False):
>                 raise ValueError("Incorrect return value!")
>
>             return result
>         returndecorator(wrapper, fn)
>     else:
>         return fn
>
> @debug_decorator
> def my_test(arg):
>     if not arg:
>         raise RuntimeError
>     return True
>
> my_test(0)
> -----
>
> And the output depending on if you're in debug mode or not:
> Top:test ixokai$ python deco.py
> Traceback (most recent call last):
>   File "deco.py", line 27, in <module>
>     my_test(0)
>   File "<string>", line 2, in my_test
>   File "deco.py", line 10, in wrapper
>     result = fn(*args, **kwargs)
>   File "deco.py", line 24, in my_test
>     raise RuntimeError
> RuntimeError
>
> Top:test ixokai$ python -O deco.py
> Traceback (most recent call last):
>   File "deco.py", line 27, in <module>
>     my_test(0)
>   File "deco.py", line 24, in my_test
>     raise RuntimeError
> RuntimeError
>
> --
> --S
>
> ... p.s: change the ".invalid" to ".com" in email address to reply privately.

Thank you all a lot! The last 3 posts helped me figure it out. Indeed,
my pass_decorator function used "@decorator", using the decoratory.py
library. This prevented return of the original function. The code that
I have now is:

#NOT THIS:
#@decorator
#def pass_decorator(f, *args, **kw): # what about the slow-down that
incurs when using pass_decorator
    #return f(*args, **kw)

def pass_decorator(f):
    return f

@decorator
def trace_decorator(f, *args, **kw):
    print "calling %s with args %s, %s" % (f.func_name, args, kw)
    return f(*args, **kw)

trace_enable_flag = False #__debug__
trace = trace_decorator if trace_enable_flag else pass_decorator



More information about the Python-list mailing list