From 63c81b8d04a6d1c2bfd10b90c227697cb934e391 Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Thu, 2 Jul 2026 10:38:48 +0200 Subject: [PATCH 1/8] ref(starlette): Add package to typing group --- pyproject.toml | 1 + uv.lock | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 881e43a105..520f33f168 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -67,6 +67,7 @@ typing = [ "httpx2", "botocore-stubs", "werkzeug", + "starlette>=1.3.1", ] test = [ "dataclasses ; python_full_version < '3.7'", diff --git a/uv.lock b/uv.lock index 4addd76e84..09742b6d5a 100644 --- a/uv.lock +++ b/uv.lock @@ -51,6 +51,7 @@ typing = [ { name = "openfeature-sdk" }, { name = "opentelemetry-distro", extras = ["otlp"] }, { name = "pymongo" }, + { name = "starlette", specifier = ">=1.3.1" }, { name = "statsig" }, { name = "strawberry-graphql" }, { name = "typer" }, @@ -1618,6 +1619,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331", size = 92072, upload-time = "2024-07-29T01:10:08.203Z" }, ] +[[package]] +name = "starlette" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/e3/7c1dc7381d9f8ab7d854328ebfa884e62cb3f3d8549ddfd37c7814f42afa/starlette-1.3.1.tar.gz", hash = "sha256:05d0213193f2fbaae60e2ecb593b4add4262ad4e46536b54abe36f11a71724e0", size = 2703240, upload-time = "2026-06-12T09:23:11.602Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/bb/2799cc2ede3ed41131f8975621e7213dfc7ef4acbbaadfa440f32500c370/starlette-1.3.1-py3-none-any.whl", hash = "sha256:c7372aae11c3c3f26a42df7bd626cec2f47d03483d261d369516a615a53714c6", size = 73632, upload-time = "2026-06-12T09:23:10.017Z" }, +] + [[package]] name = "statsig" version = "0.71.6" From 790b198690fa1c3aa79b5072cdf8c379725447de Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Thu, 2 Jul 2026 10:42:08 +0200 Subject: [PATCH 2/8] . --- sentry_sdk/integrations/starlette.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/sentry_sdk/integrations/starlette.py b/sentry_sdk/integrations/starlette.py index eccb4f780f..e694e3b397 100644 --- a/sentry_sdk/integrations/starlette.py +++ b/sentry_sdk/integrations/starlette.py @@ -45,26 +45,26 @@ from sentry_sdk._types import Event, HttpStatusCodeRange try: - import starlette # type: ignore + import starlette from starlette import __version__ as STARLETTE_VERSION - from starlette.applications import Starlette # type: ignore - from starlette.datastructures import ( # type: ignore + from starlette.applications import Starlette + from starlette.datastructures import ( UploadFile, ) - from starlette.middleware import Middleware # type: ignore - from starlette.middleware.authentication import ( # type: ignore + from starlette.middleware import Middleware + from starlette.middleware.authentication import ( AuthenticationMiddleware, ) - from starlette.requests import Request # type: ignore - from starlette.routing import Match # type: ignore - from starlette.types import ASGIApp, Receive, Send # type: ignore + from starlette.requests import Request + from starlette.routing import Match + from starlette.types import ASGIApp, Receive, Send from starlette.types import Scope as StarletteScope except ImportError: raise DidNotEnable("Starlette is not installed") try: # Starlette 0.20 - from starlette.middleware.exceptions import ExceptionMiddleware # type: ignore + from starlette.middleware.exceptions import ExceptionMiddleware except ImportError: # Startlette 0.19.1 from starlette.exceptions import ExceptionMiddleware # type: ignore @@ -430,7 +430,7 @@ def _sentry_middleware_init( if cls == ExceptionMiddleware: patch_exception_middleware(cls) - Middleware.__init__ = _sentry_middleware_init + Middleware.__init__ = _sentry_middleware_init # type: ignore[method-assign] def patch_asgi_app(root_path_in_path: "_RootPathInPath") -> None: @@ -462,7 +462,7 @@ async def _sentry_patched_asgi_app( return await middleware(scope, receive, send) - Starlette.__call__ = _sentry_patched_asgi_app + Starlette.__call__ = _sentry_patched_asgi_app # type: ignore[method-assign] # This was vendored in from Starlette to support Starlette 0.19.1 because @@ -662,7 +662,7 @@ def patch_templates() -> None: # https://github.com/Kludex/starlette/commit/96479daca2e4bd8157f68d914fd162aa94eff73a try: - from starlette.templating import Jinja2Templates # type: ignore + from starlette.templating import Jinja2Templates except ImportError: return @@ -692,7 +692,7 @@ def add_sentry_trace_meta(request: "Request") -> "Dict[str, Any]": return old_jinja2templates_init(self, *args, **kwargs) - Jinja2Templates.__init__ = _sentry_jinja2templates_init + Jinja2Templates.__init__ = _sentry_jinja2templates_init # type: ignore[method-assign] class StarletteRequestExtractor: From c2da81b4401be19589ffd47db3aa1dc4b8600933 Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Thu, 2 Jul 2026 11:00:13 +0200 Subject: [PATCH 3/8] . --- sentry_sdk/integrations/mcp.py | 2 +- sentry_sdk/integrations/starlette.py | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/sentry_sdk/integrations/mcp.py b/sentry_sdk/integrations/mcp.py index 7ec7a22c21..e59c40feb3 100644 --- a/sentry_sdk/integrations/mcp.py +++ b/sentry_sdk/integrations/mcp.py @@ -55,7 +55,7 @@ if TYPE_CHECKING: from typing import Any, Callable, ContextManager, Optional, Tuple, Union - from starlette.types import Receive, Scope, Send # type: ignore[import-not-found] + from starlette.types import Receive, Scope, Send from sentry_sdk.traces import StreamedSpan from sentry_sdk.tracing import Span diff --git a/sentry_sdk/integrations/starlette.py b/sentry_sdk/integrations/starlette.py index e694e3b397..e79ef06cee 100644 --- a/sentry_sdk/integrations/starlette.py +++ b/sentry_sdk/integrations/starlette.py @@ -42,8 +42,9 @@ if TYPE_CHECKING: from typing import Any, Awaitable, Callable, Container, Dict, Optional, Tuple, Union - from sentry_sdk._types import Event, HttpStatusCodeRange + from starlette.middleware import _MiddlewareFactory + from sentry_sdk._types import Event, HttpStatusCodeRange try: import starlette from starlette import __version__ as STARLETTE_VERSION @@ -156,7 +157,7 @@ def setup_once() -> None: patch_templates() -def _enable_span_for_middleware(middleware_class: "Any") -> type: +def _enable_span_for_middleware(middleware_class: "Any") -> _MiddlewareFactory[...,]: old_call = middleware_class.__call__ async def _create_span_call( @@ -701,8 +702,6 @@ class StarletteRequestExtractor: (like form data or cookies) and adds it to the Sentry event. """ - request: "Request" = None - def __init__(self: "StarletteRequestExtractor", request: "Request") -> None: self.request = request From 7c3ef779e59414b52623ccc6607ab3d9679decf6 Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Thu, 2 Jul 2026 11:01:16 +0200 Subject: [PATCH 4/8] . --- sentry_sdk/integrations/starlette.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry_sdk/integrations/starlette.py b/sentry_sdk/integrations/starlette.py index e79ef06cee..57451987d1 100644 --- a/sentry_sdk/integrations/starlette.py +++ b/sentry_sdk/integrations/starlette.py @@ -157,7 +157,7 @@ def setup_once() -> None: patch_templates() -def _enable_span_for_middleware(middleware_class: "Any") -> _MiddlewareFactory[...,]: +def _enable_span_for_middleware(middleware_class: "Any") -> "_MiddlewareFactory[...,]": old_call = middleware_class.__call__ async def _create_span_call( From dbcad8688253a85cf79825c10974a2793df9f27a Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Thu, 2 Jul 2026 11:03:37 +0200 Subject: [PATCH 5/8] . --- sentry_sdk/integrations/starlette.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/sentry_sdk/integrations/starlette.py b/sentry_sdk/integrations/starlette.py index 57451987d1..cc86f171ad 100644 --- a/sentry_sdk/integrations/starlette.py +++ b/sentry_sdk/integrations/starlette.py @@ -40,8 +40,19 @@ ) if TYPE_CHECKING: - from typing import Any, Awaitable, Callable, Container, Dict, Optional, Tuple, Union + from typing import ( + Any, + Awaitable, + Callable, + Container, + Dict, + Optional, + ParamSpec, + Tuple, + Union, + ) + P = ParamSpec("P") from starlette.middleware import _MiddlewareFactory from sentry_sdk._types import Event, HttpStatusCodeRange @@ -157,7 +168,9 @@ def setup_once() -> None: patch_templates() -def _enable_span_for_middleware(middleware_class: "Any") -> "_MiddlewareFactory[...,]": +def _enable_span_for_middleware( + middleware_class: "_MiddlewareFactory[P]", +) -> "_MiddlewareFactory[P]": old_call = middleware_class.__call__ async def _create_span_call( From a40e5e1934cec9c266876ac54d746c85b2297bee Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Thu, 2 Jul 2026 11:08:27 +0200 Subject: [PATCH 6/8] fix --- sentry_sdk/integrations/starlette.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/sentry_sdk/integrations/starlette.py b/sentry_sdk/integrations/starlette.py index cc86f171ad..2e6b9ba2bc 100644 --- a/sentry_sdk/integrations/starlette.py +++ b/sentry_sdk/integrations/starlette.py @@ -47,14 +47,15 @@ Container, Dict, Optional, - ParamSpec, Tuple, + TypeVar, Union, ) - P = ParamSpec("P") from starlette.middleware import _MiddlewareFactory + _MiddlewareClass = TypeVar("_MiddlewareClass", bound=_MiddlewareFactory[...]) + from sentry_sdk._types import Event, HttpStatusCodeRange try: import starlette @@ -169,8 +170,8 @@ def setup_once() -> None: def _enable_span_for_middleware( - middleware_class: "_MiddlewareFactory[P]", -) -> "_MiddlewareFactory[P]": + middleware_class: "_MiddlewareClass", +) -> "_MiddlewareClass": old_call = middleware_class.__call__ async def _create_span_call( @@ -430,7 +431,7 @@ def patch_middlewares() -> None: if not_yet_patched: def _sentry_middleware_init( - self: "Any", cls: "Any", *args: "Any", **kwargs: "Any" + self: "Any", cls: "_MiddlewareFactory[...]", *args: "Any", **kwargs: "Any" ) -> None: if cls == SentryAsgiMiddleware: return old_middleware_init(self, cls, *args, **kwargs) From 4a7b3473916accb3bd7cdebf851bc1f7a5b1c54b Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Thu, 2 Jul 2026 11:37:36 +0200 Subject: [PATCH 7/8] fix --- sentry_sdk/integrations/starlette.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry_sdk/integrations/starlette.py b/sentry_sdk/integrations/starlette.py index 2e6b9ba2bc..5977e3208c 100644 --- a/sentry_sdk/integrations/starlette.py +++ b/sentry_sdk/integrations/starlette.py @@ -172,7 +172,7 @@ def setup_once() -> None: def _enable_span_for_middleware( middleware_class: "_MiddlewareClass", ) -> "_MiddlewareClass": - old_call = middleware_class.__call__ + old_call: "Callable[..., Awaitable[Any]]" = middleware_class.__call__ async def _create_span_call( app: "Any", From 38c3c646061f66b1da95f73b9e3942706972e53d Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Thu, 2 Jul 2026 11:47:10 +0200 Subject: [PATCH 8/8] . --- sentry_sdk/integrations/starlette.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/sentry_sdk/integrations/starlette.py b/sentry_sdk/integrations/starlette.py index 5977e3208c..8b1e485d9e 100644 --- a/sentry_sdk/integrations/starlette.py +++ b/sentry_sdk/integrations/starlette.py @@ -48,14 +48,9 @@ Dict, Optional, Tuple, - TypeVar, Union, ) - from starlette.middleware import _MiddlewareFactory - - _MiddlewareClass = TypeVar("_MiddlewareClass", bound=_MiddlewareFactory[...]) - from sentry_sdk._types import Event, HttpStatusCodeRange try: import starlette @@ -170,8 +165,8 @@ def setup_once() -> None: def _enable_span_for_middleware( - middleware_class: "_MiddlewareClass", -) -> "_MiddlewareClass": + middleware_class: "Any", +) -> "Any": old_call: "Callable[..., Awaitable[Any]]" = middleware_class.__call__ async def _create_span_call( @@ -431,7 +426,7 @@ def patch_middlewares() -> None: if not_yet_patched: def _sentry_middleware_init( - self: "Any", cls: "_MiddlewareFactory[...]", *args: "Any", **kwargs: "Any" + self: "Any", cls: "Any", *args: "Any", **kwargs: "Any" ) -> None: if cls == SentryAsgiMiddleware: return old_middleware_init(self, cls, *args, **kwargs)