We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Adding routes to subapps is broken after attaching subapp to the parent app
## Long story short

If one adds routes to subapp before `app.add_subapp` accessing them works well, otherwise it results in 404.

## Expected behaviour

It's naturally expected that routing will work well regardless of the order of function calls.

## Actual behaviour

Given `sub_app_cbv.py`:
```python
import sys
import aiohttp.web

API_URL_PREFIX = r'/api/v1'

class PingView(aiohttp.web.View):
    async def get(self):
        return aiohttp.web.Response(text='pong')

def just_app_with_routes_def(app, api_app):
    app.router.add_route('GET', API_URL_PREFIX + r'/ping/', PingView)

def sub_app_after_routes_def(app, api_app):
    api_app.router.add_route('GET', r'/ping/', PingView)
    app.add_subapp(API_URL_PREFIX, api_app)

def sub_app_before_routes_def(app, api_app):
    app.add_subapp(API_URL_PREFIX, api_app)
    api_app.router.add_route('GET', r'/ping/', PingView)

def run_app(coro_name):
    print(f'Going to run {coro_name}')
    setup_app = globals()[coro_name]
    app = aiohttp.web.Application()
    api_app = aiohttp.web.Application()
    setup_app(app, api_app)
    aiohttp.web.run_app(app)

def main():
    if len(sys.argv) < 2:
        raise RuntimeError('Supply one cli argument plz [just_app_with_routes_def|sub_app_after_routes_def|sub_app_before_routes_def]')
    coro_name = sys.argv[1]
    run_app(coro_name)

__name__ == '__main__' and main()
```

##### Demo 1

```shell
$ python sub_app_cbv.py just_app_with_routes_def
Going to run just_app_with_routes_def
======== Running on http://0.0.0.0:8080 ========
(Press CTRL+C to quit)
```

```shell
$ http :8080/api/v1/ping/
HTTP/1.1 200 OK
Content-Length: 4
Content-Type: text/plain; charset=utf-8
Date: Thu, 11 Jan 2018 23:17:52 GMT
Server: Python/3.6 aiohttp/2.3.7
pong
```

##### Demo 2

```shell
$ python sub_app_cbv.py sub_app_after_routes_def
Going to run sub_app_after_routes_def
======== Running on http://0.0.0.0:8080 ========
(Press CTRL+C to quit)
```

```shell
$ http :8080/api/v1/ping/
HTTP/1.1 200 OK
Content-Length: 4
Content-Type: text/plain; charset=utf-8
Date: Thu, 11 Jan 2018 23:20:58 GMT
Server: Python/3.6 aiohttp/2.3.7
pong
```

##### Demo 3

```shell
$ python sub_app_cbv.py sub_app_before_routes_def
Going to run sub_app_before_routes_def
======== Running on http://0.0.0.0:8080 ========
(Press CTRL+C to quit)
```

```shell
$ http :8080/api/v1/ping/
HTTP/1.1 404 Not Found
Content-Length: 14
Content-Type: text/plain; charset=utf-8
Date: Thu, 11 Jan 2018 23:21:41 GMT
Server: Python/3.6 aiohttp/2.3.7
404: Not Found
```

## Steps to reproduce

See above.

## Your environment

