Repository: aio-libs/aiohttp

Issue:
Recent change to GunicornWebWorker breaks code
## Long story short

For development, I like using the autoreload feature you can get with gunicorn; so I've been using the following python script to start up a development server:

``` python
import os

if __name__ == '__main__':
    command = (
        'gunicorn server:app ' +
        '--bind 0.0.0.0:5000 ' +
        '--workers 1 ' +
        '--worker-class aiohttp.worker.GunicornUVLoopWebWorker ' +
        '--reload')
    os.system(command)
```

This works on the 0.22 branch, but fails when I move to the master branch (1.0.0a0).  I get the following traceback using the master branch when I try to launch the server:

```
Traceback (most recent call last):
  File "/Users/bcmyers/Dropbox/Programming/python/website/venv/lib/python3.5/site-packages/gunicorn/arbiter.py", line 557, in spawn_worker
    worker.init_process()
  File "/Users/bcmyers/Dropbox/Programming/python/website/venv/lib/python3.5/site-packages/aiohttp/worker.py", line 196, in init_process
    super().init_process()
  File "/Users/bcmyers/Dropbox/Programming/python/website/venv/lib/python3.5/site-packages/aiohttp/worker.py", line 36, in init_process
    super().init_process()
  File "/Users/bcmyers/Dropbox/Programming/python/website/venv/lib/python3.5/site-packages/gunicorn/workers/base.py", line 132, in init_process
    self.run()
  File "/Users/bcmyers/Dropbox/Programming/python/website/venv/lib/python3.5/site-packages/aiohttp/worker.py", line 43, in run
    self.loop.run_until_complete(self._runner)
  File "uvloop/loop.pyx", line 1133, in uvloop.loop.Loop.run_until_complete (uvloop/loop.c:19943)
  File "uvloop/future.pyx", line 123, in uvloop.loop.BaseFuture.result (uvloop/loop.c:94147)
  File "uvloop/future.pyx", line 78, in uvloop.loop.BaseFuture._result_impl (uvloop/loop.c:93686)
  File "uvloop/task.pyx", line 126, in uvloop.loop.BaseTask._fast_step (uvloop/loop.c:99430)
  File "/Users/bcmyers/Dropbox/Programming/python/website/venv/lib/python3.5/site-packages/aiohttp/worker.py", line 91, in _run
    handler = self.make_handler(self.wsgi)
  File "/Users/bcmyers/Dropbox/Programming/python/website/venv/lib/python3.5/site-packages/aiohttp/worker.py", line 52, in make_handler
    debug=self.cfg.debug,
  File "/Users/bcmyers/Dropbox/Programming/python/website/venv/lib/python3.5/site-packages/gunicorn/config.py", line 58, in __getattr__
    raise AttributeError("No configuration setting for: %s" % name)
AttributeError: No configuration setting for: debug
```

I think the reason is that the `make_handler` method on the `GunicornWebWorker` class has changed from this:

``` python
def make_handler(self, app):
    if hasattr(self.cfg, 'debug'):
        is_debug = self.cfg.debug
    else:
        is_debug = self.log.loglevel == logging.DEBUG

    return app.make_handler(
        logger=self.log,
        debug=is_debug,
        timeout=self.cfg.timeout,
        keep_alive=self.cfg.keepalive,
        access_log=self.log.access_log,
        access_log_format=self.cfg.access_log_format)
```

to this:

``` python
def make_handler(self, app):
    return app.make_handler(
        logger=self.log,
        debug=self.cfg.debug,
        timeout=self.cfg.timeout,
        keep_alive=self.cfg.keepalive,
        access_log=self.log.access_log,
        access_log_format=self._get_valid_log_format(
            self.cfg.access_log_format))
```

It appears my `cfg` object has no `debug` attribute, which was fine on branch 0.22 but leads to my script failing on the master branch.  Is this a bug?  If not, it would be great if someone could let me know how to fix my code.

Thanks!
## My environment

```
aiohttp==1.0.0a0
gunicorn==19.6.0
uvloop==0.5.3
```



Discussion:
Thank you very much for testing not-released-yet code and raising the issue.
I've solve the bug before aiohttp 1.0 publishing


