Reputation: 9007
Given a function foobar
how can I check that it's a generator that is expected by Tornado?
In [1]: from tornado import gen
In [2]: @gen.coroutine
...: def foobar():
...: print 'boom'
...:
I wasn't able to find any properties, that could indicate that it's correctly decorated by a gen.coroutine
Upvotes: 4
Views: 406
Reputation: 22154
There is no good way to detect this, and even if @coroutine
were modified to set some attribute, this would fail in cases when multiple decorators are used (e.g. handlers may be decorated with both @authenticated
and @coroutine
, and the @authenticated
decorator's wrapper will hide whatever @coroutine
added)
Furthermore, many functions (including core Tornado methods like AsyncHTTPClient.fetch
or most methods of IOStream
) are not technically coroutines but they can be called as if they were. In most cases the most important question is not "is this a coroutine" but "does this return a Future
". There is no way to determine this in Python without calling the function.
Upvotes: 4
Reputation: 363294
I could not find a satisfactory way to introspect it from the already existing decorator gen.coroutine
.
I'm not sure if this is helpful for you, but if you have control over the specific decorator itself then you may have the option of simply tacking on an attribute to the function itself.
>>> def my_gen_coroutine(f):
... f = gen.coroutine(f)
... f.is_a_tornado_generator = True
... return f
...
>>> @my_gen_coroutine
... def foobar():
... print 'boom'
...
>>> foobar.is_a_tornado_generator
True
>>> foobar()
boom
<tornado.concurrent.Future at 0x1397d50>
Of course, you would use getattr(some_function, 'is_a_tornado_generator', False)
when you don't know if the attribute is there or not.
Upvotes: 2