The problem of anonymity with decorators

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Franck Pommereau

    #1

    The problem of anonymity with decorators

    Dear all,

    I would like to work around the "anonymizin g" effect of decorators when
    an exception is raised in the wrapped function. Let's consider the
    following example:

    def int_result (fun) :
    def wrapped (*largs, **kwargs) :
    result = fun(*largs, **kwargs)
    if not isinstance(resu lt, int) :
    raise TypeError, "should return int"
    return result
    return wrapped

    @int_result
    def add (a, b) :
    return a+b

    print add(1, 2)
    print add("foo", "bar")

    As expected, the last line results in raising TypeError:

    Traceback (most recent call last):
    File "wrapping.p y", line 14, in ?
    print add("foo", "bar")
    File "wrapping.p y", line 5, in wrapped
    raise TypeError, "should return int"
    TypeError: should return int

    My problem is that the errors comes from a function named "wrapped"
    while I'd prefer to see here the name of the wrapped function. Indeed,
    the code above is only a stripped down sample code but in my
    application, I'll have a lot of functions, all wrapped the same way. So
    I'd prefer a traceback like:

    Traceback (most recent call last):
    File "wrapping.p y", line 14, in ?
    print add("foo", "bar")
    File "wrapping.p y", line 8, in add (wrapped)
    @int_result
    TypeError: should return int

    Where the exception seems to come from the point where add "was"
    wrapped, instead of from the inside of the wrapper.

    I tried to change wrapper.__name_ _ and wrapper.func_na me but it does not
    change the traceback, and wrapper.func_co de.co_name is read-only. I also
    tried, unsuccessfully, to rename functions with:

    import new
    def rename (fun, name) :
    return new.function(fu n.func_code, {}, name)

    So, my questions:
    - can I change a function name so that it affects the traceback when an
    exception is raised in the function?
    - is there some special trick to raise an exception making it, in
    appearance, coming from somewhere else?

    Thanks in advance for any answer.

    Regards,
    Franck
  • Alex Martelli

    #2
    Re: The problem of anonymity with decorators

    Franck Pommereau <pommereau@un iv-paris12.fr> wrote:
    ...[color=blue]
    > import new
    > def rename (fun, name) :
    > return new.function(fu n.func_code, {}, name)[/color]

    You need to make a new code object too:

    def int_result(fun) :
    def wrapped(*largs, **kwargs) :
    result = fun(*largs, **kwargs)
    if not isinstance(resu lt, int) :
    raise TypeError, "should return int"
    return result
    w = wrapped.func_co de
    c = new.code(w.co_a rgcount, w.co_nlocals, w.co_stacksize,
    w.co_flags, w.co_code, w.co_consts, w.co_names,
    w.co_varnames, w.co_filename, fun.func_name,
    w.co_firstlinen o, w.co_lnotab,
    w.co_freevars, w.co_cellvars)
    return new.function(c, fun.func_global s, fun.func_name,
    fun.func_defaul ts, wrapped.func_cl osure)

    Of course, you should refactor these last three statement into a

    def remix(wrapped, fun): ...
    """ return a function like 'wrapped' but w/name and defaults fm 'fun'
    """
    ...same 3 statements as above, from w = ... onwards...



    Alex

    Comment

    • Michele Simionato

      #3
      Re: The problem of anonymity with decorators

      Using my decorator module
      (http://www.phyast.pitt.edu/~micheles...mentation.html,
      http://www.phyast.pitt.edu/~micheles.../decorator.zip) you solve
      the problem of the
      name, but the traceback is still not perfect. You get:

      # dec_traceback.p y
      from ms.decorator import decorator

      @decorator
      def int_result (fun, *largs, **kwargs) :
      result = fun(*largs, **kwargs)
      if not isinstance(resu lt, int) :
      raise TypeError, "should return int"
      return result

      @int_result
      def add (a, b) :
      return a+b

      print add(1, 2)
      print add("foo", "bar")

      # end dec_traceback.p y

      $ python dec_traceback.p y
      3
      Traceback (most recent call last):
      File "dec_traceback. py", line 15, in ?
      print add("foo", "bar")
      File "<string>", line 2, in add
      File "dec_traceback. py", line 7, in int_result
      raise TypeError, "should return int"
      TypeError: should return int

      The reason of <string> is that the module internally uses 'exec'. There
      should be a way around
      that, anyway, but I have no time to check it right now.
      Still, the module may be of inspiration to you.

      Michele Simionato

      Comment

      • skip@pobox.com

        #4
        Re: The problem of anonymity with decorators


        Franck> My problem is that the errors comes from a function named
        Franck> "wrapped" while I'd prefer to see here the name of the wrapped
        Franck> function.

        Take a look at



        In particular, check out the Decorator decorator.

        Skip

        Comment

        • Franck Pommereau

          #5
          Re: The problem of anonymity with decorators

          Alex, Michele and Skip,

          Many thanks for your help, I should find my way by putting all these
          information together.

          Best regards,
          Franck

          Comment

          Working...