Gentoo laptop, pyenv, 3.6. Not really env-related.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `aiohttp/web_app.py`
Content:
```
1 import asyncio
2 import warnings
3 from collections import MutableMapping
4 from functools import partial
5 
6 from . import hdrs
7 from .abc import AbstractAccessLogger, AbstractMatchInfo, AbstractRouter
8 from .frozenlist import FrozenList
9 from .helpers import AccessLogger
10 from .log import web_logger
11 from .signals import Signal
12 from .web_middlewares import _fix_request_current_app
13 from .web_request import Request
14 from .web_response import StreamResponse
15 from .web_server import Server
16 from .web_urldispatcher import PrefixedSubAppResource, UrlDispatcher
17 
18 
19 class Application(MutableMapping):
20     def __init__(self, *,
21                  logger=web_logger,
22                  router=None,
23                  middlewares=(),
24                  handler_args=None,
25                  client_max_size=1024**2,
26                  loop=None,
27                  debug=...):
28         if router is None:
29             router = UrlDispatcher()
30         assert isinstance(router, AbstractRouter), router
31 
32         if loop is not None:
33             warnings.warn("loop argument is deprecated", DeprecationWarning,
34                           stacklevel=2)
35 
36         self._debug = debug
37         self._router = router
38         self._loop = loop
39         self._handler_args = handler_args
40         self.logger = logger
41 
42         self._middlewares = FrozenList(middlewares)
43         self._state = {}
44         self._frozen = False
45         self._subapps = []
46 
47         self._on_response_prepare = Signal(self)
48         self._on_startup = Signal(self)
49         self._on_shutdown = Signal(self)
50         self._on_cleanup = Signal(self)
51         self._client_max_size = client_max_size
52 
53     # MutableMapping API
54 
55     def __eq__(self, other):
56         return self is other
57 
58     def __getitem__(self, key):
59         return self._state[key]
60 
61     def _check_frozen(self):
62         if self._frozen:
63             warnings.warn("Changing state of started or joined "
64                           "application is deprecated",
65                           DeprecationWarning,
66                           stacklevel=3)
67 
68     def __setitem__(self, key, value):
69         self._check_frozen()
70         self._state[key] = value
71 
72     def __delitem__(self, key):
73         self._check_frozen()
74         del self._state[key]
75 
76     def __len__(self):
77         return len(self._state)
78 
79     def __iter__(self):
80         return iter(self._state)
81 
82     ########
83     @property
84     def loop(self):
85         return self._loop
86 
87     def _set_loop(self, loop):
88         if loop is None:
89             loop = asyncio.get_event_loop()
90         if self._loop is not None and self._loop is not loop:
91             raise RuntimeError(
92                 "web.Application instance initialized with different loop")
93 
94         self._loop = loop
95 
96         # set loop debug
97         if self._debug is ...:
98             self._debug = loop.get_debug()
99 
100         # set loop to sub applications
101         for subapp in self._subapps:
102             subapp._set_loop(loop)
103 
104     @property
105     def frozen(self):
106         return self._frozen
107 
108     def freeze(self):
109         if self._frozen:
110             return
111 
112         self._frozen = True
113         self._middlewares.freeze()
114         self._router.freeze()
115         self._on_response_prepare.freeze()
116         self._on_startup.freeze()
117         self._on_shutdown.freeze()
118         self._on_cleanup.freeze()
119         self._middlewares_handlers = tuple(self._prepare_middleware())
120 
121         # If current app and any subapp do not have middlewares avoid run all
122         # of the code footprint that it implies, which have a middleware
123         # hardcoded per app that sets up the current_app attribute. If no
124         # middlewares are configured the handler will receive the proper
125         # current_app without needing all of this code.
126         self._run_middlewares = True if self.middlewares else False
127 
128         for subapp in self._subapps:
129             subapp.freeze()
130             self._run_middlewares =\
131                 self._run_middlewares or subapp._run_middlewares
132 
133     @property
134     def debug(self):
135         return self._debug
136 
137     def _reg_subapp_signals(self, subapp):
138 
139         def reg_handler(signame):
140             subsig = getattr(subapp, signame)
141 
142             async def handler(app):
143                 await subsig.send(subapp)
144             appsig = getattr(self, signame)
145             appsig.append(handler)
146 
147         reg_handler('on_startup')
148         reg_handler('on_shutdown')
149         reg_handler('on_cleanup')
150 
151     def add_subapp(self, prefix, subapp):
152         if self.frozen:
153             raise RuntimeError(
154                 "Cannot add sub application to frozen application")
155         if subapp.frozen:
156             raise RuntimeError("Cannot add frozen application")
157         if prefix.endswith('/'):
158             prefix = prefix[:-1]
159         if prefix in ('', '/'):
160             raise ValueError("Prefix cannot be empty")
161 
162         resource = PrefixedSubAppResource(prefix, subapp)
163         self.router.register_resource(resource)
164         self._reg_subapp_signals(subapp)
165         self._subapps.append(subapp)
166         if self._loop is not None:
167             subapp._set_loop(self._loop)
168         return resource
169 
170     @property
171     def on_response_prepare(self):
172         return self._on_response_prepare
173 
174     @property
175     def on_startup(self):
176         return self._on_startup
177 
178     @property
179     def on_shutdown(self):
180         return self._on_shutdown
181 
182     @property
183     def on_cleanup(self):
184         return self._on_cleanup
185 
186     @property
187     def router(self):
188         return self._router
189 
190     @property
191     def middlewares(self):
192         return self._middlewares
193 
194     def make_handler(self, *,
195                      loop=None,
196                      access_log_class=AccessLogger,
197                      **kwargs):
198 
199         if not issubclass(access_log_class, AbstractAccessLogger):
200             raise TypeError(
201                 'access_log_class must be subclass of '
202                 'aiohttp.abc.AbstractAccessLogger, got {}'.format(
203                     access_log_class))
204 
205         self._set_loop(loop)
206         self.freeze()
207 
208         kwargs['debug'] = self.debug
209         if self._handler_args:
210             for k, v in self._handler_args.items():
211                 kwargs[k] = v
212 
213         return Server(self._handle, request_factory=self._make_request,
214                       access_log_class=access_log_class,
215                       loop=self.loop, **kwargs)
216 
217     async def startup(self):
218         """Causes on_startup signal
219 
220         Should be called in the event loop along with the request handler.
221         """
222         await self.on_startup.send(self)
223 
224     async def shutdown(self):
225         """Causes on_shutdown signal
226 
227         Should be called before cleanup()
228         """
229         await self.on_shutdown.send(self)
230 
231     async def cleanup(self):
232         """Causes on_cleanup signal
233 
234         Should be called after shutdown()
235         """
236         await self.on_cleanup.send(self)
237 
238     def _make_request(self, message, payload, protocol, writer, task,
239                       _cls=Request):
240         return _cls(
241             message, payload, protocol, writer, task,
242             self._loop,
243             client_max_size=self._client_max_size)
244 
245     def _prepare_middleware(self):
246         for m in reversed(self._middlewares):
247             if getattr(m, '__middleware_version__', None) == 1:
248                 yield m, True
249             else:
250                 warnings.warn('old-style middleware "{!r}" deprecated, '
251                               'see #2252'.format(m),
252                               DeprecationWarning, stacklevel=2)
253                 yield m, False
254 
255         yield _fix_request_current_app(self), True
256 
257     async def _handle(self, request):
258         match_info = await self._router.resolve(request)
259         assert isinstance(match_info, AbstractMatchInfo), match_info
260         match_info.add_app(self)
261 
262         if __debug__:
263             match_info.freeze()
264 
265         resp = None
266         request._match_info = match_info
267         expect = request.headers.get(hdrs.EXPECT)
268         if expect:
269             resp = await match_info.expect_handler(request)
270             await request.writer.drain()
271 
272         if resp is None:
273             handler = match_info.handler
274 
275             if self._run_middlewares:
276                 for app in match_info.apps[::-1]:
277                     for m, new_style in app._middlewares_handlers:
278                         if new_style:
279                             handler = partial(m, handler=handler)
280                         else:
281                             handler = await m(app, handler)
282 
283             resp = await handler(request)
284 
285         assert isinstance(resp, StreamResponse), \
286             ("Handler {!r} should return response instance, "
287              "got {!r} [middlewares {!r}]").format(
288                  match_info.handler, type(resp),
289                  [middleware
290                   for app in match_info.apps
291                   for middleware in app.middlewares])
292         return resp
293 
294     def __call__(self):
295         """gunicorn compatibility"""
296         return self
297 
298     def __repr__(self):
299         return "<Application 0x{:x}>".format(id(self))
300
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/aiohttp/web_app.py b/aiohttp/web_app.py
--- a/aiohttp/web_app.py
+++ b/aiohttp/web_app.py
@@ -163,6 +163,7 @@
         self.router.register_resource(resource)
         self._reg_subapp_signals(subapp)
         self._subapps.append(subapp)
+        subapp.freeze()
         if self._loop is not None:
             subapp._set_loop(self._loop)
         return resource

{"golden_diff": "diff --git a/aiohttp/web_app.py b/aiohttp/web_app.py\n--- a/aiohttp/web_app.py\n+++ b/aiohttp/web_app.py\n@@ -163,6 +163,7 @@\n         self.router.register_resource(resource)\n         self._reg_subapp_signals(subapp)\n         self._subapps.append(subapp)\n+        subapp.freeze()\n         if self._loop is not None:\n             subapp._set_loop(self._loop)\n         return resource\n", "issue": "Adding routes to subapps is broken after attaching subapp to the parent app\n## Long story short\r\n\r\nIf one adds routes to subapp before `app.add_subapp` accessing them works well, otherwise it results in 404.\r\n\r\n## Expected behaviour\r\n\r\nIt's naturally expected that routing will work well regardless of the order of function calls.\r\n\r\n## Actual behaviour\r\n\r\nGiven `sub_app_cbv.py`:\r\n```python\r\nimport sys\r\nimport aiohttp.web\r\n\r\nAPI_URL_PREFIX = r'/api/v1'\r\n\r\nclass PingView(aiohttp.web.View):\r\n    async def get(self):\r\n        return aiohttp.web.Response(text='pong')\r\n\r\ndef just_app_with_routes_def(app, api_app):\r\n    app.router.add_route('GET', API_URL_PREFIX + r'/ping/', PingView)\r\n\r\ndef sub_app_after_routes_def(app, api_app):\r\n    api_app.router.add_route('GET', r'/ping/', PingView)\r\n    app.add_subapp(API_URL_PREFIX, api_app)\r\n\r\ndef sub_app_before_routes_def(app, api_app):\r\n    app.add_subapp(API_URL_PREFIX, api_app)\r\n    api_app.router.add_route('GET', r'/ping/', PingView)\r\n\r\ndef run_app(coro_name):\r\n    print(f'Going to run {coro_name}')\r\n    setup_app = globals()[coro_name]\r\n    app = aiohttp.web.Application()\r\n    api_app = aiohttp.web.Application()\r\n    setup_app(app, api_app)\r\n    aiohttp.web.run_app(app)\r\n\r\ndef main():\r\n    if len(sys.argv) < 2:\r\n        raise RuntimeError('Supply one cli argument plz [just_app_with_routes_def|sub_app_after_routes_def|sub_app_before_routes_def]')\r\n    coro_name = sys.argv[1]\r\n    run_app(coro_name)\r\n\r\n__name__ == '__main__' and main()\r\n```\r\n\r\n##### Demo 1\r\n\r\n```shell\r\n$ python sub_app_cbv.py just_app_with_routes_def\r\nGoing to run just_app_with_routes_def\r\n======== Running on http://0.0.0.0:8080 ========\r\n(Press CTRL+C to quit)\r\n```\r\n\r\n```shell\r\n$ http :8080/api/v1/ping/\r\nHTTP/1.1 200 OK\r\nContent-Length: 4\r\nContent-Type: text/plain; charset=utf-8\r\nDate: Thu, 11 Jan 2018 23:17:52 GMT\r\nServer: Python/3.6 aiohttp/2.3.7\r\npong\r\n```\r\n\r\n##### Demo 2\r\n\r\n```shell\r\n$ python sub_app_cbv.py sub_app_after_routes_def\r\nGoing to run sub_app_after_routes_def\r\n======== Running on http://0.0.0.0:8080 ========\r\n(Press CTRL+C to quit)\r\n```\r\n\r\n```shell\r\n$ http :8080/api/v1/ping/\r\nHTTP/1.1 200 OK\r\nContent-Length: 4\r\nContent-Type: text/plain; charset=utf-8\r\nDate: Thu, 11 Jan 2018 23:20:58 GMT\r\nServer: Python/3.6 aiohttp/2.3.7\r\npong\r\n```\r\n\r\n##### Demo 3\r\n\r\n```shell\r\n$ python sub_app_cbv.py sub_app_before_routes_def\r\nGoing to run sub_app_before_routes_def\r\n======== Running on http://0.0.0.0:8080 ========\r\n(Press CTRL+C to quit)\r\n```\r\n\r\n```shell\r\n$ http :8080/api/v1/ping/\r\nHTTP/1.1 404 Not Found\r\nContent-Length: 14\r\nContent-Type: text/plain; charset=utf-8\r\nDate: Thu, 11 Jan 2018 23:21:41 GMT\r\nServer: Python/3.6 aiohttp/2.3.7\r\n404: Not Found\r\n```\r\n\r\n## Steps to reproduce\r\n\r\nSee above.\r\n\r\n## Your environment\r\n\r\nGentoo laptop, pyenv, 3.6. Not really env-related.\r\n\n", "before_files": [{"content": "import asyncio\nimport warnings\nfrom collections import MutableMapping\nfrom functools import partial\n\nfrom . import hdrs\nfrom .abc import AbstractAccessLogger, AbstractMatchInfo, AbstractRouter\nfrom .frozenlist import FrozenList\nfrom .helpers import AccessLogger\nfrom .log import web_logger\nfrom .signals import Signal\nfrom .web_middlewares import _fix_request_current_app\nfrom .web_request import Request\nfrom .web_response import StreamResponse\nfrom .web_server import Server\nfrom .web_urldispatcher import PrefixedSubAppResource, UrlDispatcher\n\n\nclass Application(MutableMapping):\n    def __init__(self, *,\n                 logger=web_logger,\n                 router=None,\n                 middlewares=(),\n                 handler_args=None,\n                 client_max_size=1024**2,\n                 loop=None,\n                 debug=...):\n        if router is None:\n            router = UrlDispatcher()\n        assert isinstance(router, AbstractRouter), router\n\n        if loop is not None:\n            warnings.warn(\"loop argument is deprecated\", DeprecationWarning,\n                          stacklevel=2)\n\n        self._debug = debug\n        self._router = router\n        self._loop = loop\n        self._handler_args = handler_args\n        self.logger = logger\n\n        self._middlewares = FrozenList(middlewares)\n        self._state = {}\n        self._frozen = False\n        self._subapps = []\n\n        self._on_response_prepare = Signal(self)\n        self._on_startup = Signal(self)\n        self._on_shutdown = Signal(self)\n        self._on_cleanup = Signal(self)\n        self._client_max_size = client_max_size\n\n    # MutableMapping API\n\n    def __eq__(self, other):\n        return self is other\n\n    def __getitem__(self, key):\n        return self._state[key]\n\n    def _check_frozen(self):\n        if self._frozen:\n            warnings.warn(\"Changing state of started or joined \"\n                          \"application is deprecated\",\n                          DeprecationWarning,\n                          stacklevel=3)\n\n    def __setitem__(self, key, value):\n        self._check_frozen()\n        self._state[key] = value\n\n    def __delitem__(self, key):\n        self._check_frozen()\n        del self._state[key]\n\n    def __len__(self):\n        return len(self._state)\n\n    def __iter__(self):\n        return iter(self._state)\n\n    ########\n    @property\n    def loop(self):\n        return self._loop\n\n    def _set_loop(self, loop):\n        if loop is None:\n            loop = asyncio.get_event_loop()\n        if self._loop is not None and self._loop is not loop:\n            raise RuntimeError(\n                \"web.Application instance initialized with different loop\")\n\n        self._loop = loop\n\n        # set loop debug\n        if self._debug is ...:\n            self._debug = loop.get_debug()\n\n        # set loop to sub applications\n        for subapp in self._subapps:\n            subapp._set_loop(loop)\n\n    @property\n    def frozen(self):\n        return self._frozen\n\n    def freeze(self):\n        if self._frozen:\n            return\n\n        self._frozen = True\n        self._middlewares.freeze()\n        self._router.freeze()\n        self._on_response_prepare.freeze()\n        self._on_startup.freeze()\n        self._on_shutdown.freeze()\n        self._on_cleanup.freeze()\n        self._middlewares_handlers = tuple(self._prepare_middleware())\n\n        # If current app and any subapp do not have middlewares avoid run all\n        # of the code footprint that it implies, which have a middleware\n        # hardcoded per app that sets up the current_app attribute. If no\n        # middlewares are configured the handler will receive the proper\n        # current_app without needing all of this code.\n        self._run_middlewares = True if self.middlewares else False\n\n        for subapp in self._subapps:\n            subapp.freeze()\n            self._run_middlewares =\\\n                self._run_middlewares or subapp._run_middlewares\n\n    @property\n    def debug(self):\n        return self._debug\n\n    def _reg_subapp_signals(self, subapp):\n\n        def reg_handler(signame):\n            subsig = getattr(subapp, signame)\n\n            async def handler(app):\n                await subsig.send(subapp)\n            appsig = getattr(self, signame)\n            appsig.append(handler)\n\n        reg_handler('on_startup')\n        reg_handler('on_shutdown')\n        reg_handler('on_cleanup')\n\n    def add_subapp(self, prefix, subapp):\n        if self.frozen:\n            raise RuntimeError(\n                \"Cannot add sub application to frozen application\")\n        if subapp.frozen:\n            raise RuntimeError(\"Cannot add frozen application\")\n        if prefix.endswith('/'):\n            prefix = prefix[:-1]\n        if prefix in ('', '/'):\n            raise ValueError(\"Prefix cannot be empty\")\n\n        resource = PrefixedSubAppResource(prefix, subapp)\n        self.router.register_resource(resource)\n        self._reg_subapp_signals(subapp)\n        self._subapps.append(subapp)\n        if self._loop is not None:\n            subapp._set_loop(self._loop)\n        return resource\n\n    @property\n    def on_response_prepare(self):\n        return self._on_response_prepare\n\n    @property\n    def on_startup(self):\n        return self._on_startup\n\n    @property\n    def on_shutdown(self):\n        return self._on_shutdown\n\n    @property\n    def on_cleanup(self):\n        return self._on_cleanup\n\n    @property\n    def router(self):\n        return self._router\n\n    @property\n    def middlewares(self):\n        return self._middlewares\n\n    def make_handler(self, *,\n                     loop=None,\n                     access_log_class=AccessLogger,\n                     **kwargs):\n\n        if not issubclass(access_log_class, AbstractAccessLogger):\n            raise TypeError(\n                'access_log_class must be subclass of '\n                'aiohttp.abc.AbstractAccessLogger, got {}'.format(\n                    access_log_class))\n\n        self._set_loop(loop)\n        self.freeze()\n\n        kwargs['debug'] = self.debug\n        if self._handler_args:\n            for k, v in self._handler_args.items():\n                kwargs[k] = v\n\n        return Server(self._handle, request_factory=self._make_request,\n                      access_log_class=access_log_class,\n                      loop=self.loop, **kwargs)\n\n    async def startup(self):\n        \"\"\"Causes on_startup signal\n\n        Should be called in the event loop along with the request handler.\n        \"\"\"\n        await self.on_startup.send(self)\n\n    async def shutdown(self):\n        \"\"\"Causes on_shutdown signal\n\n        Should be called before cleanup()\n        \"\"\"\n        await self.on_shutdown.send(self)\n\n    async def cleanup(self):\n        \"\"\"Causes on_cleanup signal\n\n        Should be called after shutdown()\n        \"\"\"\n        await self.on_cleanup.send(self)\n\n    def _make_request(self, message, payload, protocol, writer, task,\n                      _cls=Request):\n        return _cls(\n            message, payload, protocol, writer, task,\n            self._loop,\n            client_max_size=self._client_max_size)\n\n    def _prepare_middleware(self):\n        for m in reversed(self._middlewares):\n            if getattr(m, '__middleware_version__', None) == 1:\n                yield m, True\n            else:\n                warnings.warn('old-style middleware \"{!r}\" deprecated, '\n                              'see #2252'.format(m),\n                              DeprecationWarning, stacklevel=2)\n                yield m, False\n\n        yield _fix_request_current_app(self), True\n\n    async def _handle(self, request):\n        match_info = await self._router.resolve(request)\n        assert isinstance(match_info, AbstractMatchInfo), match_info\n        match_info.add_app(self)\n\n        if __debug__:\n            match_info.freeze()\n\n        resp = None\n        request._match_info = match_info\n        expect = request.headers.get(hdrs.EXPECT)\n        if expect:\n            resp = await match_info.expect_handler(request)\n            await request.writer.drain()\n\n        if resp is None:\n            handler = match_info.handler\n\n            if self._run_middlewares:\n                for app in match_info.apps[::-1]:\n                    for m, new_style in app._middlewares_handlers:\n                        if new_style:\n                            handler = partial(m, handler=handler)\n                        else:\n                            handler = await m(app, handler)\n\n            resp = await handler(request)\n\n        assert isinstance(resp, StreamResponse), \\\n            (\"Handler {!r} should return response instance, \"\n             \"got {!r} [middlewares {!r}]\").format(\n                 match_info.handler, type(resp),\n                 [middleware\n                  for app in match_info.apps\n                  for middleware in app.middlewares])\n        return resp\n\n    def __call__(self):\n        \"\"\"gunicorn compatibility\"\"\"\n        return self\n\n    def __repr__(self):\n        return \"<Application 0x{:x}>\".format(id(self))\n", "path": "aiohttp/web_app.py"}], "after_files": [{"content": "import asyncio\nimport warnings\nfrom collections import MutableMapping\nfrom functools import partial\n\nfrom . import hdrs\nfrom .abc import AbstractAccessLogger, AbstractMatchInfo, AbstractRouter\nfrom .frozenlist import FrozenList\nfrom .helpers import AccessLogger\nfrom .log import web_logger\nfrom .signals import Signal\nfrom .web_middlewares import _fix_request_current_app\nfrom .web_request import Request\nfrom .web_response import StreamResponse\nfrom .web_server import Server\nfrom .web_urldispatcher import PrefixedSubAppResource, UrlDispatcher\n\n\nclass Application(MutableMapping):\n    def __init__(self, *,\n                 logger=web_logger,\n                 router=None,\n                 middlewares=(),\n                 handler_args=None,\n                 client_max_size=1024**2,\n                 loop=None,\n                 debug=...):\n        if router is None:\n            router = UrlDispatcher()\n        assert isinstance(router, AbstractRouter), router\n\n        if loop is not None:\n            warnings.warn(\"loop argument is deprecated\", DeprecationWarning,\n                          stacklevel=2)\n\n        self._debug = debug\n        self._router = router\n        self._loop = loop\n        self._handler_args = handler_args\n        self.logger = logger\n\n        self._middlewares = FrozenList(middlewares)\n        self._state = {}\n        self._frozen = False\n        self._subapps = []\n\n        self._on_response_prepare = Signal(self)\n        self._on_startup = Signal(self)\n        self._on_shutdown = Signal(self)\n        self._on_cleanup = Signal(self)\n        self._client_max_size = client_max_size\n\n    # MutableMapping API\n\n    def __eq__(self, other):\n        return self is other\n\n    def __getitem__(self, key):\n        return self._state[key]\n\n    def _check_frozen(self):\n        if self._frozen:\n            warnings.warn(\"Changing state of started or joined \"\n                          \"application is deprecated\",\n                          DeprecationWarning,\n                          stacklevel=3)\n\n    def __setitem__(self, key, value):\n        self._check_frozen()\n        self._state[key] = value\n\n    def __delitem__(self, key):\n        self._check_frozen()\n        del self._state[key]\n\n    def __len__(self):\n        return len(self._state)\n\n    def __iter__(self):\n        return iter(self._state)\n\n    ########\n    @property\n    def loop(self):\n        return self._loop\n\n    def _set_loop(self, loop):\n        if loop is None:\n            loop = asyncio.get_event_loop()\n        if self._loop is not None and self._loop is not loop:\n            raise RuntimeError(\n                \"web.Application instance initialized with different loop\")\n\n        self._loop = loop\n\n        # set loop debug\n        if self._debug is ...:\n            self._debug = loop.get_debug()\n\n        # set loop to sub applications\n        for subapp in self._subapps:\n            subapp._set_loop(loop)\n\n    @property\n    def frozen(self):\n        return self._frozen\n\n    def freeze(self):\n        if self._frozen:\n            return\n\n        self._frozen = True\n        self._middlewares.freeze()\n        self._router.freeze()\n        self._on_response_prepare.freeze()\n        self._on_startup.freeze()\n        self._on_shutdown.freeze()\n        self._on_cleanup.freeze()\n        self._middlewares_handlers = tuple(self._prepare_middleware())\n\n        # If current app and any subapp do not have middlewares avoid run all\n        # of the code footprint that it implies, which have a middleware\n        # hardcoded per app that sets up the current_app attribute. If no\n        # middlewares are configured the handler will receive the proper\n        # current_app without needing all of this code.\n        self._run_middlewares = True if self.middlewares else False\n\n        for subapp in self._subapps:\n            subapp.freeze()\n            self._run_middlewares =\\\n                self._run_middlewares or subapp._run_middlewares\n\n    @property\n    def debug(self):\n        return self._debug\n\n    def _reg_subapp_signals(self, subapp):\n\n        def reg_handler(signame):\n            subsig = getattr(subapp, signame)\n\n            async def handler(app):\n                await subsig.send(subapp)\n            appsig = getattr(self, signame)\n            appsig.append(handler)\n\n        reg_handler('on_startup')\n        reg_handler('on_shutdown')\n        reg_handler('on_cleanup')\n\n    def add_subapp(self, prefix, subapp):\n        if self.frozen:\n            raise RuntimeError(\n                \"Cannot add sub application to frozen application\")\n        if subapp.frozen:\n            raise RuntimeError(\"Cannot add frozen application\")\n        if prefix.endswith('/'):\n            prefix = prefix[:-1]\n        if prefix in ('', '/'):\n            raise ValueError(\"Prefix cannot be empty\")\n\n        resource = PrefixedSubAppResource(prefix, subapp)\n        self.router.register_resource(resource)\n        self._reg_subapp_signals(subapp)\n        self._subapps.append(subapp)\n        subapp.freeze()\n        if self._loop is not None:\n            subapp._set_loop(self._loop)\n        return resource\n\n    @property\n    def on_response_prepare(self):\n        return self._on_response_prepare\n\n    @property\n    def on_startup(self):\n        return self._on_startup\n\n    @property\n    def on_shutdown(self):\n        return self._on_shutdown\n\n    @property\n    def on_cleanup(self):\n        return self._on_cleanup\n\n    @property\n    def router(self):\n        return self._router\n\n    @property\n    def middlewares(self):\n        return self._middlewares\n\n    def make_handler(self, *,\n                     loop=None,\n                     access_log_class=AccessLogger,\n                     **kwargs):\n\n        if not issubclass(access_log_class, AbstractAccessLogger):\n            raise TypeError(\n                'access_log_class must be subclass of '\n                'aiohttp.abc.AbstractAccessLogger, got {}'.format(\n                    access_log_class))\n\n        self._set_loop(loop)\n        self.freeze()\n\n        kwargs['debug'] = self.debug\n        if self._handler_args:\n            for k, v in self._handler_args.items():\n                kwargs[k] = v\n\n        return Server(self._handle, request_factory=self._make_request,\n                      access_log_class=access_log_class,\n                      loop=self.loop, **kwargs)\n\n    async def startup(self):\n        \"\"\"Causes on_startup signal\n\n        Should be called in the event loop along with the request handler.\n        \"\"\"\n        await self.on_startup.send(self)\n\n    async def shutdown(self):\n        \"\"\"Causes on_shutdown signal\n\n        Should be called before cleanup()\n        \"\"\"\n        await self.on_shutdown.send(self)\n\n    async def cleanup(self):\n        \"\"\"Causes on_cleanup signal\n\n        Should be called after shutdown()\n        \"\"\"\n        await self.on_cleanup.send(self)\n\n    def _make_request(self, message, payload, protocol, writer, task,\n                      _cls=Request):\n        return _cls(\n            message, payload, protocol, writer, task,\n            self._loop,\n            client_max_size=self._client_max_size)\n\n    def _prepare_middleware(self):\n        for m in reversed(self._middlewares):\n            if getattr(m, '__middleware_version__', None) == 1:\n                yield m, True\n            else:\n                warnings.warn('old-style middleware \"{!r}\" deprecated, '\n                              'see #2252'.format(m),\n                              DeprecationWarning, stacklevel=2)\n                yield m, False\n\n        yield _fix_request_current_app(self), True\n\n    async def _handle(self, request):\n        match_info = await self._router.resolve(request)\n        assert isinstance(match_info, AbstractMatchInfo), match_info\n        match_info.add_app(self)\n\n        if __debug__:\n            match_info.freeze()\n\n        resp = None\n        request._match_info = match_info\n        expect = request.headers.get(hdrs.EXPECT)\n        if expect:\n            resp = await match_info.expect_handler(request)\n            await request.writer.drain()\n\n        if resp is None:\n            handler = match_info.handler\n\n            if self._run_middlewares:\n                for app in match_info.apps[::-1]:\n                    for m, new_style in app._middlewares_handlers:\n                        if new_style:\n                            handler = partial(m, handler=handler)\n                        else:\n                            handler = await m(app, handler)\n\n            resp = await handler(request)\n\n        assert isinstance(resp, StreamResponse), \\\n            (\"Handler {!r} should return response instance, \"\n             \"got {!r} [middlewares {!r}]\").format(\n                 match_info.handler, type(resp),\n                 [middleware\n                  for app in match_info.apps\n                  for middleware in app.middlewares])\n        return resp\n\n    def __call__(self):\n        \"\"\"gunicorn compatibility\"\"\"\n        return self\n\n    def __repr__(self):\n        return \"<Application 0x{:x}>\".format(id(self))\n", "path": "aiohttp/web_app.py"}]}