We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Routes that were working on 0.5.5 not working on 0.6.2
Greetings, thanks for the project. 

I am having issues after upgrading where it seems one of my routes is getting converted to a coroutine somewhere and not awaited and then is being passed down all the middleware.

```
Traceback (most recent call last):
  File "../lib/python3.7/site-packages/uvicorn/protocols/http/httptools_impl.py", line 387, in run_asgi
    result = await asgi(self.receive, self.send)
  File "../lib/python3.7/site-packages/uvicorn/middleware/message_logger.py", line 59, in __call__
    await self.inner(self.receive, self.send)
  File "../lib/python3.7/site-packages/uvicorn/middleware/debug.py", line 80, in __call__
    await asgi(receive, self.send)
  File "../lib/python3.7/site-packages/starlette/exceptions.py", line 69, in app
    raise exc from None
  File "../lib/python3.7/site-packages/starlette/exceptions.py", line 61, in app
    await instance(receive, sender)
TypeError: 'coroutine' object is not callable
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `starlette/routing.py`
Content:
```
1 import asyncio
2 import inspect
3 import re
4 import typing
5 from concurrent.futures import ThreadPoolExecutor
6 
7 from starlette.datastructures import URL
8 from starlette.exceptions import HTTPException
9 from starlette.graphql import GraphQLApp
10 from starlette.requests import Request
11 from starlette.responses import PlainTextResponse
12 from starlette.types import ASGIApp, ASGIInstance, Receive, Scope, Send
13 from starlette.websockets import WebSocket, WebSocketClose
14 
15 
16 class NoMatchFound(Exception):
17     pass
18 
19 
20 def request_response(func: typing.Callable) -> ASGIApp:
21     """
22     Takes a function or coroutine `func(request) -> response`,
23     and returns an ASGI application.
24     """
25     is_coroutine = asyncio.iscoroutinefunction(func)
26 
27     def app(scope: Scope) -> ASGIInstance:
28         async def awaitable(receive: Receive, send: Send) -> None:
29             request = Request(scope, receive=receive)
30             if is_coroutine:
31                 response = await func(request)
32             else:
33                 response = func(request)
34             await response(receive, send)
35 
36         return awaitable
37 
38     return app
39 
40 
41 def websocket_session(func: typing.Callable) -> ASGIApp:
42     """
43     Takes a coroutine `func(session)`, and returns an ASGI application.
44     """
45 
46     def app(scope: Scope) -> ASGIInstance:
47         async def awaitable(receive: Receive, send: Send) -> None:
48             session = WebSocket(scope, receive=receive, send=send)
49             await func(session)
50 
51         return awaitable
52 
53     return app
54 
55 
56 def get_name(endpoint: typing.Callable) -> str:
57     if inspect.isfunction(endpoint) or inspect.isclass(endpoint):
58         return endpoint.__name__
59     return endpoint.__class__.__name__
60 
61 
62 def replace_params(path: str, **path_params: str) -> str:
63     for key, value in path_params.items():
64         path = path.replace("{" + key + "}", value)
65     return path
66 
67 
68 class BaseRoute:
69     def matches(self, scope: Scope) -> typing.Tuple[bool, Scope]:
70         raise NotImplementedError()  # pragma: no cover
71 
72     def url_path_for(self, name: str, **path_params: str) -> URL:
73         raise NotImplementedError()  # pragma: no cover
74 
75     def __call__(self, scope: Scope) -> ASGIInstance:
76         raise NotImplementedError()  # pragma: no cover
77 
78 
79 class Route(BaseRoute):
80     def __init__(
81         self, path: str, *, endpoint: typing.Callable, methods: typing.List[str] = None
82     ) -> None:
83         self.path = path
84         self.endpoint = endpoint
85         self.name = get_name(endpoint)
86 
87         if inspect.isfunction(endpoint):
88             self.app = request_response(endpoint)
89             if methods is None:
90                 methods = ["GET"]
91         else:
92             self.app = endpoint
93 
94         self.methods = methods
95         regex = "^" + path + "$"
96         regex = re.sub("{([a-zA-Z_][a-zA-Z0-9_]*)}", r"(?P<\1>[^/]+)", regex)
97         self.path_regex = re.compile(regex)
98         self.param_names = set(self.path_regex.groupindex.keys())
99 
100     def matches(self, scope: Scope) -> typing.Tuple[bool, Scope]:
101         if scope["type"] == "http":
102             match = self.path_regex.match(scope["path"])
103             if match:
104                 path_params = dict(scope.get("path_params", {}))
105                 path_params.update(match.groupdict())
106                 child_scope = dict(scope)
107                 child_scope["path_params"] = path_params
108                 return True, child_scope
109         return False, {}
110 
111     def url_path_for(self, name: str, **path_params: str) -> URL:
112         if name != self.name or self.param_names != set(path_params.keys()):
113             raise NoMatchFound()
114         return URL(scheme="http", path=replace_params(self.path, **path_params))
115 
116     def __call__(self, scope: Scope) -> ASGIInstance:
117         if self.methods and scope["method"] not in self.methods:
118             if "app" in scope:
119                 raise HTTPException(status_code=405)
120             return PlainTextResponse("Method Not Allowed", status_code=405)
121         return self.app(scope)
122 
123     def __eq__(self, other: typing.Any) -> bool:
124         return (
125             isinstance(other, Route)
126             and self.path == other.path
127             and self.endpoint == other.endpoint
128             and self.methods == other.methods
129         )
130 
131 
132 class WebSocketRoute(BaseRoute):
133     def __init__(self, path: str, *, endpoint: typing.Callable) -> None:
134         self.path = path
135         self.endpoint = endpoint
136         self.name = get_name(endpoint)
137 
138         if inspect.isfunction(endpoint):
139             self.app = websocket_session(endpoint)
140         else:
141             self.app = endpoint
142 
143         regex = "^" + path + "$"
144         regex = re.sub("{([a-zA-Z_][a-zA-Z0-9_]*)}", r"(?P<\1>[^/]+)", regex)
145         self.path_regex = re.compile(regex)
146         self.param_names = set(self.path_regex.groupindex.keys())
147 
148     def matches(self, scope: Scope) -> typing.Tuple[bool, Scope]:
149         if scope["type"] == "websocket":
150             match = self.path_regex.match(scope["path"])
151             if match:
152                 path_params = dict(scope.get("path_params", {}))
153                 path_params.update(match.groupdict())
154                 child_scope = dict(scope)
155                 child_scope["path_params"] = path_params
156                 return True, child_scope
157         return False, {}
158 
159     def url_path_for(self, name: str, **path_params: str) -> URL:
160         if name != self.name or self.param_names != set(path_params.keys()):
161             raise NoMatchFound()
162         return URL(scheme="ws", path=replace_params(self.path, **path_params))
163 
164     def __call__(self, scope: Scope) -> ASGIInstance:
165         return self.app(scope)
166 
167     def __eq__(self, other: typing.Any) -> bool:
168         return (
169             isinstance(other, WebSocketRoute)
170             and self.path == other.path
171             and self.endpoint == other.endpoint
172         )
173 
174 
175 class Mount(BaseRoute):
176     def __init__(self, path: str, app: ASGIApp) -> None:
177         self.path = path
178         self.app = app
179         regex = "^" + path
180         regex = re.sub("{([a-zA-Z_][a-zA-Z0-9_]*)}", r"(?P<\1>[^/]*)", regex)
181         self.path_regex = re.compile(regex)
182 
183     @property
184     def routes(self) -> typing.List[BaseRoute]:
185         return getattr(self.app, "routes", None)
186 
187     def matches(self, scope: Scope) -> typing.Tuple[bool, Scope]:
188         match = self.path_regex.match(scope["path"])
189         if match:
190             path_params = dict(scope.get("path_params", {}))
191             path_params.update(match.groupdict())
192             child_scope = dict(scope)
193             child_scope["path_params"] = path_params
194             child_scope["root_path"] = scope.get("root_path", "") + match.string
195             child_scope["path"] = scope["path"][match.span()[1] :]
196             return True, child_scope
197         return False, {}
198 
199     def url_path_for(self, name: str, **path_params: str) -> URL:
200         for route in self.routes or []:
201             try:
202                 url = route.url_path_for(name, **path_params)
203                 return URL(scheme=url.scheme, path=self.path + url.path)
204             except NoMatchFound as exc:
205                 pass
206         raise NoMatchFound()
207 
208     def __call__(self, scope: Scope) -> ASGIInstance:
209         return self.app(scope)
210 
211     def __eq__(self, other: typing.Any) -> bool:
212         return (
213             isinstance(other, Mount)
214             and self.path == other.path
215             and self.app == other.app
216         )
217 
218 
219 class Router:
220     def __init__(
221         self, routes: typing.List[BaseRoute] = None, default: ASGIApp = None
222     ) -> None:
223         self.routes = [] if routes is None else routes
224         self.default = self.not_found if default is None else default
225 
226     def mount(self, path: str, app: ASGIApp) -> None:
227         route = Mount(path, app=app)
228         self.routes.append(route)
229 
230     def add_route(
231         self, path: str, endpoint: typing.Callable, methods: typing.List[str] = None
232     ) -> None:
233         route = Route(path, endpoint=endpoint, methods=methods)
234         self.routes.append(route)
235 
236     def add_graphql_route(
237         self, path: str, schema: typing.Any, executor: typing.Any = None
238     ) -> None:
239         app = GraphQLApp(schema=schema, executor=executor)
240         self.add_route(path, endpoint=app)
241 
242     def add_websocket_route(self, path: str, endpoint: typing.Callable) -> None:
243         route = WebSocketRoute(path, endpoint=endpoint)
244         self.routes.append(route)
245 
246     def route(self, path: str, methods: typing.List[str] = None) -> typing.Callable:
247         def decorator(func: typing.Callable) -> typing.Callable:
248             self.add_route(path, func, methods=methods)
249             return func
250 
251         return decorator
252 
253     def websocket_route(self, path: str) -> typing.Callable:
254         def decorator(func: typing.Callable) -> typing.Callable:
255             self.add_websocket_route(path, func)
256             return func
257 
258         return decorator
259 
260     def not_found(self, scope: Scope) -> ASGIInstance:
261         if scope["type"] == "websocket":
262             return WebSocketClose()
263 
264         # If we're running inside a starlette application then raise an
265         # exception, so that the configurable exception handler can deal with
266         # returning the response. For plain ASGI apps, just return the response.
267         if "app" in scope:
268             raise HTTPException(status_code=404)
269         return PlainTextResponse("Not Found", status_code=404)
270 
271     def url_path_for(self, name: str, **path_params: str) -> URL:
272         for route in self.routes:
273             try:
274                 return route.url_path_for(name, **path_params)
275             except NoMatchFound as exc:
276                 pass
277         raise NoMatchFound()
278 
279     def __call__(self, scope: Scope) -> ASGIInstance:
280         assert scope["type"] in ("http", "websocket")
281 
282         if "router" not in scope:
283             scope["router"] = self
284 
285         for route in self.routes:
286             matched, child_scope = route.matches(scope)
287             if matched:
288                 return route(child_scope)
289         return self.not_found(scope)
290 
291     def __eq__(self, other: typing.Any) -> bool:
292         return isinstance(other, Router) and self.routes == other.routes
293
```
--- 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/starlette/routing.py b/starlette/routing.py
--- a/starlette/routing.py
+++ b/starlette/routing.py
@@ -84,7 +84,7 @@
         self.endpoint = endpoint
         self.name = get_name(endpoint)
 
-        if inspect.isfunction(endpoint):
+        if inspect.isfunction(endpoint) or inspect.ismethod(endpoint):
             self.app = request_response(endpoint)
             if methods is None:
                 methods = ["GET"]
@@ -135,7 +135,7 @@
         self.endpoint = endpoint
         self.name = get_name(endpoint)
 
-        if inspect.isfunction(endpoint):
+        if inspect.isfunction(endpoint) or inspect.ismethod(endpoint):
             self.app = websocket_session(endpoint)
         else:
             self.app = endpoint

{"golden_diff": "diff --git a/starlette/routing.py b/starlette/routing.py\n--- a/starlette/routing.py\n+++ b/starlette/routing.py\n@@ -84,7 +84,7 @@\n         self.endpoint = endpoint\n         self.name = get_name(endpoint)\n \n-        if inspect.isfunction(endpoint):\n+        if inspect.isfunction(endpoint) or inspect.ismethod(endpoint):\n             self.app = request_response(endpoint)\n             if methods is None:\n                 methods = [\"GET\"]\n@@ -135,7 +135,7 @@\n         self.endpoint = endpoint\n         self.name = get_name(endpoint)\n \n-        if inspect.isfunction(endpoint):\n+        if inspect.isfunction(endpoint) or inspect.ismethod(endpoint):\n             self.app = websocket_session(endpoint)\n         else:\n             self.app = endpoint\n", "issue": "Routes that were working on 0.5.5 not working on 0.6.2\nGreetings, thanks for the project. \r\n\r\nI am having issues after upgrading where it seems one of my routes is getting converted to a coroutine somewhere and not awaited and then is being passed down all the middleware.\r\n\r\n```\r\nTraceback (most recent call last):\r\n  File \"../lib/python3.7/site-packages/uvicorn/protocols/http/httptools_impl.py\", line 387, in run_asgi\r\n    result = await asgi(self.receive, self.send)\r\n  File \"../lib/python3.7/site-packages/uvicorn/middleware/message_logger.py\", line 59, in __call__\r\n    await self.inner(self.receive, self.send)\r\n  File \"../lib/python3.7/site-packages/uvicorn/middleware/debug.py\", line 80, in __call__\r\n    await asgi(receive, self.send)\r\n  File \"../lib/python3.7/site-packages/starlette/exceptions.py\", line 69, in app\r\n    raise exc from None\r\n  File \"../lib/python3.7/site-packages/starlette/exceptions.py\", line 61, in app\r\n    await instance(receive, sender)\r\nTypeError: 'coroutine' object is not callable\r\n```\n", "before_files": [{"content": "import asyncio\nimport inspect\nimport re\nimport typing\nfrom concurrent.futures import ThreadPoolExecutor\n\nfrom starlette.datastructures import URL\nfrom starlette.exceptions import HTTPException\nfrom starlette.graphql import GraphQLApp\nfrom starlette.requests import Request\nfrom starlette.responses import PlainTextResponse\nfrom starlette.types import ASGIApp, ASGIInstance, Receive, Scope, Send\nfrom starlette.websockets import WebSocket, WebSocketClose\n\n\nclass NoMatchFound(Exception):\n    pass\n\n\ndef request_response(func: typing.Callable) -> ASGIApp:\n    \"\"\"\n    Takes a function or coroutine `func(request) -> response`,\n    and returns an ASGI application.\n    \"\"\"\n    is_coroutine = asyncio.iscoroutinefunction(func)\n\n    def app(scope: Scope) -> ASGIInstance:\n        async def awaitable(receive: Receive, send: Send) -> None:\n            request = Request(scope, receive=receive)\n            if is_coroutine:\n                response = await func(request)\n            else:\n                response = func(request)\n            await response(receive, send)\n\n        return awaitable\n\n    return app\n\n\ndef websocket_session(func: typing.Callable) -> ASGIApp:\n    \"\"\"\n    Takes a coroutine `func(session)`, and returns an ASGI application.\n    \"\"\"\n\n    def app(scope: Scope) -> ASGIInstance:\n        async def awaitable(receive: Receive, send: Send) -> None:\n            session = WebSocket(scope, receive=receive, send=send)\n            await func(session)\n\n        return awaitable\n\n    return app\n\n\ndef get_name(endpoint: typing.Callable) -> str:\n    if inspect.isfunction(endpoint) or inspect.isclass(endpoint):\n        return endpoint.__name__\n    return endpoint.__class__.__name__\n\n\ndef replace_params(path: str, **path_params: str) -> str:\n    for key, value in path_params.items():\n        path = path.replace(\"{\" + key + \"}\", value)\n    return path\n\n\nclass BaseRoute:\n    def matches(self, scope: Scope) -> typing.Tuple[bool, Scope]:\n        raise NotImplementedError()  # pragma: no cover\n\n    def url_path_for(self, name: str, **path_params: str) -> URL:\n        raise NotImplementedError()  # pragma: no cover\n\n    def __call__(self, scope: Scope) -> ASGIInstance:\n        raise NotImplementedError()  # pragma: no cover\n\n\nclass Route(BaseRoute):\n    def __init__(\n        self, path: str, *, endpoint: typing.Callable, methods: typing.List[str] = None\n    ) -> None:\n        self.path = path\n        self.endpoint = endpoint\n        self.name = get_name(endpoint)\n\n        if inspect.isfunction(endpoint):\n            self.app = request_response(endpoint)\n            if methods is None:\n                methods = [\"GET\"]\n        else:\n            self.app = endpoint\n\n        self.methods = methods\n        regex = \"^\" + path + \"$\"\n        regex = re.sub(\"{([a-zA-Z_][a-zA-Z0-9_]*)}\", r\"(?P<\\1>[^/]+)\", regex)\n        self.path_regex = re.compile(regex)\n        self.param_names = set(self.path_regex.groupindex.keys())\n\n    def matches(self, scope: Scope) -> typing.Tuple[bool, Scope]:\n        if scope[\"type\"] == \"http\":\n            match = self.path_regex.match(scope[\"path\"])\n            if match:\n                path_params = dict(scope.get(\"path_params\", {}))\n                path_params.update(match.groupdict())\n                child_scope = dict(scope)\n                child_scope[\"path_params\"] = path_params\n                return True, child_scope\n        return False, {}\n\n    def url_path_for(self, name: str, **path_params: str) -> URL:\n        if name != self.name or self.param_names != set(path_params.keys()):\n            raise NoMatchFound()\n        return URL(scheme=\"http\", path=replace_params(self.path, **path_params))\n\n    def __call__(self, scope: Scope) -> ASGIInstance:\n        if self.methods and scope[\"method\"] not in self.methods:\n            if \"app\" in scope:\n                raise HTTPException(status_code=405)\n            return PlainTextResponse(\"Method Not Allowed\", status_code=405)\n        return self.app(scope)\n\n    def __eq__(self, other: typing.Any) -> bool:\n        return (\n            isinstance(other, Route)\n            and self.path == other.path\n            and self.endpoint == other.endpoint\n            and self.methods == other.methods\n        )\n\n\nclass WebSocketRoute(BaseRoute):\n    def __init__(self, path: str, *, endpoint: typing.Callable) -> None:\n        self.path = path\n        self.endpoint = endpoint\n        self.name = get_name(endpoint)\n\n        if inspect.isfunction(endpoint):\n            self.app = websocket_session(endpoint)\n        else:\n            self.app = endpoint\n\n        regex = \"^\" + path + \"$\"\n        regex = re.sub(\"{([a-zA-Z_][a-zA-Z0-9_]*)}\", r\"(?P<\\1>[^/]+)\", regex)\n        self.path_regex = re.compile(regex)\n        self.param_names = set(self.path_regex.groupindex.keys())\n\n    def matches(self, scope: Scope) -> typing.Tuple[bool, Scope]:\n        if scope[\"type\"] == \"websocket\":\n            match = self.path_regex.match(scope[\"path\"])\n            if match:\n                path_params = dict(scope.get(\"path_params\", {}))\n                path_params.update(match.groupdict())\n                child_scope = dict(scope)\n                child_scope[\"path_params\"] = path_params\n                return True, child_scope\n        return False, {}\n\n    def url_path_for(self, name: str, **path_params: str) -> URL:\n        if name != self.name or self.param_names != set(path_params.keys()):\n            raise NoMatchFound()\n        return URL(scheme=\"ws\", path=replace_params(self.path, **path_params))\n\n    def __call__(self, scope: Scope) -> ASGIInstance:\n        return self.app(scope)\n\n    def __eq__(self, other: typing.Any) -> bool:\n        return (\n            isinstance(other, WebSocketRoute)\n            and self.path == other.path\n            and self.endpoint == other.endpoint\n        )\n\n\nclass Mount(BaseRoute):\n    def __init__(self, path: str, app: ASGIApp) -> None:\n        self.path = path\n        self.app = app\n        regex = \"^\" + path\n        regex = re.sub(\"{([a-zA-Z_][a-zA-Z0-9_]*)}\", r\"(?P<\\1>[^/]*)\", regex)\n        self.path_regex = re.compile(regex)\n\n    @property\n    def routes(self) -> typing.List[BaseRoute]:\n        return getattr(self.app, \"routes\", None)\n\n    def matches(self, scope: Scope) -> typing.Tuple[bool, Scope]:\n        match = self.path_regex.match(scope[\"path\"])\n        if match:\n            path_params = dict(scope.get(\"path_params\", {}))\n            path_params.update(match.groupdict())\n            child_scope = dict(scope)\n            child_scope[\"path_params\"] = path_params\n            child_scope[\"root_path\"] = scope.get(\"root_path\", \"\") + match.string\n            child_scope[\"path\"] = scope[\"path\"][match.span()[1] :]\n            return True, child_scope\n        return False, {}\n\n    def url_path_for(self, name: str, **path_params: str) -> URL:\n        for route in self.routes or []:\n            try:\n                url = route.url_path_for(name, **path_params)\n                return URL(scheme=url.scheme, path=self.path + url.path)\n            except NoMatchFound as exc:\n                pass\n        raise NoMatchFound()\n\n    def __call__(self, scope: Scope) -> ASGIInstance:\n        return self.app(scope)\n\n    def __eq__(self, other: typing.Any) -> bool:\n        return (\n            isinstance(other, Mount)\n            and self.path == other.path\n            and self.app == other.app\n        )\n\n\nclass Router:\n    def __init__(\n        self, routes: typing.List[BaseRoute] = None, default: ASGIApp = None\n    ) -> None:\n        self.routes = [] if routes is None else routes\n        self.default = self.not_found if default is None else default\n\n    def mount(self, path: str, app: ASGIApp) -> None:\n        route = Mount(path, app=app)\n        self.routes.append(route)\n\n    def add_route(\n        self, path: str, endpoint: typing.Callable, methods: typing.List[str] = None\n    ) -> None:\n        route = Route(path, endpoint=endpoint, methods=methods)\n        self.routes.append(route)\n\n    def add_graphql_route(\n        self, path: str, schema: typing.Any, executor: typing.Any = None\n    ) -> None:\n        app = GraphQLApp(schema=schema, executor=executor)\n        self.add_route(path, endpoint=app)\n\n    def add_websocket_route(self, path: str, endpoint: typing.Callable) -> None:\n        route = WebSocketRoute(path, endpoint=endpoint)\n        self.routes.append(route)\n\n    def route(self, path: str, methods: typing.List[str] = None) -> typing.Callable:\n        def decorator(func: typing.Callable) -> typing.Callable:\n            self.add_route(path, func, methods=methods)\n            return func\n\n        return decorator\n\n    def websocket_route(self, path: str) -> typing.Callable:\n        def decorator(func: typing.Callable) -> typing.Callable:\n            self.add_websocket_route(path, func)\n            return func\n\n        return decorator\n\n    def not_found(self, scope: Scope) -> ASGIInstance:\n        if scope[\"type\"] == \"websocket\":\n            return WebSocketClose()\n\n        # If we're running inside a starlette application then raise an\n        # exception, so that the configurable exception handler can deal with\n        # returning the response. For plain ASGI apps, just return the response.\n        if \"app\" in scope:\n            raise HTTPException(status_code=404)\n        return PlainTextResponse(\"Not Found\", status_code=404)\n\n    def url_path_for(self, name: str, **path_params: str) -> URL:\n        for route in self.routes:\n            try:\n                return route.url_path_for(name, **path_params)\n            except NoMatchFound as exc:\n                pass\n        raise NoMatchFound()\n\n    def __call__(self, scope: Scope) -> ASGIInstance:\n        assert scope[\"type\"] in (\"http\", \"websocket\")\n\n        if \"router\" not in scope:\n            scope[\"router\"] = self\n\n        for route in self.routes:\n            matched, child_scope = route.matches(scope)\n            if matched:\n                return route(child_scope)\n        return self.not_found(scope)\n\n    def __eq__(self, other: typing.Any) -> bool:\n        return isinstance(other, Router) and self.routes == other.routes\n", "path": "starlette/routing.py"}], "after_files": [{"content": "import asyncio\nimport inspect\nimport re\nimport typing\nfrom concurrent.futures import ThreadPoolExecutor\n\nfrom starlette.datastructures import URL\nfrom starlette.exceptions import HTTPException\nfrom starlette.graphql import GraphQLApp\nfrom starlette.requests import Request\nfrom starlette.responses import PlainTextResponse\nfrom starlette.types import ASGIApp, ASGIInstance, Receive, Scope, Send\nfrom starlette.websockets import WebSocket, WebSocketClose\n\n\nclass NoMatchFound(Exception):\n    pass\n\n\ndef request_response(func: typing.Callable) -> ASGIApp:\n    \"\"\"\n    Takes a function or coroutine `func(request) -> response`,\n    and returns an ASGI application.\n    \"\"\"\n    is_coroutine = asyncio.iscoroutinefunction(func)\n\n    def app(scope: Scope) -> ASGIInstance:\n        async def awaitable(receive: Receive, send: Send) -> None:\n            request = Request(scope, receive=receive)\n            if is_coroutine:\n                response = await func(request)\n            else:\n                response = func(request)\n            await response(receive, send)\n\n        return awaitable\n\n    return app\n\n\ndef websocket_session(func: typing.Callable) -> ASGIApp:\n    \"\"\"\n    Takes a coroutine `func(session)`, and returns an ASGI application.\n    \"\"\"\n\n    def app(scope: Scope) -> ASGIInstance:\n        async def awaitable(receive: Receive, send: Send) -> None:\n            session = WebSocket(scope, receive=receive, send=send)\n            await func(session)\n\n        return awaitable\n\n    return app\n\n\ndef get_name(endpoint: typing.Callable) -> str:\n    if inspect.isfunction(endpoint) or inspect.isclass(endpoint):\n        return endpoint.__name__\n    return endpoint.__class__.__name__\n\n\ndef replace_params(path: str, **path_params: str) -> str:\n    for key, value in path_params.items():\n        path = path.replace(\"{\" + key + \"}\", value)\n    return path\n\n\nclass BaseRoute:\n    def matches(self, scope: Scope) -> typing.Tuple[bool, Scope]:\n        raise NotImplementedError()  # pragma: no cover\n\n    def url_path_for(self, name: str, **path_params: str) -> URL:\n        raise NotImplementedError()  # pragma: no cover\n\n    def __call__(self, scope: Scope) -> ASGIInstance:\n        raise NotImplementedError()  # pragma: no cover\n\n\nclass Route(BaseRoute):\n    def __init__(\n        self, path: str, *, endpoint: typing.Callable, methods: typing.List[str] = None\n    ) -> None:\n        self.path = path\n        self.endpoint = endpoint\n        self.name = get_name(endpoint)\n\n        if inspect.isfunction(endpoint) or inspect.ismethod(endpoint):\n            self.app = request_response(endpoint)\n            if methods is None:\n                methods = [\"GET\"]\n        else:\n            self.app = endpoint\n\n        self.methods = methods\n        regex = \"^\" + path + \"$\"\n        regex = re.sub(\"{([a-zA-Z_][a-zA-Z0-9_]*)}\", r\"(?P<\\1>[^/]+)\", regex)\n        self.path_regex = re.compile(regex)\n        self.param_names = set(self.path_regex.groupindex.keys())\n\n    def matches(self, scope: Scope) -> typing.Tuple[bool, Scope]:\n        if scope[\"type\"] == \"http\":\n            match = self.path_regex.match(scope[\"path\"])\n            if match:\n                path_params = dict(scope.get(\"path_params\", {}))\n                path_params.update(match.groupdict())\n                child_scope = dict(scope)\n                child_scope[\"path_params\"] = path_params\n                return True, child_scope\n        return False, {}\n\n    def url_path_for(self, name: str, **path_params: str) -> URL:\n        if name != self.name or self.param_names != set(path_params.keys()):\n            raise NoMatchFound()\n        return URL(scheme=\"http\", path=replace_params(self.path, **path_params))\n\n    def __call__(self, scope: Scope) -> ASGIInstance:\n        if self.methods and scope[\"method\"] not in self.methods:\n            if \"app\" in scope:\n                raise HTTPException(status_code=405)\n            return PlainTextResponse(\"Method Not Allowed\", status_code=405)\n        return self.app(scope)\n\n    def __eq__(self, other: typing.Any) -> bool:\n        return (\n            isinstance(other, Route)\n            and self.path == other.path\n            and self.endpoint == other.endpoint\n            and self.methods == other.methods\n        )\n\n\nclass WebSocketRoute(BaseRoute):\n    def __init__(self, path: str, *, endpoint: typing.Callable) -> None:\n        self.path = path\n        self.endpoint = endpoint\n        self.name = get_name(endpoint)\n\n        if inspect.isfunction(endpoint) or inspect.ismethod(endpoint):\n            self.app = websocket_session(endpoint)\n        else:\n            self.app = endpoint\n\n        regex = \"^\" + path + \"$\"\n        regex = re.sub(\"{([a-zA-Z_][a-zA-Z0-9_]*)}\", r\"(?P<\\1>[^/]+)\", regex)\n        self.path_regex = re.compile(regex)\n        self.param_names = set(self.path_regex.groupindex.keys())\n\n    def matches(self, scope: Scope) -> typing.Tuple[bool, Scope]:\n        if scope[\"type\"] == \"websocket\":\n            match = self.path_regex.match(scope[\"path\"])\n            if match:\n                path_params = dict(scope.get(\"path_params\", {}))\n                path_params.update(match.groupdict())\n                child_scope = dict(scope)\n                child_scope[\"path_params\"] = path_params\n                return True, child_scope\n        return False, {}\n\n    def url_path_for(self, name: str, **path_params: str) -> URL:\n        if name != self.name or self.param_names != set(path_params.keys()):\n            raise NoMatchFound()\n        return URL(scheme=\"ws\", path=replace_params(self.path, **path_params))\n\n    def __call__(self, scope: Scope) -> ASGIInstance:\n        return self.app(scope)\n\n    def __eq__(self, other: typing.Any) -> bool:\n        return (\n            isinstance(other, WebSocketRoute)\n            and self.path == other.path\n            and self.endpoint == other.endpoint\n        )\n\n\nclass Mount(BaseRoute):\n    def __init__(self, path: str, app: ASGIApp) -> None:\n        self.path = path\n        self.app = app\n        regex = \"^\" + path\n        regex = re.sub(\"{([a-zA-Z_][a-zA-Z0-9_]*)}\", r\"(?P<\\1>[^/]*)\", regex)\n        self.path_regex = re.compile(regex)\n\n    @property\n    def routes(self) -> typing.List[BaseRoute]:\n        return getattr(self.app, \"routes\", None)\n\n    def matches(self, scope: Scope) -> typing.Tuple[bool, Scope]:\n        match = self.path_regex.match(scope[\"path\"])\n        if match:\n            path_params = dict(scope.get(\"path_params\", {}))\n            path_params.update(match.groupdict())\n            child_scope = dict(scope)\n            child_scope[\"path_params\"] = path_params\n            child_scope[\"root_path\"] = scope.get(\"root_path\", \"\") + match.string\n            child_scope[\"path\"] = scope[\"path\"][match.span()[1] :]\n            return True, child_scope\n        return False, {}\n\n    def url_path_for(self, name: str, **path_params: str) -> URL:\n        for route in self.routes or []:\n            try:\n                url = route.url_path_for(name, **path_params)\n                return URL(scheme=url.scheme, path=self.path + url.path)\n            except NoMatchFound as exc:\n                pass\n        raise NoMatchFound()\n\n    def __call__(self, scope: Scope) -> ASGIInstance:\n        return self.app(scope)\n\n    def __eq__(self, other: typing.Any) -> bool:\n        return (\n            isinstance(other, Mount)\n            and self.path == other.path\n            and self.app == other.app\n        )\n\n\nclass Router:\n    def __init__(\n        self, routes: typing.List[BaseRoute] = None, default: ASGIApp = None\n    ) -> None:\n        self.routes = [] if routes is None else routes\n        self.default = self.not_found if default is None else default\n\n    def mount(self, path: str, app: ASGIApp) -> None:\n        route = Mount(path, app=app)\n        self.routes.append(route)\n\n    def add_route(\n        self, path: str, endpoint: typing.Callable, methods: typing.List[str] = None\n    ) -> None:\n        route = Route(path, endpoint=endpoint, methods=methods)\n        self.routes.append(route)\n\n    def add_graphql_route(\n        self, path: str, schema: typing.Any, executor: typing.Any = None\n    ) -> None:\n        app = GraphQLApp(schema=schema, executor=executor)\n        self.add_route(path, endpoint=app)\n\n    def add_websocket_route(self, path: str, endpoint: typing.Callable) -> None:\n        route = WebSocketRoute(path, endpoint=endpoint)\n        self.routes.append(route)\n\n    def route(self, path: str, methods: typing.List[str] = None) -> typing.Callable:\n        def decorator(func: typing.Callable) -> typing.Callable:\n            self.add_route(path, func, methods=methods)\n            return func\n\n        return decorator\n\n    def websocket_route(self, path: str) -> typing.Callable:\n        def decorator(func: typing.Callable) -> typing.Callable:\n            self.add_websocket_route(path, func)\n            return func\n\n        return decorator\n\n    def not_found(self, scope: Scope) -> ASGIInstance:\n        if scope[\"type\"] == \"websocket\":\n            return WebSocketClose()\n\n        # If we're running inside a starlette application then raise an\n        # exception, so that the configurable exception handler can deal with\n        # returning the response. For plain ASGI apps, just return the response.\n        if \"app\" in scope:\n            raise HTTPException(status_code=404)\n        return PlainTextResponse(\"Not Found\", status_code=404)\n\n    def url_path_for(self, name: str, **path_params: str) -> URL:\n        for route in self.routes:\n            try:\n                return route.url_path_for(name, **path_params)\n            except NoMatchFound as exc:\n                pass\n        raise NoMatchFound()\n\n    def __call__(self, scope: Scope) -> ASGIInstance:\n        assert scope[\"type\"] in (\"http\", \"websocket\")\n\n        if \"router\" not in scope:\n            scope[\"router\"] = self\n\n        for route in self.routes:\n            matched, child_scope = route.matches(scope)\n            if matched:\n                return route(child_scope)\n        return self.not_found(scope)\n\n    def __eq__(self, other: typing.Any) -> bool:\n        return isinstance(other, Router) and self.routes == other.routes\n", "path": "starlette/routing.py"}]}