diff --git a/.travis.yml b/.travis.yml index 0b08ce660a6..4845bc0edce 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,6 +23,9 @@ install: - pip install -r requirements-ci.txt - pip install aiodns - pip install coveralls + - if python -c "import sys; sys.exit(sys.version_info < (3,5))"; then + pip install uvloop; + fi script: - flake8 aiohttp diff --git a/aiohttp/worker.py b/aiohttp/worker.py index 593962d3a4c..9a8fd3e3a72 100644 --- a/aiohttp/worker.py +++ b/aiohttp/worker.py @@ -9,7 +9,7 @@ from aiohttp.helpers import ensure_future -__all__ = ('GunicornWebWorker',) +__all__ = ('GunicornWebWorker', 'GunicornUVLoopWebWorker') class GunicornWebWorker(base.Worker): @@ -129,3 +129,20 @@ def handle_quit(self, sig, frame): def handle_abort(self, sig, frame): self.alive = False self.exit_code = 1 + + +class GunicornUVLoopWebWorker(GunicornWebWorker): + + def init_process(self): + import uvloop + + # Close any existing event loop before setting a + # new policy. + asyncio.get_event_loop().close() + + # Setup uvloop policy, so that every + # asyncio.get_event_loop() will create an instance + # of uvloop event loop. + asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) + + super().init_process() diff --git a/docs/gunicorn.rst b/docs/gunicorn.rst index 12d0c6dc21d..01e5dc4ed91 100644 --- a/docs/gunicorn.rst +++ b/docs/gunicorn.rst @@ -84,6 +84,12 @@ aiohttp.wsgi applications:: Gunicorn is now running and ready to serve requests to your app's worker processes. +.. note:: + + If you want to use an alternative asyncio event loop + `uvloop <https://github.com/MagicStack/uvloop>`_, you can use the + ``aiohttp.worker.GunicornUVLoopWebWorker`` worker class. + More information ---------------- diff --git a/tests/test_worker.py b/tests/test_worker.py index 79d909c4fe5..dbb3001018d 100644 --- a/tests/test_worker.py +++ b/tests/test_worker.py @@ -1,13 +1,16 @@ """Tests for aiohttp/worker.py""" import asyncio import pytest +import sys +import unittest + from unittest import mock base_worker = pytest.importorskip('aiohttp.worker') -class MyWorker(base_worker.GunicornWebWorker): +class BaseTestWorker: def __init__(self): self.servers = [] @@ -16,9 +19,23 @@ def __init__(self): self.cfg.graceful_timeout = 100 -@pytest.fixture -def worker(): - return MyWorker() +class AsyncioWorker(BaseTestWorker, base_worker.GunicornWebWorker): + pass + + +class UvloopWorker(BaseTestWorker, base_worker.GunicornUVLoopWebWorker): + + def __init__(self): + if sys.version_info < (3, 5): + # uvloop requires Python 3.5. + raise unittest.SkipTest() + + super().__init__() + + +@pytest.fixture(params=[AsyncioWorker, UvloopWorker]) +def worker(request): + return request.param() def test_init_process(worker):