Skip to content

Commit 4e8080f

Browse files
authored
📌 Upgrade Starlette version (fastapi#1057)
1 parent fbbed6f commit 4e8080f

File tree

5 files changed

+118
-10
lines changed

5 files changed

+118
-10
lines changed

fastapi/applications.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
from fastapi.utils import warning_response_model_skip_defaults_deprecated
1919
from starlette.applications import Starlette
2020
from starlette.datastructures import State
21-
from starlette.exceptions import ExceptionMiddleware, HTTPException
22-
from starlette.middleware.errors import ServerErrorMiddleware
21+
from starlette.exceptions import HTTPException
22+
from starlette.middleware import Middleware
2323
from starlette.requests import Request
2424
from starlette.responses import HTMLResponse, JSONResponse, Response
2525
from starlette.routing import BaseRoute
@@ -29,9 +29,9 @@
2929
class FastAPI(Starlette):
3030
def __init__(
3131
self,
32+
*,
3233
debug: bool = False,
3334
routes: List[BaseRoute] = None,
34-
template_directory: str = None,
3535
title: str = "FastAPI",
3636
description: str = "",
3737
version: str = "0.1.0",
@@ -42,19 +42,28 @@ def __init__(
4242
redoc_url: Optional[str] = "/redoc",
4343
swagger_ui_oauth2_redirect_url: Optional[str] = "/docs/oauth2-redirect",
4444
swagger_ui_init_oauth: Optional[dict] = None,
45+
middleware: Sequence[Middleware] = None,
46+
exception_handlers: Dict[Union[int, Type[Exception]], Callable] = None,
47+
on_startup: Sequence[Callable] = None,
48+
on_shutdown: Sequence[Callable] = None,
4549
**extra: Dict[str, Any],
4650
) -> None:
4751
self.default_response_class = default_response_class
4852
self._debug = debug
4953
self.state = State()
5054
self.router: routing.APIRouter = routing.APIRouter(
51-
routes, dependency_overrides_provider=self
55+
routes,
56+
dependency_overrides_provider=self,
57+
on_startup=on_startup,
58+
on_shutdown=on_shutdown,
5259
)
53-
self.exception_middleware = ExceptionMiddleware(self.router, debug=debug)
54-
self.error_middleware = ServerErrorMiddleware(
55-
self.exception_middleware, debug=debug
60+
self.exception_handlers = (
61+
{} if exception_handlers is None else dict(exception_handlers)
5662
)
5763

64+
self.user_middleware = [] if middleware is None else list(middleware)
65+
self.middleware_stack = self.build_middleware_stack()
66+
5867
self.title = title
5968
self.description = description
6069
self.version = version

fastapi/routing.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,9 +346,15 @@ def __init__(
346346
dependency_overrides_provider: Any = None,
347347
route_class: Type[APIRoute] = APIRoute,
348348
default_response_class: Type[Response] = None,
349+
on_startup: Sequence[Callable] = None,
350+
on_shutdown: Sequence[Callable] = None,
349351
) -> None:
350352
super().__init__(
351-
routes=routes, redirect_slashes=redirect_slashes, default=default
353+
routes=routes,
354+
redirect_slashes=redirect_slashes,
355+
default=default,
356+
on_startup=on_startup,
357+
on_shutdown=on_shutdown,
352358
)
353359
self.dependency_overrides_provider = dependency_overrides_provider
354360
self.route_class = route_class
@@ -552,6 +558,10 @@ def include_router(
552558
self.add_websocket_route(
553559
prefix + route.path, route.endpoint, name=route.name
554560
)
561+
for handler in router.on_startup:
562+
self.add_event_handler("startup", handler)
563+
for handler in router.on_shutdown:
564+
self.add_event_handler("shutdown", handler)
555565

556566
def get(
557567
self,

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ classifiers = [
3232
"Topic :: Internet :: WWW/HTTP",
3333
]
3434
requires = [
35-
"starlette >=0.12.9,<=0.12.9",
35+
"starlette ==0.13.2",
3636
"pydantic >=0.32.2,<2.0.0"
3737
]
3838
description-file = "README.md"

tests/test_empty_router.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@ def get_empty():
2121
def test_use_empty():
2222
with client:
2323
response = client.get("/prefix")
24+
assert response.status_code == 200
2425
assert response.json() == ["OK"]
2526

2627
response = client.get("/prefix/")
27-
assert response.status_code == 404
28+
assert response.status_code == 200
29+
assert response.json() == ["OK"]
2830

2931

3032
def test_include_empty():

tests/test_router_events.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
from fastapi import APIRouter, FastAPI
2+
from pydantic import BaseModel
3+
from starlette.testclient import TestClient
4+
5+
6+
class State(BaseModel):
7+
app_startup: bool = False
8+
app_shutdown: bool = False
9+
router_startup: bool = False
10+
router_shutdown: bool = False
11+
sub_router_startup: bool = False
12+
sub_router_shutdown: bool = False
13+
14+
15+
state = State()
16+
17+
app = FastAPI()
18+
19+
20+
@app.on_event("startup")
21+
def app_startup():
22+
state.app_startup = True
23+
24+
25+
@app.on_event("shutdown")
26+
def app_shutdown():
27+
state.app_shutdown = True
28+
29+
30+
router = APIRouter()
31+
32+
33+
@router.on_event("startup")
34+
def router_startup():
35+
state.router_startup = True
36+
37+
38+
@router.on_event("shutdown")
39+
def router_shutdown():
40+
state.router_shutdown = True
41+
42+
43+
sub_router = APIRouter()
44+
45+
46+
@sub_router.on_event("startup")
47+
def sub_router_startup():
48+
state.sub_router_startup = True
49+
50+
51+
@sub_router.on_event("shutdown")
52+
def sub_router_shutdown():
53+
state.sub_router_shutdown = True
54+
55+
56+
@sub_router.get("/")
57+
def main():
58+
return {"message": "Hello World"}
59+
60+
61+
router.include_router(sub_router)
62+
app.include_router(router)
63+
64+
65+
def test_router_events():
66+
assert state.app_startup is False
67+
assert state.router_startup is False
68+
assert state.sub_router_startup is False
69+
assert state.app_shutdown is False
70+
assert state.router_shutdown is False
71+
assert state.sub_router_shutdown is False
72+
with TestClient(app) as client:
73+
assert state.app_startup is True
74+
assert state.router_startup is True
75+
assert state.sub_router_startup is True
76+
assert state.app_shutdown is False
77+
assert state.router_shutdown is False
78+
assert state.sub_router_shutdown is False
79+
response = client.get("/")
80+
assert response.status_code == 200
81+
assert response.json() == {"message": "Hello World"}
82+
assert state.app_startup is True
83+
assert state.router_startup is True
84+
assert state.sub_router_startup is True
85+
assert state.app_shutdown is True
86+
assert state.router_shutdown is True
87+
assert state.sub_router_shutdown is True

0 commit comments

Comments
 (0)