Package: greenado
greenado========.. image:: https://travis-ci.org/virtuald/greenado.png?branch=master:target: https://travis-ci.org/virtuald/greenado:alt: Test status.. image:: https://coveralls.io/repos/virtuald/greenado/badge.png:target: https://coveralls.io/r/virtuald/greenado:alt: Test coverage status.. image:: https://readthedocs.org/projects/greenado/badge/?version=latest:target: https://readthedocs.org/projects/greenado/?badge=latest:alt: DocumentationGreenado is a utility library that provides greenlet-based coroutines fortornado. In tornado, coroutines allow you to perform asynchronous operationswithout using callbacks, providing a pseudo-synchronous flow in yourfunctions.When using Tornado's :func:`@gen.coroutine <tornado.gen.coroutine>` in alarge codebase, you will notice that they tend to be 'infectious' fromthe bottom up. In other words, for them to be truly useful, callers ofthe coroutine should 'yield' to them, which requires them to be acoroutine. In turn, their callers need to 'yield', and so on.Instead, greenado coroutines infect from the top down, and only requiresthe :func:`@greenado.groutine <greenado.concurrent.groutine>` decorator*somewhere* in the call hierarchy, but it doesn't really matter where.Once the decorator is used, you can use :func:`greenado.gyield() <greenado.concurrent.gyield>`to pseudo-synchronously wait for asynchronous events to occur. This reducescomplexity in large codebases, as you only need to use the decorator atthe very top of your call trees, and nowhere else.Documentation=============Documentation can be found at http://greenado.readthedocs.org/en/latest/Installation & Requirements===========================Installation is easiest using pip:.. code-block:: bash$ pip install greenadogreenado should work using tornado 3.2, but I only actively use it intornado 4+I have only tested greenado on Linux & OSX, but I imagine that it wouldwork correctly on platforms that tornado and greenlet support.Example usage=============In the below examples, 'main_function' is your toplevel functionin the call hierarchy that needs to call things that eventually callsome asynchronous operation in tornado.Normal tornado coroutine usage might look something like this:.. code-block:: pythonfrom tornado import gen@gen.coroutinedef do_long_operation():retval = yield long_operation()raise gen.Return(retval)@gen.coroutinedef call_long_operation():retval = yield do_long_operation()raise gen.Return(retval)@gen.coroutinedef main_function():retval = yield call_long_operation()With greenado, it looks something like this instead:.. code-block:: pythonimport greenadodef do_long_operation():retval = greenado.gyield(long_operation())return retvaldef call_long_operation():retval = do_long_operation()return retval@greenado.groutinedef main_function():retval = call_long_operation()Functions wrapped by :func:`@greenado.groutine <greenado.concurrent.groutine>` return a:class:`tornado.concurrent.Future` object which you must either yield, callresult(), or use :meth:`IOLoop.add_future <tornado.ioloop.IOLoop.add_future>` on, otherwise you may riskswallowing exceptions.Why can't I use the yield keyword?----------------------------------Well, actually, if you use yet another decorator, you still can! Check outthis example:.. code-block:: pythonimport greenado@greenado.generatordef do_long_operation():retval = yield long_operation()return retvaldef call_long_operation():retval = do_long_operation()return retval@greenado.groutinedef main_function():retval = call_long_operation()You'll note that this is very similar to the coroutines available fromtornado (and in fact, the implementation is mostly the same), but thedifference is that (once again) you don't need to do anything specialto call the do_long_operation function, other than make sure that:func:`@greenado.groutine <greenado.concurrent.groutine>` is in the call stack somewhere.Testing=======greenado.testing contains a function called gen_test which can be usedexactly like :func:`tornado.testing.gen_test`:.. code-block:: pythonimport greenadofrom greenado.testing import gen_testfrom tornado.testing import AsyncTestCasedef something_that_yields():greenado.gyield(something())class MyTest(AsyncTestCase):@gen_testdef test_something(self):something_that_yields()Contributing new changes========================1. Fork this repository2. Create your feature branch (`git checkout -b my-new-feature`)3. Test your changes (`tests/run_tests.sh`)4. Commit your changes (`git commit -am 'Add some feature'`)5. Push to the branch (`git push origin my-new-feature`)6. Create new Pull RequestCredit======Greenado is similar to and inspired by https://github.com/mopub/greenlet-tornadoand https://github.com/Gawen/tornalet, but does not require that you use it froma tornado web handler as they do.Authors=======Dustin Spicuzza (dustin@virtualroadside.com)