We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
mypy complains about `exception_handlers` dict with `HTTPException` key
### Checklist

<!-- Please make sure you check all these items before submitting your bug report. -->

- [x] The bug is reproducible against the latest release and/or `master`.
- [x] There are no similar issues or pull requests to fix it yet.

Related, but not the same:
* #1034 
* #1139 
* #949

### Describe the bug

<!-- A clear and concise description of what the bug is. -->

### To reproduce

Given an example.py: 

```python
from starlette.applications import Starlette
from starlette.exceptions import HTTPException
from starlette.requests import Request
from starlette.responses import Response
from starlette.routing import Route

def handle_http_exception(request: Request, exc: HTTPException) -> Response:
    return Response('foo')


exception_handlers = {
    HTTPException: handle_http_exception
}
app = Starlette(exception_handlers=exception_handlers)
```

### Expected behavior

Mypy does not present an error.

### Actual behavior

```console
$ mypy example.py
example.py:14: error: Argument "exception_handlers" to "Starlette" has incompatible type "Dict[Type[HTTPException], Callable[[Request, HTTPException], Response]]"; expected "Optional[Dict[Union[int, Type[Exception]], Callable[..., Any]]]"
Found 1 error in 1 file (checked 1 source file)
```

### Debugging material

None

### Environment

- OS: Debian (`Linux ... 4.19.0-14-amd64 #1 SMP Debian 4.19.171-2 (2021-01-30) x86_64 GNU/Linux`)
- Python version: `Python 3.9.1`
- Starlette version: `starlette==0.14.2`

### Additional context

For propriety:

https://github.com/encode/starlette/blob/master/docs/exceptions.md#L42

https://github.com/encode/starlette/blob/ed73b97c9b8f4aa527eed88032c04ce9fe109a3c/starlette/applications.py#L44

I think this is a Starlette issue and not a mypy issue; apologies if I'm wrong here.

