Skip to content

Commit c6e153b

Browse files
committed
feat: Remove starlette middleware compat (#4030)
Remove starlette middleware compat
1 parent c176f73 commit c6e153b

File tree

5 files changed

+28
-44
lines changed

5 files changed

+28
-44
lines changed

docs/examples/application_state/using_application_state.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def set_state_on_startup(app: Litestar) -> None:
1616
app.state.value = "abc123"
1717

1818

19-
def middleware_factory(*, app: "ASGIApp") -> "ASGIApp":
19+
def middleware_factory(app: "ASGIApp") -> "ASGIApp":
2020
"""A middleware can access application state via `scope`."""
2121

2222
async def my_middleware(scope: "Scope", receive: "Receive", send: "Send") -> None:

docs/release-notes/whats-new-3.rst

+19
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,25 @@ this functionality are now required to inherit from
245245
:class:`~.plugins.OpenAPISchemaPlugin`.
246246

247247

248+
Dropped support for starlette middleware protocol
249+
-------------------------------------------------
250+
251+
The `starlette middleware protocol <https://www.starlette.io/middleware>`_ is no longer
252+
supported.
253+
254+
Only the "factory" pattern will now be supported, i.e. a callable that receives an ASGI
255+
callable as its only argument and returns another ASGI callable:
256+
257+
.. code-block:: python
258+
259+
def middleware(app: ASGIApp) -> ASGIApp:
260+
...
261+
262+
263+
.. seealso::
264+
:doc:`/usage/middleware/index`
265+
266+
248267
Removal of ``SerializationPluginProtocol``
249268
------------------------------------------
250269

litestar/_asgi/routing_trie/mapping.py

+2-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22

33
from pathlib import Path
4-
from typing import TYPE_CHECKING, Any, cast
4+
from typing import TYPE_CHECKING, cast
55

66
from litestar._asgi.routing_trie.types import (
77
ASGIHandlerTuple,
@@ -215,9 +215,5 @@ def build_route_middleware_stack(
215215
asgi_handler = AllowedHostsMiddleware(app=asgi_handler, config=app.allowed_hosts)
216216

217217
for middleware in handler_middleware:
218-
if hasattr(middleware, "__iter__"):
219-
handler, kwargs = cast("tuple[Any, dict[str, Any]]", middleware)
220-
asgi_handler = handler(app=asgi_handler, **kwargs)
221-
else:
222-
asgi_handler = middleware(app=asgi_handler) # type: ignore[call-arg]
218+
asgi_handler = middleware(asgi_handler)
223219
return asgi_handler

litestar/types/composite_types.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323

2424
if TYPE_CHECKING:
25-
from collections.abc import Iterator, Mapping, MutableMapping, Sequence
25+
from collections.abc import Mapping, MutableMapping, Sequence
2626
from os import PathLike
2727
from pathlib import Path
2828

@@ -32,15 +32,14 @@
3232
from litestar.datastructures.response_header import ResponseHeader
3333
from litestar.di import Provide
3434
from litestar.enums import ScopeType
35-
from litestar.middleware.base import DefineMiddleware, MiddlewareProtocol
3635
from litestar.params import ParameterKwarg
3736

3837
from .asgi_types import ASGIApp
3938
from .callable_types import AnyCallable, ExceptionHandler
4039

4140
Dependencies: TypeAlias = "Mapping[str, Union[Provide, AnyCallable]]"
4241
ExceptionHandlersMap: TypeAlias = "MutableMapping[Union[int, type[Exception]], ExceptionHandler]"
43-
Middleware: TypeAlias = "Union[Callable[..., ASGIApp], DefineMiddleware, Iterator[tuple[ASGIApp, dict[str, Any]]], type[MiddlewareProtocol]]"
42+
Middleware: TypeAlias = Callable[..., "ASGIApp"]
4443
ParametersMap: TypeAlias = "Mapping[str, ParameterKwarg]"
4544
PathType: TypeAlias = "Union[Path, PathLike, str]"
4645
ResponseCookies: TypeAlias = "Union[Sequence[Cookie], Mapping[str, str]]"
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
from __future__ import annotations
22

3-
from collections.abc import Iterator
4-
from typing import Any
53
from unittest.mock import MagicMock
64

75
import pytest
@@ -42,36 +40,8 @@ async def handler() -> None:
4240
route = HTTPRoute(path="/", route_handlers=[handler])
4341
build_route_middleware_stack(app=Litestar(), route=route, route_handler=handler)
4442
mock_middleware.assert_called_once()
45-
((_, kw_args),) = mock_middleware.call_args_list
46-
assert isinstance(kw_args["app"], ExceptionHandlerMiddleware)
4743

48-
49-
def test_build_route_middleware_stack_with_starlette_middleware(monkeypatch: pytest.MonkeyPatch) -> None:
50-
# test our support for starlette's Middleware class
51-
class Middleware:
52-
"""A Starlette ``Middleware`` class.
53-
54-
See https://github.com/encode/starlette/blob/23c81da94b57701eabd43f582093442e6811f81d/starlette/middleware/__init__.py#L4-L17
55-
"""
56-
57-
def __init__(self, cls: Any, **options: Any) -> None:
58-
self.cls = cls
59-
self.options = options
60-
61-
def __iter__(self) -> Iterator[Any]:
62-
as_tuple = (self.cls, self.options)
63-
return iter(as_tuple)
64-
65-
mock_middleware = MagicMock()
66-
mock_middleware_arg = MagicMock()
67-
del mock_middleware.__iter__
68-
69-
@get("/", middleware=[Middleware(mock_middleware, arg=mock_middleware_arg)]) # type: ignore[list-item]
70-
async def handler() -> None:
71-
pass
72-
73-
route = HTTPRoute(path="/", route_handlers=[handler])
74-
build_route_middleware_stack(app=Litestar(), route=route, route_handler=handler)
75-
((_, kw_args),) = mock_middleware.call_args_list
76-
assert isinstance(kw_args["app"], ExceptionHandlerMiddleware)
77-
assert kw_args["arg"] is mock_middleware_arg
44+
call_args = mock_middleware.call_args_list[0]
45+
assert len(call_args.args) == 1
46+
assert isinstance(call_args.args[0], ExceptionHandlerMiddleware)
47+
assert not call_args.kwargs

0 commit comments

Comments
 (0)