diff --git a/aiohttp/web.py b/aiohttp/web.py index bba0f1b777b..cac2cf334fa 100644 --- a/aiohttp/web.py +++ b/aiohttp/web.py @@ -221,6 +221,22 @@ def middlewares(self): return self._middlewares def make_handler(self, **kwargs): + try: + debug = kwargs['debug'] + except KeyError: + pass + else: + if debug != self.debug: + raise ValueError( + "The value of `debug` parameter conflicts with the debug " + "settings of the `Application` instance. " + "The application's debug mode setting should be used " + "instead as a single point to setup a debug mode. " + "For more information please check " + "http://aiohttp.readthedocs.io/en/stable/" + "web_reference.html#aiohttp.web.Application" + ) + kwargs['debug'] = self.debug return self._handler_factory( self, self.router, loop=self.loop, **kwargs) diff --git a/docs/web_reference.rst b/docs/web_reference.rst index 00a10cf200b..3beadd99dba 100644 --- a/docs/web_reference.rst +++ b/docs/web_reference.rst @@ -1026,16 +1026,16 @@ Although :class:`Application` is a :obj:`dict`-like object, it can't be duplicated like one using :meth:`Application.copy`. .. class:: Application(*, loop=None, router=None, logger=, \ - middlewares=(), **kwargs) + middlewares=(), debug=False, **kwargs) The class inherits :class:`dict`. :param loop: :ref:`event loop` used - for processing HTTP requests. + for processing HTTP requests. - If param is ``None`` :func:`asyncio.get_event_loop` - used for getting default event loop, but we strongly - recommend to use explicit loops everywhere. + If param is ``None`` :func:`asyncio.get_event_loop` + used for getting default event loop, but we strongly + recommend to use explicit loops everywhere. :param router: :class:`aiohttp.abc.AbstractRouter` instance, the system creates :class:`UrlDispatcher` by default if @@ -1048,6 +1048,8 @@ duplicated like one using :meth:`Application.copy`. :param middlewares: :class:`list` of middleware factories, see :ref:`aiohttp-web-middlewares` for details. + :param debug: Switches debug mode. + .. attribute:: router Read-only property that returns *router instance*. @@ -1060,6 +1062,11 @@ duplicated like one using :meth:`Application.copy`. :ref:`event loop` used for processing HTTP requests. + + .. attribute:: debug + + Boolean value indicating whether the debug mode is turned on or off. + .. attribute:: on_response_prepare A :class:`~aiohttp.signals.Signal` that is fired at the beginning @@ -1128,6 +1135,13 @@ duplicated like one using :meth:`Application.copy`. :param kwargs: additional parameters for :class:`RequestHandlerFactory` constructor. + .. note:: + You should not pass ``debug`` parameter within ``kwargs`` since + its usage in :meth:`Application.make_handler` is deprecated in favor + of :attr:`Application.debug`. + The :class:`Application`'s debug mode setting should be used + as a single point to setup a debug mode. + You should pass result of the method as *protocol_factory* to :meth:`~asyncio.AbstractEventLoop.create_server`, e.g.:: diff --git a/tests/test_web_application.py b/tests/test_web_application.py index 718fc7f1ea8..060966b59f1 100644 --- a/tests/test_web_application.py +++ b/tests/test_web_application.py @@ -29,6 +29,24 @@ def test_app_default_loop(loop): assert loop is app.loop +@pytest.mark.parametrize('debug', [True, False]) +def test_app_make_handler_debug_exc(loop, mocker, debug): + app = web.Application(loop=loop, debug=debug) + + mocker.spy(app, '_handler_factory') + + app.make_handler() + app.make_handler(debug=debug) + + assert app._handler_factory.call_count == 2 + app._handler_factory.assert_called_with(app, app.router, loop=loop, + debug=debug) + + with pytest.raises(ValueError) as exc: + app.make_handler(debug=not debug) + assert 'The value of `debug` parameter conflicts with the' in str(exc) + + @asyncio.coroutine def test_app_register_on_finish(loop): app = web.Application(loop=loop)