Resolving patch:
diff --git a/aiohttp/worker.py b/aiohttp/worker.py
--- a/aiohttp/worker.py
+++ b/aiohttp/worker.py
@@ -1,6 +1,7 @@
 """Async gunicorn worker for aiohttp.web"""
 
 import asyncio
+import logging
 import os
 import re
 import signal
@@ -47,11 +48,16 @@ def run(self):
         sys.exit(self.exit_code)
 
     def make_handler(self, app):
+        if hasattr(self.cfg, 'debug'):
+            is_debug = self.cfg.debug
+        else:
+            is_debug = self.log.loglevel == logging.DEBUG
+
         return app.make_handler(
             logger=self.log,
-            debug=self.cfg.debug,
-            timeout=self.cfg.timeout,
-            keep_alive=self.cfg.keepalive,
+            debug=is_debug,
+            slow_request_timeout=self.cfg.timeout,
+            keepalive_timeout=self.cfg.keepalive,
             access_log=self.log.access_log,
             access_log_format=self._get_valid_log_format(
                 self.cfg.access_log_format))


Test patch:
diff --git a/tests/test_worker.py b/tests/test_worker.py
--- a/tests/test_worker.py
+++ b/tests/test_worker.py
@@ -1,5 +1,6 @@
 """Tests for aiohttp/worker.py"""
 import asyncio
+import logging
 import pathlib
 import ssl
 from unittest import mock
@@ -11,6 +12,7 @@
 
 base_worker = pytest.importorskip('aiohttp.worker')
 
+
 try:
     import uvloop
 except ImportError:
@@ -106,6 +108,62 @@ def test_make_handler(worker, mocker):
     assert worker._get_valid_log_format.called
 
 
+def test_make_handler_debug_in_config(worker, mocker):
+    app = mock.Mock()
+    make_handler = app.make_handler = mock.Mock()
+    worker.cfg.debug = True
+    worker.cfg.access_log_format = worker.DEFAULT_GUNICORN_LOG_FORMAT
+    worker.cfg.keepalive = 10
+    worker.cfg.timeout = 15
+    worker.log = mock.Mock()
+    worker.make_handler(app)
+    make_handler.assert_called_with(
+        access_log=mock.ANY,
+        access_log_format=worker.DEFAULT_AIOHTTP_LOG_FORMAT,
+        debug=True,
+        keepalive_timeout=10,
+        logger=mock.ANY,
+        slow_request_timeout=15)
+
+
+def test_make_handler_no_debug_in_config(worker, mocker):
+    app = mock.Mock()
+    make_handler = app.make_handler = mock.Mock()
+    del worker.cfg.debug
+    worker.cfg.access_log_format = worker.DEFAULT_GUNICORN_LOG_FORMAT
+    worker.cfg.keepalive = 10
+    worker.cfg.timeout = 15
+    worker.log = mock.Mock()
+    worker.log.loglevel = logging.DEBUG
+    worker.make_handler(app)
+    make_handler.assert_called_with(
+        access_log=mock.ANY,
+        access_log_format=worker.DEFAULT_AIOHTTP_LOG_FORMAT,
+        debug=True,
+        keepalive_timeout=10,
+        logger=mock.ANY,
+        slow_request_timeout=15)
+
+
+def test_make_handler_no_debug_in_config_not_debug_logger(worker, mocker):
+    app = mock.Mock()
+    make_handler = app.make_handler = mock.Mock()
+    del worker.cfg.debug
+    worker.cfg.access_log_format = worker.DEFAULT_GUNICORN_LOG_FORMAT
+    worker.cfg.keepalive = 10
+    worker.cfg.timeout = 15
+    worker.log = mock.Mock()
+    worker.log.loglevel = logging.INFO
+    worker.make_handler(app)
+    make_handler.assert_called_with(
+        access_log=mock.ANY,
+        access_log_format=worker.DEFAULT_AIOHTTP_LOG_FORMAT,
+        debug=False,
+        keepalive_timeout=10,
+        logger=mock.ANY,
+        slow_request_timeout=15)
+
+
 @pytest.mark.parametrize('source,result', [
     (ACCEPTABLE_LOG_FORMAT, ACCEPTABLE_LOG_FORMAT),
     (AsyncioWorker.DEFAULT_GUNICORN_LOG_FORMAT,