--- 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/exceptions.py`
Content:
```
1 import asyncio
2 import http
3 import typing
4 
5 from starlette.concurrency import run_in_threadpool
6 from starlette.requests import Request
7 from starlette.responses import PlainTextResponse, Response
8 from starlette.types import ASGIApp, Message, Receive, Scope, Send
9 
10 
11 class HTTPException(Exception):
12     def __init__(self, status_code: int, detail: str = None) -> None:
13         if detail is None:
14             detail = http.HTTPStatus(status_code).phrase
15         self.status_code = status_code
16         self.detail = detail
17 
18     def __repr__(self) -> str:
19         class_name = self.__class__.__name__
20         return f"{class_name}(status_code={self.status_code!r}, detail={self.detail!r})"
21 
22 
23 class ExceptionMiddleware:
24     def __init__(
25         self, app: ASGIApp, handlers: dict = None, debug: bool = False
26     ) -> None:
27         self.app = app
28         self.debug = debug  # TODO: We ought to handle 404 cases if debug is set.
29         self._status_handlers: typing.Dict[int, typing.Callable] = {}
30         self._exception_handlers: typing.Dict[
31             typing.Type[Exception], typing.Callable
32         ] = {HTTPException: self.http_exception}
33         if handlers is not None:
34             for key, value in handlers.items():
35                 self.add_exception_handler(key, value)
36 
37     def add_exception_handler(
38         self,
39         exc_class_or_status_code: typing.Union[int, typing.Type[Exception]],
40         handler: typing.Callable,
41     ) -> None:
42         if isinstance(exc_class_or_status_code, int):
43             self._status_handlers[exc_class_or_status_code] = handler
44         else:
45             assert issubclass(exc_class_or_status_code, Exception)
46             self._exception_handlers[exc_class_or_status_code] = handler
47 
48     def _lookup_exception_handler(
49         self, exc: Exception
50     ) -> typing.Optional[typing.Callable]:
51         for cls in type(exc).__mro__:
52             if cls in self._exception_handlers:
53                 return self._exception_handlers[cls]
54         return None
55 
56     async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
57         if scope["type"] != "http":
58             await self.app(scope, receive, send)
59             return
60 
61         response_started = False
62 
63         async def sender(message: Message) -> None:
64             nonlocal response_started
65 
66             if message["type"] == "http.response.start":
67                 response_started = True
68             await send(message)
69 
70         try:
71             await self.app(scope, receive, sender)
72         except Exception as exc:
73             handler = None
74 
75             if isinstance(exc, HTTPException):
76                 handler = self._status_handlers.get(exc.status_code)
77 
78             if handler is None:
79                 handler = self._lookup_exception_handler(exc)
80 
81             if handler is None:
82                 raise exc
83 
84             if response_started:
85                 msg = "Caught handled exception, but response already started."
86                 raise RuntimeError(msg) from exc
87 
88             request = Request(scope, receive=receive)
89             if asyncio.iscoroutinefunction(handler):
90                 response = await handler(request, exc)
91             else:
92                 response = await run_in_threadpool(handler, request, exc)
93             await response(scope, receive, sender)
94 
95     def http_exception(self, request: Request, exc: HTTPException) -> Response:
96         if exc.status_code in {204, 304}:
97             return Response(b"", status_code=exc.status_code)
98         return PlainTextResponse(exc.detail, status_code=exc.status_code)
99
```

Path: `starlette/applications.py`
Content:
```
1 import typing
2 
3 from starlette.datastructures import State, URLPath
4 from starlette.exceptions import ExceptionMiddleware
5 from starlette.middleware import Middleware
6 from starlette.middleware.base import BaseHTTPMiddleware
7 from starlette.middleware.errors import ServerErrorMiddleware
8 from starlette.routing import BaseRoute, Router
9 from starlette.types import ASGIApp, Receive, Scope, Send
10 
11 
12 class Starlette:
13     """
14     Creates an application instance.
15 
16     **Parameters:**
17 
18     * **debug** - Boolean indicating if debug tracebacks should be returned on errors.
19     * **routes** - A list of routes to serve incoming HTTP and WebSocket requests.
20     * **middleware** - A list of middleware to run for every request. A starlette
21     application will always automatically include two middleware classes.
22     `ServerErrorMiddleware` is added as the very outermost middleware, to handle
23     any uncaught errors occurring anywhere in the entire stack.
24     `ExceptionMiddleware` is added as the very innermost middleware, to deal
25     with handled exception cases occurring in the routing or endpoints.
26     * **exception_handlers** - A dictionary mapping either integer status codes,
27     or exception class types onto callables which handle the exceptions.
28     Exception handler callables should be of the form
29     `handler(request, exc) -> response` and may be be either standard functions, or
30     async functions.
31     * **on_startup** - A list of callables to run on application startup.
32     Startup handler callables do not take any arguments, and may be be either
33     standard functions, or async functions.
34     * **on_shutdown** - A list of callables to run on application shutdown.
35     Shutdown handler callables do not take any arguments, and may be be either
36     standard functions, or async functions.
37     """
38 
39     def __init__(
40         self,
41         debug: bool = False,
42         routes: typing.Sequence[BaseRoute] = None,
43         middleware: typing.Sequence[Middleware] = None,
44         exception_handlers: typing.Dict[
45             typing.Union[int, typing.Type[Exception]], typing.Callable
46         ] = None,
47         on_startup: typing.Sequence[typing.Callable] = None,
48         on_shutdown: typing.Sequence[typing.Callable] = None,
49         lifespan: typing.Callable[["Starlette"], typing.AsyncContextManager] = None,
50     ) -> None:
51         # The lifespan context function is a newer style that replaces
52         # on_startup / on_shutdown handlers. Use one or the other, not both.
53         assert lifespan is None or (
54             on_startup is None and on_shutdown is None
55         ), "Use either 'lifespan' or 'on_startup'/'on_shutdown', not both."
56 
57         self._debug = debug
58         self.state = State()
59         self.router = Router(
60             routes, on_startup=on_startup, on_shutdown=on_shutdown, lifespan=lifespan
61         )
62         self.exception_handlers = (
63             {} if exception_handlers is None else dict(exception_handlers)
64         )
65         self.user_middleware = [] if middleware is None else list(middleware)
66         self.middleware_stack = self.build_middleware_stack()
67 
68     def build_middleware_stack(self) -> ASGIApp:
69         debug = self.debug
70         error_handler = None
71         exception_handlers = {}
72 
73         for key, value in self.exception_handlers.items():
74             if key in (500, Exception):
75                 error_handler = value
76             else:
77                 exception_handlers[key] = value
78 
79         middleware = (
80             [Middleware(ServerErrorMiddleware, handler=error_handler, debug=debug)]
81             + self.user_middleware
82             + [
83                 Middleware(
84                     ExceptionMiddleware, handlers=exception_handlers, debug=debug
85                 )
86             ]
87         )
88 
89         app = self.router
90         for cls, options in reversed(middleware):
91             app = cls(app=app, **options)
92         return app
93 
94     @property
95     def routes(self) -> typing.List[BaseRoute]:
96         return self.router.routes
97 
98     @property
99     def debug(self) -> bool:
100         return self._debug
101 
102     @debug.setter
103     def debug(self, value: bool) -> None:
104         self._debug = value
105         self.middleware_stack = self.build_middleware_stack()
106 
107     def url_path_for(self, name: str, **path_params: typing.Any) -> URLPath:
108         return self.router.url_path_for(name, **path_params)
109 
110     async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
111         scope["app"] = self
112         await self.middleware_stack(scope, receive, send)
113 
114     # The following usages are now discouraged in favour of configuration
115     #  during Starlette.__init__(...)
116     def on_event(self, event_type: str) -> typing.Callable:
117         return self.router.on_event(event_type)
118 
119     def mount(self, path: str, app: ASGIApp, name: str = None) -> None:
120         self.router.mount(path, app=app, name=name)
121 
122     def host(self, host: str, app: ASGIApp, name: str = None) -> None:
123         self.router.host(host, app=app, name=name)
124 
125     def add_middleware(self, middleware_class: type, **options: typing.Any) -> None:
126         self.user_middleware.insert(0, Middleware(middleware_class, **options))
127         self.middleware_stack = self.build_middleware_stack()
128 
129     def add_exception_handler(
130         self,
131         exc_class_or_status_code: typing.Union[int, typing.Type[Exception]],
132         handler: typing.Callable,
133     ) -> None:
134         self.exception_handlers[exc_class_or_status_code] = handler
135         self.middleware_stack = self.build_middleware_stack()
136 
137     def add_event_handler(self, event_type: str, func: typing.Callable) -> None:
138         self.router.add_event_handler(event_type, func)
139 
140     def add_route(
141         self,
142         path: str,
143         route: typing.Callable,
144         methods: typing.List[str] = None,
145         name: str = None,
146         include_in_schema: bool = True,
147     ) -> None:
148         self.router.add_route(
149             path, route, methods=methods, name=name, include_in_schema=include_in_schema
150         )
151 
152     def add_websocket_route(
153         self, path: str, route: typing.Callable, name: str = None
154     ) -> None:
155         self.router.add_websocket_route(path, route, name=name)
156 
157     def exception_handler(
158         self, exc_class_or_status_code: typing.Union[int, typing.Type[Exception]]
159     ) -> typing.Callable:
160         def decorator(func: typing.Callable) -> typing.Callable:
161             self.add_exception_handler(exc_class_or_status_code, func)
162             return func
163 
164         return decorator
165 
166     def route(
167         self,
168         path: str,
169         methods: typing.List[str] = None,
170         name: str = None,
171         include_in_schema: bool = True,
172     ) -> typing.Callable:
173         def decorator(func: typing.Callable) -> typing.Callable:
174             self.router.add_route(
175                 path,
176                 func,
177                 methods=methods,
178                 name=name,
179                 include_in_schema=include_in_schema,
180             )
181             return func
182 
183         return decorator
184 
185     def websocket_route(self, path: str, name: str = None) -> typing.Callable:
186         def decorator(func: typing.Callable) -> typing.Callable:
187             self.router.add_websocket_route(path, func, name=name)
188             return func
189 
190         return decorator
191 
192     def middleware(self, middleware_type: str) -> typing.Callable:
193         assert (
194             middleware_type == "http"
195         ), 'Currently only middleware("http") is supported.'
196 
197         def decorator(func: typing.Callable) -> typing.Callable:
198             self.add_middleware(BaseHTTPMiddleware, dispatch=func)
199             return func
200 
201         return decorator
202
```
--- 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/applications.py b/starlette/applications.py
--- a/starlette/applications.py
+++ b/starlette/applications.py
@@ -5,6 +5,8 @@
 from starlette.middleware import Middleware
 from starlette.middleware.base import BaseHTTPMiddleware
 from starlette.middleware.errors import ServerErrorMiddleware
+from starlette.requests import Request
+from starlette.responses import Response
 from starlette.routing import BaseRoute, Router
 from starlette.types import ASGIApp, Receive, Scope, Send
 
@@ -23,7 +25,7 @@
     any uncaught errors occurring anywhere in the entire stack.
     `ExceptionMiddleware` is added as the very innermost middleware, to deal
     with handled exception cases occurring in the routing or endpoints.
-    * **exception_handlers** - A dictionary mapping either integer status codes,
+    * **exception_handlers** - A mapping of either integer status codes,
     or exception class types onto callables which handle the exceptions.
     Exception handler callables should be of the form
     `handler(request, exc) -> response` and may be be either standard functions, or
@@ -41,8 +43,8 @@
         debug: bool = False,
         routes: typing.Sequence[BaseRoute] = None,
         middleware: typing.Sequence[Middleware] = None,
-        exception_handlers: typing.Dict[
-            typing.Union[int, typing.Type[Exception]], typing.Callable
+        exception_handlers: typing.Mapping[
+            typing.Any, typing.Callable[[Request, Exception], Response]
         ] = None,
         on_startup: typing.Sequence[typing.Callable] = None,
         on_shutdown: typing.Sequence[typing.Callable] = None,
@@ -68,7 +70,9 @@
     def build_middleware_stack(self) -> ASGIApp:
         debug = self.debug
         error_handler = None
-        exception_handlers = {}
+        exception_handlers: typing.Dict[
+            typing.Any, typing.Callable[[Request, Exception], Response]
+        ] = {}
 
         for key, value in self.exception_handlers.items():
             if key in (500, Exception):
diff --git a/starlette/exceptions.py b/starlette/exceptions.py
--- a/starlette/exceptions.py
+++ b/starlette/exceptions.py
@@ -22,7 +22,12 @@
 
 class ExceptionMiddleware:
     def __init__(
-        self, app: ASGIApp, handlers: dict = None, debug: bool = False
+        self,
+        app: ASGIApp,
+        handlers: typing.Mapping[
+            typing.Any, typing.Callable[[Request, Exception], Response]
+        ] = None,
+        debug: bool = False,
     ) -> None:
         self.app = app
         self.debug = debug  # TODO: We ought to handle 404 cases if debug is set.
@@ -37,7 +42,7 @@
     def add_exception_handler(
         self,
         exc_class_or_status_code: typing.Union[int, typing.Type[Exception]],
-        handler: typing.Callable,
+        handler: typing.Callable[[Request, Exception], Response],
     ) -> None:
         if isinstance(exc_class_or_status_code, int):
             self._status_handlers[exc_class_or_status_code] = handler

{"golden_diff": "diff --git a/starlette/applications.py b/starlette/applications.py\n--- a/starlette/applications.py\n+++ b/starlette/applications.py\n@@ -5,6 +5,8 @@\n from starlette.middleware import Middleware\n from starlette.middleware.base import BaseHTTPMiddleware\n from starlette.middleware.errors import ServerErrorMiddleware\n+from starlette.requests import Request\n+from starlette.responses import Response\n from starlette.routing import BaseRoute, Router\n from starlette.types import ASGIApp, Receive, Scope, Send\n \n@@ -23,7 +25,7 @@\n     any uncaught errors occurring anywhere in the entire stack.\n     `ExceptionMiddleware` is added as the very innermost middleware, to deal\n     with handled exception cases occurring in the routing or endpoints.\n-    * **exception_handlers** - A dictionary mapping either integer status codes,\n+    * **exception_handlers** - A mapping of either integer status codes,\n     or exception class types onto callables which handle the exceptions.\n     Exception handler callables should be of the form\n     `handler(request, exc) -> response` and may be be either standard functions, or\n@@ -41,8 +43,8 @@\n         debug: bool = False,\n         routes: typing.Sequence[BaseRoute] = None,\n         middleware: typing.Sequence[Middleware] = None,\n-        exception_handlers: typing.Dict[\n-            typing.Union[int, typing.Type[Exception]], typing.Callable\n+        exception_handlers: typing.Mapping[\n+            typing.Any, typing.Callable[[Request, Exception], Response]\n         ] = None,\n         on_startup: typing.Sequence[typing.Callable] = None,\n         on_shutdown: typing.Sequence[typing.Callable] = None,\n@@ -68,7 +70,9 @@\n     def build_middleware_stack(self) -> ASGIApp:\n         debug = self.debug\n         error_handler = None\n-        exception_handlers = {}\n+        exception_handlers: typing.Dict[\n+            typing.Any, typing.Callable[[Request, Exception], Response]\n+        ] = {}\n \n         for key, value in self.exception_handlers.items():\n             if key in (500, Exception):\ndiff --git a/starlette/exceptions.py b/starlette/exceptions.py\n--- a/starlette/exceptions.py\n+++ b/starlette/exceptions.py\n@@ -22,7 +22,12 @@\n \n class ExceptionMiddleware:\n     def __init__(\n-        self, app: ASGIApp, handlers: dict = None, debug: bool = False\n+        self,\n+        app: ASGIApp,\n+        handlers: typing.Mapping[\n+            typing.Any, typing.Callable[[Request, Exception], Response]\n+        ] = None,\n+        debug: bool = False,\n     ) -> None:\n         self.app = app\n         self.debug = debug  # TODO: We ought to handle 404 cases if debug is set.\n@@ -37,7 +42,7 @@\n     def add_exception_handler(\n         self,\n         exc_class_or_status_code: typing.Union[int, typing.Type[Exception]],\n-        handler: typing.Callable,\n+        handler: typing.Callable[[Request, Exception], Response],\n     ) -> None:\n         if isinstance(exc_class_or_status_code, int):\n             self._status_handlers[exc_class_or_status_code] = handler\n", "issue": "mypy complains about `exception_handlers` dict with `HTTPException` key\n### Checklist\r\n\r\n<!-- Please make sure you check all these items before submitting your bug report. -->\r\n\r\n- [x] The bug is reproducible against the latest release and/or `master`.\r\n- [x] There are no similar issues or pull requests to fix it yet.\r\n\r\nRelated, but not the same:\r\n* #1034 \r\n* #1139 \r\n* #949\r\n\r\n### Describe the bug\r\n\r\n<!-- A clear and concise description of what the bug is. -->\r\n\r\n### To reproduce\r\n\r\nGiven an example.py: \r\n\r\n```python\r\nfrom starlette.applications import Starlette\r\nfrom starlette.exceptions import HTTPException\r\nfrom starlette.requests import Request\r\nfrom starlette.responses import Response\r\nfrom starlette.routing import Route\r\n\r\ndef handle_http_exception(request: Request, exc: HTTPException) -> Response:\r\n    return Response('foo')\r\n\r\n\r\nexception_handlers = {\r\n    HTTPException: handle_http_exception\r\n}\r\napp = Starlette(exception_handlers=exception_handlers)\r\n```\r\n\r\n### Expected behavior\r\n\r\nMypy does not present an error.\r\n\r\n### Actual behavior\r\n\r\n```console\r\n$ mypy example.py\r\nexample.py:14: error: Argument \"exception_handlers\" to \"Starlette\" has incompatible type \"Dict[Type[HTTPException], Callable[[Request, HTTPException], Response]]\"; expected \"Optional[Dict[Union[int, Type[Exception]], Callable[..., Any]]]\"\r\nFound 1 error in 1 file (checked 1 source file)\r\n```\r\n\r\n### Debugging material\r\n\r\nNone\r\n\r\n### Environment\r\n\r\n- OS: Debian (`Linux ... 4.19.0-14-amd64 #1 SMP Debian 4.19.171-2 (2021-01-30) x86_64 GNU/Linux`)\r\n- Python version: `Python 3.9.1`\r\n- Starlette version: `starlette==0.14.2`\r\n\r\n### Additional context\r\n\r\nFor propriety:\r\n\r\nhttps://github.com/encode/starlette/blob/master/docs/exceptions.md#L42\r\n\r\nhttps://github.com/encode/starlette/blob/ed73b97c9b8f4aa527eed88032c04ce9fe109a3c/starlette/applications.py#L44\r\n\r\nI think this is a Starlette issue and not a mypy issue; apologies if I'm wrong here.\n", "before_files": [{"content": "import asyncio\nimport http\nimport typing\n\nfrom starlette.concurrency import run_in_threadpool\nfrom starlette.requests import Request\nfrom starlette.responses import PlainTextResponse, Response\nfrom starlette.types import ASGIApp, Message, Receive, Scope, Send\n\n\nclass HTTPException(Exception):\n    def __init__(self, status_code: int, detail: str = None) -> None:\n        if detail is None:\n            detail = http.HTTPStatus(status_code).phrase\n        self.status_code = status_code\n        self.detail = detail\n\n    def __repr__(self) -> str:\n        class_name = self.__class__.__name__\n        return f\"{class_name}(status_code={self.status_code!r}, detail={self.detail!r})\"\n\n\nclass ExceptionMiddleware:\n    def __init__(\n        self, app: ASGIApp, handlers: dict = None, debug: bool = False\n    ) -> None:\n        self.app = app\n        self.debug = debug  # TODO: We ought to handle 404 cases if debug is set.\n        self._status_handlers: typing.Dict[int, typing.Callable] = {}\n        self._exception_handlers: typing.Dict[\n            typing.Type[Exception], typing.Callable\n        ] = {HTTPException: self.http_exception}\n        if handlers is not None:\n            for key, value in handlers.items():\n                self.add_exception_handler(key, value)\n\n    def add_exception_handler(\n        self,\n        exc_class_or_status_code: typing.Union[int, typing.Type[Exception]],\n        handler: typing.Callable,\n    ) -> None:\n        if isinstance(exc_class_or_status_code, int):\n            self._status_handlers[exc_class_or_status_code] = handler\n        else:\n            assert issubclass(exc_class_or_status_code, Exception)\n            self._exception_handlers[exc_class_or_status_code] = handler\n\n    def _lookup_exception_handler(\n        self, exc: Exception\n    ) -> typing.Optional[typing.Callable]:\n        for cls in type(exc).__mro__:\n            if cls in self._exception_handlers:\n                return self._exception_handlers[cls]\n        return None\n\n    async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:\n        if scope[\"type\"] != \"http\":\n            await self.app(scope, receive, send)\n            return\n\n        response_started = False\n\n        async def sender(message: Message) -> None:\n            nonlocal response_started\n\n            if message[\"type\"] == \"http.response.start\":\n                response_started = True\n            await send(message)\n\n        try:\n            await self.app(scope, receive, sender)\n        except Exception as exc:\n            handler = None\n\n            if isinstance(exc, HTTPException):\n                handler = self._status_handlers.get(exc.status_code)\n\n            if handler is None:\n                handler = self._lookup_exception_handler(exc)\n\n            if handler is None:\n                raise exc\n\n            if response_started:\n                msg = \"Caught handled exception, but response already started.\"\n                raise RuntimeError(msg) from exc\n\n            request = Request(scope, receive=receive)\n            if asyncio.iscoroutinefunction(handler):\n                response = await handler(request, exc)\n            else:\n                response = await run_in_threadpool(handler, request, exc)\n            await response(scope, receive, sender)\n\n    def http_exception(self, request: Request, exc: HTTPException) -> Response:\n        if exc.status_code in {204, 304}:\n            return Response(b\"\", status_code=exc.status_code)\n        return PlainTextResponse(exc.detail, status_code=exc.status_code)\n", "path": "starlette/exceptions.py"}, {"content": "import typing\n\nfrom starlette.datastructures import State, URLPath\nfrom starlette.exceptions import ExceptionMiddleware\nfrom starlette.middleware import Middleware\nfrom starlette.middleware.base import BaseHTTPMiddleware\nfrom starlette.middleware.errors import ServerErrorMiddleware\nfrom starlette.routing import BaseRoute, Router\nfrom starlette.types import ASGIApp, Receive, Scope, Send\n\n\nclass Starlette:\n    \"\"\"\n    Creates an application instance.\n\n    **Parameters:**\n\n    * **debug** - Boolean indicating if debug tracebacks should be returned on errors.\n    * **routes** - A list of routes to serve incoming HTTP and WebSocket requests.\n    * **middleware** - A list of middleware to run for every request. A starlette\n    application will always automatically include two middleware classes.\n    `ServerErrorMiddleware` is added as the very outermost middleware, to handle\n    any uncaught errors occurring anywhere in the entire stack.\n    `ExceptionMiddleware` is added as the very innermost middleware, to deal\n    with handled exception cases occurring in the routing or endpoints.\n    * **exception_handlers** - A dictionary mapping either integer status codes,\n    or exception class types onto callables which handle the exceptions.\n    Exception handler callables should be of the form\n    `handler(request, exc) -> response` and may be be either standard functions, or\n    async functions.\n    * **on_startup** - A list of callables to run on application startup.\n    Startup handler callables do not take any arguments, and may be be either\n    standard functions, or async functions.\n    * **on_shutdown** - A list of callables to run on application shutdown.\n    Shutdown handler callables do not take any arguments, and may be be either\n    standard functions, or async functions.\n    \"\"\"\n\n    def __init__(\n        self,\n        debug: bool = False,\n        routes: typing.Sequence[BaseRoute] = None,\n        middleware: typing.Sequence[Middleware] = None,\n        exception_handlers: typing.Dict[\n            typing.Union[int, typing.Type[Exception]], typing.Callable\n        ] = None,\n        on_startup: typing.Sequence[typing.Callable] = None,\n        on_shutdown: typing.Sequence[typing.Callable] = None,\n        lifespan: typing.Callable[[\"Starlette\"], typing.AsyncContextManager] = None,\n    ) -> None:\n        # The lifespan context function is a newer style that replaces\n        # on_startup / on_shutdown handlers. Use one or the other, not both.\n        assert lifespan is None or (\n            on_startup is None and on_shutdown is None\n        ), \"Use either 'lifespan' or 'on_startup'/'on_shutdown', not both.\"\n\n        self._debug = debug\n        self.state = State()\n        self.router = Router(\n            routes, on_startup=on_startup, on_shutdown=on_shutdown, lifespan=lifespan\n        )\n        self.exception_handlers = (\n            {} if exception_handlers is None else dict(exception_handlers)\n        )\n        self.user_middleware = [] if middleware is None else list(middleware)\n        self.middleware_stack = self.build_middleware_stack()\n\n    def build_middleware_stack(self) -> ASGIApp:\n        debug = self.debug\n        error_handler = None\n        exception_handlers = {}\n\n        for key, value in self.exception_handlers.items():\n            if key in (500, Exception):\n                error_handler = value\n            else:\n                exception_handlers[key] = value\n\n        middleware = (\n            [Middleware(ServerErrorMiddleware, handler=error_handler, debug=debug)]\n            + self.user_middleware\n            + [\n                Middleware(\n                    ExceptionMiddleware, handlers=exception_handlers, debug=debug\n                )\n            ]\n        )\n\n        app = self.router\n        for cls, options in reversed(middleware):\n            app = cls(app=app, **options)\n        return app\n\n    @property\n    def routes(self) -> typing.List[BaseRoute]:\n        return self.router.routes\n\n    @property\n    def debug(self) -> bool:\n        return self._debug\n\n    @debug.setter\n    def debug(self, value: bool) -> None:\n        self._debug = value\n        self.middleware_stack = self.build_middleware_stack()\n\n    def url_path_for(self, name: str, **path_params: typing.Any) -> URLPath:\n        return self.router.url_path_for(name, **path_params)\n\n    async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:\n        scope[\"app\"] = self\n        await self.middleware_stack(scope, receive, send)\n\n    # The following usages are now discouraged in favour of configuration\n    # \u00a0during Starlette.__init__(...)\n    def on_event(self, event_type: str) -> typing.Callable:\n        return self.router.on_event(event_type)\n\n    def mount(self, path: str, app: ASGIApp, name: str = None) -> None:\n        self.router.mount(path, app=app, name=name)\n\n    def host(self, host: str, app: ASGIApp, name: str = None) -> None:\n        self.router.host(host, app=app, name=name)\n\n    def add_middleware(self, middleware_class: type, **options: typing.Any) -> None:\n        self.user_middleware.insert(0, Middleware(middleware_class, **options))\n        self.middleware_stack = self.build_middleware_stack()\n\n    def add_exception_handler(\n        self,\n        exc_class_or_status_code: typing.Union[int, typing.Type[Exception]],\n        handler: typing.Callable,\n    ) -> None:\n        self.exception_handlers[exc_class_or_status_code] = handler\n        self.middleware_stack = self.build_middleware_stack()\n\n    def add_event_handler(self, event_type: str, func: typing.Callable) -> None:\n        self.router.add_event_handler(event_type, func)\n\n    def add_route(\n        self,\n        path: str,\n        route: typing.Callable,\n        methods: typing.List[str] = None,\n        name: str = None,\n        include_in_schema: bool = True,\n    ) -> None:\n        self.router.add_route(\n            path, route, methods=methods, name=name, include_in_schema=include_in_schema\n        )\n\n    def add_websocket_route(\n        self, path: str, route: typing.Callable, name: str = None\n    ) -> None:\n        self.router.add_websocket_route(path, route, name=name)\n\n    def exception_handler(\n        self, exc_class_or_status_code: typing.Union[int, typing.Type[Exception]]\n    ) -> typing.Callable:\n        def decorator(func: typing.Callable) -> typing.Callable:\n            self.add_exception_handler(exc_class_or_status_code, func)\n            return func\n\n        return decorator\n\n    def route(\n        self,\n        path: str,\n        methods: typing.List[str] = None,\n        name: str = None,\n        include_in_schema: bool = True,\n    ) -> typing.Callable:\n        def decorator(func: typing.Callable) -> typing.Callable:\n            self.router.add_route(\n                path,\n                func,\n                methods=methods,\n                name=name,\n                include_in_schema=include_in_schema,\n            )\n            return func\n\n        return decorator\n\n    def websocket_route(self, path: str, name: str = None) -> typing.Callable:\n        def decorator(func: typing.Callable) -> typing.Callable:\n            self.router.add_websocket_route(path, func, name=name)\n            return func\n\n        return decorator\n\n    def middleware(self, middleware_type: str) -> typing.Callable:\n        assert (\n            middleware_type == \"http\"\n        ), 'Currently only middleware(\"http\") is supported.'\n\n        def decorator(func: typing.Callable) -> typing.Callable:\n            self.add_middleware(BaseHTTPMiddleware, dispatch=func)\n            return func\n\n        return decorator\n", "path": "starlette/applications.py"}], "after_files": [{"content": "import asyncio\nimport http\nimport typing\n\nfrom starlette.concurrency import run_in_threadpool\nfrom starlette.requests import Request\nfrom starlette.responses import PlainTextResponse, Response\nfrom starlette.types import ASGIApp, Message, Receive, Scope, Send\n\n\nclass HTTPException(Exception):\n    def __init__(self, status_code: int, detail: str = None) -> None:\n        if detail is None:\n            detail = http.HTTPStatus(status_code).phrase\n        self.status_code = status_code\n        self.detail = detail\n\n    def __repr__(self) -> str:\n        class_name = self.__class__.__name__\n        return f\"{class_name}(status_code={self.status_code!r}, detail={self.detail!r})\"\n\n\nclass ExceptionMiddleware:\n    def __init__(\n        self,\n        app: ASGIApp,\n        handlers: typing.Mapping[\n            typing.Any, typing.Callable[[Request, Exception], Response]\n        ] = None,\n        debug: bool = False,\n    ) -> None:\n        self.app = app\n        self.debug = debug  # TODO: We ought to handle 404 cases if debug is set.\n        self._status_handlers: typing.Dict[int, typing.Callable] = {}\n        self._exception_handlers: typing.Dict[\n            typing.Type[Exception], typing.Callable\n        ] = {HTTPException: self.http_exception}\n        if handlers is not None:\n            for key, value in handlers.items():\n                self.add_exception_handler(key, value)\n\n    def add_exception_handler(\n        self,\n        exc_class_or_status_code: typing.Union[int, typing.Type[Exception]],\n        handler: typing.Callable[[Request, Exception], Response],\n    ) -> None:\n        if isinstance(exc_class_or_status_code, int):\n            self._status_handlers[exc_class_or_status_code] = handler\n        else:\n            assert issubclass(exc_class_or_status_code, Exception)\n            self._exception_handlers[exc_class_or_status_code] = handler\n\n    def _lookup_exception_handler(\n        self, exc: Exception\n    ) -> typing.Optional[typing.Callable]:\n        for cls in type(exc).__mro__:\n            if cls in self._exception_handlers:\n                return self._exception_handlers[cls]\n        return None\n\n    async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:\n        if scope[\"type\"] != \"http\":\n            await self.app(scope, receive, send)\n            return\n\n        response_started = False\n\n        async def sender(message: Message) -> None:\n            nonlocal response_started\n\n            if message[\"type\"] == \"http.response.start\":\n                response_started = True\n            await send(message)\n\n        try:\n            await self.app(scope, receive, sender)\n        except Exception as exc:\n            handler = None\n\n            if isinstance(exc, HTTPException):\n                handler = self._status_handlers.get(exc.status_code)\n\n            if handler is None:\n                handler = self._lookup_exception_handler(exc)\n\n            if handler is None:\n                raise exc\n\n            if response_started:\n                msg = \"Caught handled exception, but response already started.\"\n                raise RuntimeError(msg) from exc\n\n            request = Request(scope, receive=receive)\n            if asyncio.iscoroutinefunction(handler):\n                response = await handler(request, exc)\n            else:\n                response = await run_in_threadpool(handler, request, exc)\n            await response(scope, receive, sender)\n\n    def http_exception(self, request: Request, exc: HTTPException) -> Response:\n        if exc.status_code in {204, 304}:\n            return Response(b\"\", status_code=exc.status_code)\n        return PlainTextResponse(exc.detail, status_code=exc.status_code)\n", "path": "starlette/exceptions.py"}, {"content": "import typing\n\nfrom starlette.datastructures import State, URLPath\nfrom starlette.exceptions import ExceptionMiddleware\nfrom starlette.middleware import Middleware\nfrom starlette.middleware.base import BaseHTTPMiddleware\nfrom starlette.middleware.errors import ServerErrorMiddleware\nfrom starlette.requests import Request\nfrom starlette.responses import Response\nfrom starlette.routing import BaseRoute, Router\nfrom starlette.types import ASGIApp, Receive, Scope, Send\n\n\nclass Starlette:\n    \"\"\"\n    Creates an application instance.\n\n    **Parameters:**\n\n    * **debug** - Boolean indicating if debug tracebacks should be returned on errors.\n    * **routes** - A list of routes to serve incoming HTTP and WebSocket requests.\n    * **middleware** - A list of middleware to run for every request. A starlette\n    application will always automatically include two middleware classes.\n    `ServerErrorMiddleware` is added as the very outermost middleware, to handle\n    any uncaught errors occurring anywhere in the entire stack.\n    `ExceptionMiddleware` is added as the very innermost middleware, to deal\n    with handled exception cases occurring in the routing or endpoints.\n    * **exception_handlers** - A mapping of either integer status codes,\n    or exception class types onto callables which handle the exceptions.\n    Exception handler callables should be of the form\n    `handler(request, exc) -> response` and may be be either standard functions, or\n    async functions.\n    * **on_startup** - A list of callables to run on application startup.\n    Startup handler callables do not take any arguments, and may be be either\n    standard functions, or async functions.\n    * **on_shutdown** - A list of callables to run on application shutdown.\n    Shutdown handler callables do not take any arguments, and may be be either\n    standard functions, or async functions.\n    \"\"\"\n\n    def __init__(\n        self,\n        debug: bool = False,\n        routes: typing.Sequence[BaseRoute] = None,\n        middleware: typing.Sequence[Middleware] = None,\n        exception_handlers: typing.Mapping[\n            typing.Any, typing.Callable[[Request, Exception], Response]\n        ] = None,\n        on_startup: typing.Sequence[typing.Callable] = None,\n        on_shutdown: typing.Sequence[typing.Callable] = None,\n        lifespan: typing.Callable[[\"Starlette\"], typing.AsyncContextManager] = None,\n    ) -> None:\n        # The lifespan context function is a newer style that replaces\n        # on_startup / on_shutdown handlers. Use one or the other, not both.\n        assert lifespan is None or (\n            on_startup is None and on_shutdown is None\n        ), \"Use either 'lifespan' or 'on_startup'/'on_shutdown', not both.\"\n\n        self._debug = debug\n        self.state = State()\n        self.router = Router(\n            routes, on_startup=on_startup, on_shutdown=on_shutdown, lifespan=lifespan\n        )\n        self.exception_handlers = (\n            {} if exception_handlers is None else dict(exception_handlers)\n        )\n        self.user_middleware = [] if middleware is None else list(middleware)\n        self.middleware_stack = self.build_middleware_stack()\n\n    def build_middleware_stack(self) -> ASGIApp:\n        debug = self.debug\n        error_handler = None\n        exception_handlers: typing.Dict[\n            typing.Any, typing.Callable[[Request, Exception], Response]\n        ] = {}\n\n        for key, value in self.exception_handlers.items():\n            if key in (500, Exception):\n                error_handler = value\n            else:\n                exception_handlers[key] = value\n\n        middleware = (\n            [Middleware(ServerErrorMiddleware, handler=error_handler, debug=debug)]\n            + self.user_middleware\n            + [\n                Middleware(\n                    ExceptionMiddleware, handlers=exception_handlers, debug=debug\n                )\n            ]\n        )\n\n        app = self.router\n        for cls, options in reversed(middleware):\n            app = cls(app=app, **options)\n        return app\n\n    @property\n    def routes(self) -> typing.List[BaseRoute]:\n        return self.router.routes\n\n    @property\n    def debug(self) -> bool:\n        return self._debug\n\n    @debug.setter\n    def debug(self, value: bool) -> None:\n        self._debug = value\n        self.middleware_stack = self.build_middleware_stack()\n\n    def url_path_for(self, name: str, **path_params: typing.Any) -> URLPath:\n        return self.router.url_path_for(name, **path_params)\n\n    async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:\n        scope[\"app\"] = self\n        await self.middleware_stack(scope, receive, send)\n\n    # The following usages are now discouraged in favour of configuration\n    # \u00a0during Starlette.__init__(...)\n    def on_event(self, event_type: str) -> typing.Callable:\n        return self.router.on_event(event_type)\n\n    def mount(self, path: str, app: ASGIApp, name: str = None) -> None:\n        self.router.mount(path, app=app, name=name)\n\n    def host(self, host: str, app: ASGIApp, name: str = None) -> None:\n        self.router.host(host, app=app, name=name)\n\n    def add_middleware(self, middleware_class: type, **options: typing.Any) -> None:\n        self.user_middleware.insert(0, Middleware(middleware_class, **options))\n        self.middleware_stack = self.build_middleware_stack()\n\n    def add_exception_handler(\n        self,\n        exc_class_or_status_code: typing.Union[int, typing.Type[Exception]],\n        handler: typing.Callable,\n    ) -> None:\n        self.exception_handlers[exc_class_or_status_code] = handler\n        self.middleware_stack = self.build_middleware_stack()\n\n    def add_event_handler(self, event_type: str, func: typing.Callable) -> None:\n        self.router.add_event_handler(event_type, func)\n\n    def add_route(\n        self,\n        path: str,\n        route: typing.Callable,\n        methods: typing.List[str] = None,\n        name: str = None,\n        include_in_schema: bool = True,\n    ) -> None:\n        self.router.add_route(\n            path, route, methods=methods, name=name, include_in_schema=include_in_schema\n        )\n\n    def add_websocket_route(\n        self, path: str, route: typing.Callable, name: str = None\n    ) -> None:\n        self.router.add_websocket_route(path, route, name=name)\n\n    def exception_handler(\n        self, exc_class_or_status_code: typing.Union[int, typing.Type[Exception]]\n    ) -> typing.Callable:\n        def decorator(func: typing.Callable) -> typing.Callable:\n            self.add_exception_handler(exc_class_or_status_code, func)\n            return func\n\n        return decorator\n\n    def route(\n        self,\n        path: str,\n        methods: typing.List[str] = None,\n        name: str = None,\n        include_in_schema: bool = True,\n    ) -> typing.Callable:\n        def decorator(func: typing.Callable) -> typing.Callable:\n            self.router.add_route(\n                path,\n                func,\n                methods=methods,\n                name=name,\n                include_in_schema=include_in_schema,\n            )\n            return func\n\n        return decorator\n\n    def websocket_route(self, path: str, name: str = None) -> typing.Callable:\n        def decorator(func: typing.Callable) -> typing.Callable:\n            self.router.add_websocket_route(path, func, name=name)\n            return func\n\n        return decorator\n\n    def middleware(self, middleware_type: str) -> typing.Callable:\n        assert (\n            middleware_type == \"http\"\n        ), 'Currently only middleware(\"http\") is supported.'\n\n        def decorator(func: typing.Callable) -> typing.Callable:\n            self.add_middleware(BaseHTTPMiddleware, dispatch=func)\n            return func\n\n        return decorator\n", "path": "starlette/applications.py"}]}