pganti / micheles

Automatically exported from code.google.com/p/micheles
0 stars 0 forks source link

Doesn't work with "callable" `func` as documented in comment. #14

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
I'm trying to decorate a fabric `WrappedCallableTask` object. The comment on 
line 73 of `decorator.py` says `func` can be a class or callable, but not an 
instance method. `WrappedCallableTask` objects are callable.

This seems to be because `self.signature` is only assigned for actual functions 
(not callables). If I set it to an empty string instead, it works as expected.

Here's an interactive shell session demonstrating the problem.

In [1]: from fabric.api import task

In [2]: import decorator

In [3]: @decorator.decorator
   ...: def foo(func, *args, **kwargs):
   ...:         print 'foo'
   ...:         return func(*args, **kwargs)
   ...: 

In [4]: def x():
   ...:         print 'X'
   ...:     

In [5]: x
Out[5]: <function __main__.x>

In [6]: x()
X

In [7]: foo(x)
Out[7]: <function __main__.x>

In [8]: foo(x)()
foo
X

In [9]: y = task(x)

In [10]: y
Out[10]: <fabric.tasks.WrappedCallableTask at 0x107171350>

# `y` is callable, just like `x`.
In [11]: y()
X

# But I can't decorate it with a decorator that has been created by 
`decorator.decorator`.
In [12]: foo(y)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-12-c34da9d57b44> in <module>()
----> 1 foo(y)

<string> in foo(func)

/Users/tailee/.virtualenvs/ixcmembers/lib/python2.7/site-packages/decorator.pyc 
in decorator(caller, func)
    198         return FunctionMaker.create(
    199             func, "return _call_(_func_, %(shortsignature)s)",
--> 200             evaldict, undecorated=func, __wrapped__=func)
    201     else: # returns a decorator
    202         if inspect.isclass(caller):

/Users/tailee/.virtualenvs/ixcmembers/lib/python2.7/site-packages/decorator.pyc 
in create(cls, obj, body, evaldict, defaults, doc, module, addsource, **attrs)
    182             signature = None
    183             func = obj
--> 184         self = cls(func, name, signature, defaults, doc, module)
    185         ibody = '\n'.join('    ' + line for line in body.splitlines())
    186         return self.make('def %(name)s(%(signature)s):\n' + ibody,

/Users/tailee/.virtualenvs/ixcmembers/lib/python2.7/site-packages/decorator.pyc 
in __init__(self, func, name, signature, defaults, doc, module, funcdict)
    122         assert hasattr(self, 'name')
    123         if not hasattr(self, 'signature'):
--> 124             raise TypeError('You are decorating a non function: %s' % 
func)
    125 
    126     def update(self, func, **kw):

TypeError: You are decorating a non function: <fabric.tasks.WrappedCallableTask 
object at 0x107171350>

Original issue reported on code.google.com by t...@interaction.net.au on 24 Jun 2014 at 7:04

GoogleCodeExporter commented 8 years ago
This is on design. If you want to decorate a callable which is not a function, 
you can, but you must add to it a signature string.

Original comment by michele....@gmail.com on 16 Mar 2015 at 3:12