Skip to content

Commit

Permalink
initialize application with loop during freeze process
Browse files Browse the repository at this point in the history
  • Loading branch information
fafhrd91 committed Mar 20, 2017
1 parent f83fa42 commit c283a46
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 66 deletions.
36 changes: 25 additions & 11 deletions aiohttp/web.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,12 @@ class Application(MutableMapping):
def __init__(self, *, logger=web_logger, router=None, middlewares=(),
handler_args=None, client_max_size=1024**2,
loop=None, debug=...):
if loop is None:
loop = asyncio.get_event_loop()
if router is None:
router = web_urldispatcher.UrlDispatcher()
assert isinstance(router, AbstractRouter), router

if debug is ...:
debug = loop.get_debug()
if loop is not None:
warnings.warn("loop argument is deprecated", ResourceWarning)

self._debug = debug
self._router = router
Expand All @@ -65,6 +63,7 @@ def __init__(self, *, logger=web_logger, router=None, middlewares=(),
self._middlewares = FrozenList(middlewares)
self._state = {}
self._frozen = False
self._subapps = []

self._on_pre_signal = PreSignal()
self._on_post_signal = PostSignal()
Expand Down Expand Up @@ -106,9 +105,19 @@ def __iter__(self):
def frozen(self):
return self._frozen

def freeze(self):
def freeze(self, loop=None):
if loop is None:
loop = asyncio.get_event_loop()
if self._loop is not None and self._loop is not loop:
raise RuntimeError(
"web.Application instance initialized with different loop")
if self._frozen:
return

if self._debug is ...:
self._debug = loop.get_debug()

self._loop = loop
self._frozen = True
self._middlewares = tuple(reversed(self._middlewares))
self._router.freeze()
Expand All @@ -119,6 +128,9 @@ def freeze(self):
self._on_shutdown.freeze()
self._on_cleanup.freeze()

for subapp in self._subapps:
subapp.freeze(loop=loop)

@property
def debug(self):
return self._debug
Expand Down Expand Up @@ -152,7 +164,7 @@ def add_subapp(self, prefix, subapp):
resource = PrefixedSubAppResource(prefix, subapp)
self.router.register_resource(resource)
self._reg_subapp_signals(subapp)
subapp.freeze()
self._subapps.append(subapp)
return resource

@property
Expand Down Expand Up @@ -191,8 +203,9 @@ def loop(self):
def middlewares(self):
return self._middlewares

def make_handler(self, *, secure_proxy_ssl_header=None, **kwargs):
self.freeze()
def make_handler(self, *, loop=None,
secure_proxy_ssl_header=None, **kwargs):
self.freeze(loop=loop)

kwargs['debug'] = self.debug
if self._handler_args:
Expand Down Expand Up @@ -277,14 +290,15 @@ def __repr__(self):
def run_app(app, *, host=None, port=None, path=None, sock=None,
shutdown_timeout=60.0, ssl_context=None,
print=print, backlog=128, access_log_format=None,
access_log=access_logger):
access_log=access_logger, loop=None):
"""Run an app locally"""
loop = app.loop
if loop is None:
loop = asyncio.get_event_loop()

make_handler_kwargs = dict()
if access_log_format is not None:
make_handler_kwargs['access_log_format'] = access_log_format
handler = app.make_handler(access_log=access_log,
handler = app.make_handler(loop=loop, access_log=access_log,
**make_handler_kwargs)

loop.run_until_complete(app.startup())
Expand Down
1 change: 1 addition & 0 deletions aiohttp/worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ def make_handler(self, app):
if hasattr(self.wsgi, 'make_handler'):
access_log = self.log.access_log if self.cfg.accesslog else None
return app.make_handler(
loop=self.loop,
logger=self.log,
slow_request_timeout=self.cfg.timeout,
keepalive_timeout=self.cfg.keepalive,
Expand Down
15 changes: 11 additions & 4 deletions docs/migration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,17 @@ ServerHttpProtocol is dropped, implementation is merged with RequestHandler
a lot of low-level api's are dropped.


Application
^^^^^^^^^^^

1. Constructor parameter `loop` is deprecated. Loop is get configured by application runner,
`run_app` function for any of gunicorn workers.

2. `Application.router.add_subapp` is dropped, use `Application.add_subapp` instead

3. `Application.finished` is dropped, use `Application.cleanup` instead


WebRequest and WebResponse
^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand All @@ -171,10 +182,6 @@ WebRequest and WebResponse
async def handle(request):
return web.FileResponse('path-to-file.txt)

5. `Application.router.add_subapp` is dropped, use `Application.add_subapp` instead

6. `Application.finished` is dropped, use `Application.cleanup` instead


RequestPayloadError
^^^^^^^^^^^^^^^^^^^
Expand Down
22 changes: 11 additions & 11 deletions docs/web_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1109,7 +1109,7 @@ will be called during application finishing.
properties for later access from a :ref:`handler<aiohttp-web-handler>` via the
:attr:`Request.app` property::

app = Application(loop=loop)
app = Application()
app['database'] = await aiopg.create_engine(**db_config)

async def handler(request):
Expand All @@ -1119,18 +1119,11 @@ properties for later access from a :ref:`handler<aiohttp-web-handler>` via the
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=<default>, \
.. class:: Application(*, router=None, logger=<default>, \
middlewares=(), debug=False, **kwargs)
The class inherits :class:`dict`.

:param loop: :ref:`event loop<asyncio-event-loop>` used
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.

:param router: :class:`aiohttp.abc.AbstractRouter` instance, the system
creates :class:`UrlDispatcher` by default if
*router* is ``None``.
Expand All @@ -1144,6 +1137,8 @@ duplicated like one using :meth:`Application.copy`.

:param debug: Switches debug mode.

:param loop: loop parameter is deprecated. loop is get set during freeze stage.

.. attribute:: router

Read-only property that returns *router instance*.
Expand Down Expand Up @@ -1222,10 +1217,16 @@ duplicated like one using :meth:`Application.copy`.

.. seealso:: :ref:`aiohttp-web-graceful-shutdown` and :attr:`on_shutdown`.

.. method:: make_handler(**kwargs)
.. method:: make_handler(loop=None, **kwargs)

Creates HTTP protocol factory for handling requests.

:param loop: :ref:`event loop<asyncio-event-loop>` used
for processing HTTP requests.

If param is ``None`` :func:`asyncio.get_event_loop`
used for getting default event loop.

:param tuple secure_proxy_ssl_header: Secure proxy SSL header. Can
be used to detect request scheme,
e.g. ``secure_proxy_ssl_header=('X-Forwarded-Proto', 'https')``.
Expand Down Expand Up @@ -1264,7 +1265,6 @@ duplicated like one using :meth:`Application.copy`.
:param float lingering_timeout: maximum waiting time for more
client data to arrive when lingering close is in effect


You should pass result of the method as *protocol_factory* to
:meth:`~asyncio.AbstractEventLoop.create_server`, e.g.::

Expand Down
Loading

0 comments on commit c283a46

Please sign in to comment.