From f109f85ace8c103e69065d1f5d0af8a60f632ac5 Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Thu, 26 Jun 2025 15:17:58 +0200 Subject: [PATCH 1/2] Migrate typing for integrations - part 2 --- sentry_sdk/integrations/chalice.py | 18 +++-- sentry_sdk/integrations/clickhouse_driver.py | 52 ++++++-------- .../integrations/cloud_resource_context.py | 25 +++---- sentry_sdk/integrations/cohere.py | 30 ++++---- sentry_sdk/integrations/dedupe.py | 13 ++-- sentry_sdk/integrations/dramatiq.py | 42 +++++------ sentry_sdk/integrations/excepthook.py | 20 +++--- sentry_sdk/integrations/executing.py | 7 +- sentry_sdk/integrations/falcon.py | 69 ++++++++----------- sentry_sdk/integrations/fastapi.py | 29 ++++---- sentry_sdk/integrations/flask.py | 69 +++++++++---------- sentry_sdk/integrations/gcp.py | 29 ++++---- sentry_sdk/integrations/gnu_backtrace.py | 10 ++- sentry_sdk/integrations/gql.py | 33 +++++---- sentry_sdk/integrations/graphene.py | 25 +++---- sentry_sdk/integrations/httpx.py | 21 +++--- sentry_sdk/integrations/huey.py | 33 ++++----- sentry_sdk/integrations/huggingface_hub.py | 22 +++--- 18 files changed, 236 insertions(+), 311 deletions(-) diff --git a/sentry_sdk/integrations/chalice.py b/sentry_sdk/integrations/chalice.py index 947e41ebf7..8a4e95ba00 100644 --- a/sentry_sdk/integrations/chalice.py +++ b/sentry_sdk/integrations/chalice.py @@ -1,3 +1,4 @@ +from __future__ import annotations import sys from functools import wraps @@ -32,8 +33,7 @@ class EventSourceHandler(ChaliceEventSourceHandler): # type: ignore - def __call__(self, event, context): - # type: (Any, Any) -> Any + def __call__(self, event: Any, context: Any) -> Any: client = sentry_sdk.get_client() with sentry_sdk.isolation_scope() as scope: @@ -56,11 +56,9 @@ def __call__(self, event, context): reraise(*exc_info) -def _get_view_function_response(app, view_function, function_args): - # type: (Any, F, Any) -> F +def _get_view_function_response(app: Any, view_function: F, function_args: Any) -> F: @wraps(view_function) - def wrapped_view_function(**function_args): - # type: (**Any) -> Any + def wrapped_view_function(**function_args: Any) -> Any: client = sentry_sdk.get_client() with sentry_sdk.isolation_scope() as scope: with capture_internal_exceptions(): @@ -99,8 +97,7 @@ class ChaliceIntegration(Integration): identifier = "chalice" @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: version = parse_version(CHALICE_VERSION) @@ -116,8 +113,9 @@ def setup_once(): RestAPIEventHandler._get_view_function_response ) - def sentry_event_response(app, view_function, function_args): - # type: (Any, F, Dict[str, Any]) -> Any + def sentry_event_response( + app: Any, view_function: F, function_args: Dict[str, Any] + ) -> Any: wrapped_view_function = _get_view_function_response( app, view_function, function_args ) diff --git a/sentry_sdk/integrations/clickhouse_driver.py b/sentry_sdk/integrations/clickhouse_driver.py index 7c908b7d6d..5d89eb0e76 100644 --- a/sentry_sdk/integrations/clickhouse_driver.py +++ b/sentry_sdk/integrations/clickhouse_driver.py @@ -1,3 +1,4 @@ +from __future__ import annotations import sentry_sdk from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations import _check_minimum_version, Integration, DidNotEnable @@ -9,27 +10,13 @@ ensure_integration_enabled, ) -from typing import TYPE_CHECKING, cast, Any, Dict, TypeVar +from typing import TYPE_CHECKING -# Hack to get new Python features working in older versions -# without introducing a hard dependency on `typing_extensions` -# from: https://stackoverflow.com/a/71944042/300572 if TYPE_CHECKING: - from typing import ParamSpec, Callable -else: - # Fake ParamSpec - class ParamSpec: - def __init__(self, _): - self.args = None - self.kwargs = None + from typing import ParamSpec, Callable, Any, Dict, TypeVar - # Callable[anything] will return None - class _Callable: - def __getitem__(self, _): - return None - - # Make instances - Callable = _Callable() + P = ParamSpec("P") + T = TypeVar("T") try: @@ -72,10 +59,6 @@ def setup_once() -> None: ) -P = ParamSpec("P") -T = TypeVar("T") - - def _wrap_start(f: Callable[P, T]) -> Callable[P, T]: @ensure_integration_enabled(ClickhouseDriverIntegration, f) def _inner(*args: P.args, **kwargs: P.kwargs) -> T: @@ -93,8 +76,7 @@ def _inner(*args: P.args, **kwargs: P.kwargs) -> T: connection._sentry_span = span # type: ignore[attr-defined] - data = _get_db_data(connection) - data = cast("dict[str, Any]", data) + data: dict[str, Any] = _get_db_data(connection) data["db.query.text"] = query if query_id: @@ -117,7 +99,11 @@ def _inner(*args: P.args, **kwargs: P.kwargs) -> T: def _wrap_end(f: Callable[P, T]) -> Callable[P, T]: def _inner_end(*args: P.args, **kwargs: P.kwargs) -> T: res = f(*args, **kwargs) - client = cast("clickhouse_driver.client.Client", args[0]) + + client = args[0] + if not isinstance(client, clickhouse_driver.client.Client): + return res + connection = client.connection span = getattr(connection, "_sentry_span", None) @@ -150,9 +136,11 @@ def _inner_end(*args: P.args, **kwargs: P.kwargs) -> T: def _wrap_send_data(f: Callable[P, T]) -> Callable[P, T]: def _inner_send_data(*args: P.args, **kwargs: P.kwargs) -> T: - client = cast("clickhouse_driver.client.Client", args[0]) + client = args[0] + if not isinstance(client, clickhouse_driver.client.Client): + return f(*args, **kwargs) + connection = client.connection - db_params_data = cast("list[Any]", args[2]) span = getattr(connection, "_sentry_span", None) if span is not None: @@ -160,11 +148,13 @@ def _inner_send_data(*args: P.args, **kwargs: P.kwargs) -> T: _set_on_span(span, data) if should_send_default_pii(): - saved_db_data = getattr( + saved_db_data: dict[str, Any] = getattr( connection, "_sentry_db_data", {} - ) # type: dict[str, Any] - db_params = saved_db_data.get("db.params") or [] # type: list[Any] - db_params.extend(db_params_data) + ) + db_params: list[Any] = saved_db_data.get("db.params") or [] + db_params_data = args[2] + if isinstance(db_params_data, list): + db_params.extend(db_params_data) saved_db_data["db.params"] = db_params span.set_attribute("db.params", _serialize_span_attribute(db_params)) diff --git a/sentry_sdk/integrations/cloud_resource_context.py b/sentry_sdk/integrations/cloud_resource_context.py index ca5ae47e6b..607899a5a7 100644 --- a/sentry_sdk/integrations/cloud_resource_context.py +++ b/sentry_sdk/integrations/cloud_resource_context.py @@ -1,3 +1,4 @@ +from __future__ import annotations import json import urllib3 @@ -65,13 +66,11 @@ class CloudResourceContextIntegration(Integration): gcp_metadata = None - def __init__(self, cloud_provider=""): - # type: (str) -> None + def __init__(self, cloud_provider: str = "") -> None: CloudResourceContextIntegration.cloud_provider = cloud_provider @classmethod - def _is_aws(cls): - # type: () -> bool + def _is_aws(cls) -> bool: try: r = cls.http.request( "PUT", @@ -95,8 +94,7 @@ def _is_aws(cls): return False @classmethod - def _get_aws_context(cls): - # type: () -> Dict[str, str] + def _get_aws_context(cls) -> Dict[str, str]: ctx = { "cloud.provider": CLOUD_PROVIDER.AWS, "cloud.platform": CLOUD_PLATFORM.AWS_EC2, @@ -149,8 +147,7 @@ def _get_aws_context(cls): return ctx @classmethod - def _is_gcp(cls): - # type: () -> bool + def _is_gcp(cls) -> bool: try: r = cls.http.request( "GET", @@ -174,8 +171,7 @@ def _is_gcp(cls): return False @classmethod - def _get_gcp_context(cls): - # type: () -> Dict[str, str] + def _get_gcp_context(cls) -> Dict[str, str]: ctx = { "cloud.provider": CLOUD_PROVIDER.GCP, "cloud.platform": CLOUD_PLATFORM.GCP_COMPUTE_ENGINE, @@ -229,8 +225,7 @@ def _get_gcp_context(cls): return ctx @classmethod - def _get_cloud_provider(cls): - # type: () -> str + def _get_cloud_provider(cls) -> str: if cls._is_aws(): return CLOUD_PROVIDER.AWS @@ -240,8 +235,7 @@ def _get_cloud_provider(cls): return "" @classmethod - def _get_cloud_resource_context(cls): - # type: () -> Dict[str, str] + def _get_cloud_resource_context(cls) -> Dict[str, str]: cloud_provider = ( cls.cloud_provider if cls.cloud_provider != "" @@ -253,8 +247,7 @@ def _get_cloud_resource_context(cls): return {} @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: cloud_provider = CloudResourceContextIntegration.cloud_provider unsupported_cloud_provider = ( cloud_provider != "" and cloud_provider not in context_getters.keys() diff --git a/sentry_sdk/integrations/cohere.py b/sentry_sdk/integrations/cohere.py index 6fd9fc8150..2eb22c76e8 100644 --- a/sentry_sdk/integrations/cohere.py +++ b/sentry_sdk/integrations/cohere.py @@ -1,3 +1,4 @@ +from __future__ import annotations from functools import wraps from sentry_sdk import consts @@ -70,20 +71,17 @@ class CohereIntegration(Integration): identifier = "cohere" origin = f"auto.ai.{identifier}" - def __init__(self, include_prompts=True): - # type: (CohereIntegration, bool) -> None + def __init__(self: CohereIntegration, include_prompts: bool = True) -> None: self.include_prompts = include_prompts @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: BaseCohere.chat = _wrap_chat(BaseCohere.chat, streaming=False) Client.embed = _wrap_embed(Client.embed) BaseCohere.chat_stream = _wrap_chat(BaseCohere.chat_stream, streaming=True) -def _capture_exception(exc): - # type: (Any) -> None +def _capture_exception(exc: Any) -> None: event, hint = event_from_exception( exc, client_options=sentry_sdk.get_client().options, @@ -92,11 +90,11 @@ def _capture_exception(exc): sentry_sdk.capture_event(event, hint=hint) -def _wrap_chat(f, streaming): - # type: (Callable[..., Any], bool) -> Callable[..., Any] +def _wrap_chat(f: Callable[..., Any], streaming: bool) -> Callable[..., Any]: - def collect_chat_response_fields(span, res, include_pii): - # type: (Span, NonStreamedChatResponse, bool) -> None + def collect_chat_response_fields( + span: Span, res: NonStreamedChatResponse, include_pii: bool + ) -> None: if include_pii: if hasattr(res, "text"): set_data_normalized( @@ -130,8 +128,7 @@ def collect_chat_response_fields(span, res, include_pii): set_data_normalized(span, SPANDATA.AI_WARNINGS, res.meta.warnings) @wraps(f) - def new_chat(*args, **kwargs): - # type: (*Any, **Any) -> Any + def new_chat(*args: Any, **kwargs: Any) -> Any: integration = sentry_sdk.get_client().get_integration(CohereIntegration) if ( @@ -185,8 +182,7 @@ def new_chat(*args, **kwargs): if streaming: old_iterator = res - def new_iterator(): - # type: () -> Iterator[StreamedChatResponse] + def new_iterator() -> Iterator[StreamedChatResponse]: with capture_internal_exceptions(): for x in old_iterator: @@ -220,12 +216,10 @@ def new_iterator(): return new_chat -def _wrap_embed(f): - # type: (Callable[..., Any]) -> Callable[..., Any] +def _wrap_embed(f: Callable[..., Any]) -> Callable[..., Any]: @wraps(f) - def new_embed(*args, **kwargs): - # type: (*Any, **Any) -> Any + def new_embed(*args: Any, **kwargs: Any) -> Any: integration = sentry_sdk.get_client().get_integration(CohereIntegration) if integration is None: return f(*args, **kwargs) diff --git a/sentry_sdk/integrations/dedupe.py b/sentry_sdk/integrations/dedupe.py index a115e35292..2434b531cb 100644 --- a/sentry_sdk/integrations/dedupe.py +++ b/sentry_sdk/integrations/dedupe.py @@ -1,3 +1,4 @@ +from __future__ import annotations import sentry_sdk from sentry_sdk.utils import ContextVar from sentry_sdk.integrations import Integration @@ -14,16 +15,13 @@ class DedupeIntegration(Integration): identifier = "dedupe" - def __init__(self): - # type: () -> None + def __init__(self) -> None: self._last_seen = ContextVar("last-seen") @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: @add_global_event_processor - def processor(event, hint): - # type: (Event, Optional[Hint]) -> Optional[Event] + def processor(event: Event, hint: Optional[Hint]) -> Optional[Event]: if hint is None: return event @@ -42,8 +40,7 @@ def processor(event, hint): return event @staticmethod - def reset_last_seen(): - # type: () -> None + def reset_last_seen() -> None: integration = sentry_sdk.get_client().get_integration(DedupeIntegration) if integration is None: return diff --git a/sentry_sdk/integrations/dramatiq.py b/sentry_sdk/integrations/dramatiq.py index a756b4c669..76abf243bc 100644 --- a/sentry_sdk/integrations/dramatiq.py +++ b/sentry_sdk/integrations/dramatiq.py @@ -1,3 +1,4 @@ +from __future__ import annotations import json import sentry_sdk @@ -36,17 +37,14 @@ class DramatiqIntegration(Integration): identifier = "dramatiq" @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: _patch_dramatiq_broker() -def _patch_dramatiq_broker(): - # type: () -> None +def _patch_dramatiq_broker() -> None: original_broker__init__ = Broker.__init__ - def sentry_patched_broker__init__(self, *args, **kw): - # type: (Broker, *Any, **Any) -> None + def sentry_patched_broker__init__(self: Broker, *args: Any, **kw: Any) -> None: integration = sentry_sdk.get_client().get_integration(DramatiqIntegration) try: @@ -85,8 +83,7 @@ class SentryMiddleware(Middleware): # type: ignore[misc] DramatiqIntegration. """ - def before_process_message(self, broker, message): - # type: (Broker, Message) -> None + def before_process_message(self, broker: Broker, message: Message) -> None: integration = sentry_sdk.get_client().get_integration(DramatiqIntegration) if integration is None: return @@ -99,8 +96,14 @@ def before_process_message(self, broker, message): scope.set_extra("dramatiq_message_id", message.message_id) scope.add_event_processor(_make_message_event_processor(message, integration)) - def after_process_message(self, broker, message, *, result=None, exception=None): - # type: (Broker, Message, Any, Optional[Any], Optional[Exception]) -> None + def after_process_message( + self: Broker, + broker: Message, + message: Any, + *, + result: Optional[Any] = None, + exception: Optional[Exception] = None, + ) -> None: integration = sentry_sdk.get_client().get_integration(DramatiqIntegration) if integration is None: return @@ -127,11 +130,11 @@ def after_process_message(self, broker, message, *, result=None, exception=None) message._scope_manager.__exit__(None, None, None) -def _make_message_event_processor(message, integration): - # type: (Message, DramatiqIntegration) -> Callable[[Event, Hint], Optional[Event]] +def _make_message_event_processor( + message: Message, integration: DramatiqIntegration +) -> Callable[[Event, Hint], Optional[Event]]: - def inner(event, hint): - # type: (Event, Hint) -> Optional[Event] + def inner(event: Event, hint: Hint) -> Optional[Event]: with capture_internal_exceptions(): DramatiqMessageExtractor(message).extract_into_event(event) @@ -141,16 +144,13 @@ def inner(event, hint): class DramatiqMessageExtractor: - def __init__(self, message): - # type: (Message) -> None + def __init__(self, message: Message) -> None: self.message_data = dict(message.asdict()) - def content_length(self): - # type: () -> int + def content_length(self) -> int: return len(json.dumps(self.message_data)) - def extract_into_event(self, event): - # type: (Event) -> None + def extract_into_event(self, event: Event) -> None: client = sentry_sdk.get_client() if not client.is_active(): return @@ -159,7 +159,7 @@ def extract_into_event(self, event): request_info = contexts.setdefault("dramatiq", {}) request_info["type"] = "dramatiq" - data = None # type: Optional[Union[AnnotatedValue, Dict[str, Any]]] + data: Optional[Union[AnnotatedValue, Dict[str, Any]]] = None if not request_body_within_bounds(client, self.content_length()): data = AnnotatedValue.removed_because_over_size_limit() else: diff --git a/sentry_sdk/integrations/excepthook.py b/sentry_sdk/integrations/excepthook.py index 61c7e460bf..ad3f7a82b6 100644 --- a/sentry_sdk/integrations/excepthook.py +++ b/sentry_sdk/integrations/excepthook.py @@ -1,3 +1,4 @@ +from __future__ import annotations import sys import sentry_sdk @@ -28,8 +29,7 @@ class ExcepthookIntegration(Integration): always_run = False - def __init__(self, always_run=False): - # type: (bool) -> None + def __init__(self, always_run: bool = False) -> None: if not isinstance(always_run, bool): raise ValueError( @@ -39,15 +39,16 @@ def __init__(self, always_run=False): self.always_run = always_run @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: sys.excepthook = _make_excepthook(sys.excepthook) -def _make_excepthook(old_excepthook): - # type: (Excepthook) -> Excepthook - def sentry_sdk_excepthook(type_, value, traceback): - # type: (Type[BaseException], BaseException, Optional[TracebackType]) -> None +def _make_excepthook(old_excepthook: Excepthook) -> Excepthook: + def sentry_sdk_excepthook( + type_: Type[BaseException], + value: BaseException, + traceback: Optional[TracebackType], + ) -> None: integration = sentry_sdk.get_client().get_integration(ExcepthookIntegration) # Note: If we replace this with ensure_integration_enabled then @@ -70,8 +71,7 @@ def sentry_sdk_excepthook(type_, value, traceback): return sentry_sdk_excepthook -def _should_send(always_run=False): - # type: (bool) -> bool +def _should_send(always_run: bool = False) -> bool: if always_run: return True diff --git a/sentry_sdk/integrations/executing.py b/sentry_sdk/integrations/executing.py index 6e68b8c0c7..649af64e58 100644 --- a/sentry_sdk/integrations/executing.py +++ b/sentry_sdk/integrations/executing.py @@ -1,3 +1,4 @@ +from __future__ import annotations import sentry_sdk from sentry_sdk.integrations import Integration, DidNotEnable from sentry_sdk.scope import add_global_event_processor @@ -20,12 +21,10 @@ class ExecutingIntegration(Integration): identifier = "executing" @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: @add_global_event_processor - def add_executing_info(event, hint): - # type: (Event, Optional[Hint]) -> Optional[Event] + def add_executing_info(event: Event, hint: Optional[Hint]) -> Optional[Event]: if sentry_sdk.get_client().get_integration(ExecutingIntegration) is None: return event diff --git a/sentry_sdk/integrations/falcon.py b/sentry_sdk/integrations/falcon.py index 9038c01a3f..622f8bb3a0 100644 --- a/sentry_sdk/integrations/falcon.py +++ b/sentry_sdk/integrations/falcon.py @@ -1,3 +1,4 @@ +from __future__ import annotations import sentry_sdk from sentry_sdk.consts import SOURCE_FOR_STYLE from sentry_sdk.integrations import _check_minimum_version, Integration, DidNotEnable @@ -33,30 +34,25 @@ falcon_app_class = falcon.App -_FALCON_UNSET = None # type: Optional[object] +_FALCON_UNSET: Optional[object] = None with capture_internal_exceptions(): from falcon.request import _UNSET as _FALCON_UNSET # type: ignore[import-not-found, no-redef] class FalconRequestExtractor(RequestExtractor): - def env(self): - # type: () -> Dict[str, Any] + def env(self) -> Dict[str, Any]: return self.request.env - def cookies(self): - # type: () -> Dict[str, Any] + def cookies(self) -> Dict[str, Any]: return self.request.cookies - def form(self): - # type: () -> None + def form(self) -> None: return None # No such concept in Falcon - def files(self): - # type: () -> None + def files(self) -> None: return None # No such concept in Falcon - def raw_data(self): - # type: () -> Optional[str] + def raw_data(self) -> Optional[str]: # As request data can only be read once we won't make this available # to Sentry. Just send back a dummy string in case there was a @@ -68,8 +64,7 @@ def raw_data(self): else: return None - def json(self): - # type: () -> Optional[Dict[str, Any]] + def json(self) -> Optional[Dict[str, Any]]: # fallback to cached_media = None if self.request._media is not available cached_media = None with capture_internal_exceptions(): @@ -90,8 +85,7 @@ def json(self): class SentryFalconMiddleware: """Captures exceptions in Falcon requests and send to Sentry""" - def process_request(self, req, resp, *args, **kwargs): - # type: (Any, Any, *Any, **Any) -> None + def process_request(self, req: Any, resp: Any, *args: Any, **kwargs: Any) -> None: integration = sentry_sdk.get_client().get_integration(FalconIntegration) if integration is None: return @@ -110,8 +104,7 @@ class FalconIntegration(Integration): transaction_style = "" - def __init__(self, transaction_style="uri_template"): - # type: (str) -> None + def __init__(self, transaction_style: str = "uri_template") -> None: if transaction_style not in TRANSACTION_STYLE_VALUES: raise ValueError( "Invalid value for transaction_style: %s (must be in %s)" @@ -120,8 +113,7 @@ def __init__(self, transaction_style="uri_template"): self.transaction_style = transaction_style @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: version = parse_version(FALCON_VERSION) _check_minimum_version(FalconIntegration, version) @@ -131,12 +123,10 @@ def setup_once(): _patch_prepare_middleware() -def _patch_wsgi_app(): - # type: () -> None +def _patch_wsgi_app() -> None: original_wsgi_app = falcon_app_class.__call__ - def sentry_patched_wsgi_app(self, env, start_response): - # type: (falcon.API, Any, Any) -> Any + def sentry_patched_wsgi_app(self: falcon.API, env: Any, start_response: Any) -> Any: integration = sentry_sdk.get_client().get_integration(FalconIntegration) if integration is None: return original_wsgi_app(self, env, start_response) @@ -151,13 +141,11 @@ def sentry_patched_wsgi_app(self, env, start_response): falcon_app_class.__call__ = sentry_patched_wsgi_app -def _patch_handle_exception(): - # type: () -> None +def _patch_handle_exception() -> None: original_handle_exception = falcon_app_class._handle_exception @ensure_integration_enabled(FalconIntegration, original_handle_exception) - def sentry_patched_handle_exception(self, *args): - # type: (falcon.API, *Any) -> Any + def sentry_patched_handle_exception(self: falcon.API, *args: Any) -> Any: # NOTE(jmagnusson): falcon 2.0 changed falcon.API._handle_exception # method signature from `(ex, req, resp, params)` to # `(req, resp, ex, params)` @@ -189,14 +177,12 @@ def sentry_patched_handle_exception(self, *args): falcon_app_class._handle_exception = sentry_patched_handle_exception -def _patch_prepare_middleware(): - # type: () -> None +def _patch_prepare_middleware() -> None: original_prepare_middleware = falcon_helpers.prepare_middleware def sentry_patched_prepare_middleware( - middleware=None, independent_middleware=False, asgi=False - ): - # type: (Any, Any, bool) -> Any + middleware: Any = None, independent_middleware: Any = False, asgi: bool = False + ) -> Any: if asgi: # We don't support ASGI Falcon apps, so we don't patch anything here return original_prepare_middleware(middleware, independent_middleware, asgi) @@ -212,8 +198,7 @@ def sentry_patched_prepare_middleware( falcon_helpers.prepare_middleware = sentry_patched_prepare_middleware -def _exception_leads_to_http_5xx(ex, response): - # type: (Exception, falcon.Response) -> bool +def _exception_leads_to_http_5xx(ex: Exception, response: falcon.Response) -> bool: is_server_error = isinstance(ex, falcon.HTTPError) and (ex.status or "").startswith( "5" ) @@ -224,13 +209,13 @@ def _exception_leads_to_http_5xx(ex, response): return (is_server_error or is_unhandled_error) and _has_http_5xx_status(response) -def _has_http_5xx_status(response): - # type: (falcon.Response) -> bool +def _has_http_5xx_status(response: falcon.Response) -> bool: return response.status.startswith("5") -def _set_transaction_name_and_source(event, transaction_style, request): - # type: (Event, str, falcon.Request) -> None +def _set_transaction_name_and_source( + event: Event, transaction_style: str, request: falcon.Request +) -> None: name_for_style = { "uri_template": request.uri_template, "path": request.path, @@ -239,11 +224,11 @@ def _set_transaction_name_and_source(event, transaction_style, request): event["transaction_info"] = {"source": SOURCE_FOR_STYLE[transaction_style]} -def _make_request_event_processor(req, integration): - # type: (falcon.Request, FalconIntegration) -> EventProcessor +def _make_request_event_processor( + req: falcon.Request, integration: FalconIntegration +) -> EventProcessor: - def event_processor(event, hint): - # type: (Event, dict[str, Any]) -> Event + def event_processor(event: Event, hint: dict[str, Any]) -> Event: _set_transaction_name_and_source(event, integration.transaction_style, req) with capture_internal_exceptions(): diff --git a/sentry_sdk/integrations/fastapi.py b/sentry_sdk/integrations/fastapi.py index 0e087e3975..10391fe934 100644 --- a/sentry_sdk/integrations/fastapi.py +++ b/sentry_sdk/integrations/fastapi.py @@ -1,3 +1,4 @@ +from __future__ import annotations import asyncio from copy import deepcopy from functools import wraps @@ -38,13 +39,13 @@ class FastApiIntegration(StarletteIntegration): identifier = "fastapi" @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: patch_get_request_handler() -def _set_transaction_name_and_source(scope, transaction_style, request): - # type: (sentry_sdk.Scope, str, Any) -> None +def _set_transaction_name_and_source( + scope: sentry_sdk.Scope, transaction_style: str, request: Any +) -> None: name = "" if transaction_style == "endpoint": @@ -71,12 +72,10 @@ def _set_transaction_name_and_source(scope, transaction_style, request): ) -def patch_get_request_handler(): - # type: () -> None +def patch_get_request_handler() -> None: old_get_request_handler = fastapi.routing.get_request_handler - def _sentry_get_request_handler(*args, **kwargs): - # type: (*Any, **Any) -> Any + def _sentry_get_request_handler(*args: Any, **kwargs: Any) -> Any: dependant = kwargs.get("dependant") if ( dependant @@ -86,8 +85,7 @@ def _sentry_get_request_handler(*args, **kwargs): old_call = dependant.call @wraps(old_call) - def _sentry_call(*args, **kwargs): - # type: (*Any, **Any) -> Any + def _sentry_call(*args: Any, **kwargs: Any) -> Any: current_scope = sentry_sdk.get_current_scope() if current_scope.root_span is not None: current_scope.root_span.update_active_thread() @@ -102,8 +100,7 @@ def _sentry_call(*args, **kwargs): old_app = old_get_request_handler(*args, **kwargs) - async def _sentry_app(*args, **kwargs): - # type: (*Any, **Any) -> Any + async def _sentry_app(*args: Any, **kwargs: Any) -> Any: integration = sentry_sdk.get_client().get_integration(FastApiIntegration) if integration is None: return await old_app(*args, **kwargs) @@ -117,10 +114,10 @@ async def _sentry_app(*args, **kwargs): extractor = StarletteRequestExtractor(request) info = await extractor.extract_request_info() - def _make_request_event_processor(req, integration): - # type: (Any, Any) -> Callable[[Event, Dict[str, Any]], Event] - def event_processor(event, hint): - # type: (Event, Dict[str, Any]) -> Event + def _make_request_event_processor( + req: Any, integration: Any + ) -> Callable[[Event, Dict[str, Any]], Event]: + def event_processor(event: Event, hint: Dict[str, Any]) -> Event: # Extract information from request request_info = event.get("request", {}) diff --git a/sentry_sdk/integrations/flask.py b/sentry_sdk/integrations/flask.py index 9223eacd24..708bcd01f9 100644 --- a/sentry_sdk/integrations/flask.py +++ b/sentry_sdk/integrations/flask.py @@ -1,3 +1,4 @@ +from __future__ import annotations import sentry_sdk from sentry_sdk.consts import SOURCE_FOR_STYLE from sentry_sdk.integrations import _check_minimum_version, DidNotEnable, Integration @@ -57,10 +58,9 @@ class FlaskIntegration(Integration): def __init__( self, - transaction_style="endpoint", # type: str - http_methods_to_capture=DEFAULT_HTTP_METHODS_TO_CAPTURE, # type: tuple[str, ...] - ): - # type: (...) -> None + transaction_style: str = "endpoint", + http_methods_to_capture: tuple[str, ...] = DEFAULT_HTTP_METHODS_TO_CAPTURE, + ) -> None: if transaction_style not in TRANSACTION_STYLE_VALUES: raise ValueError( "Invalid value for transaction_style: %s (must be in %s)" @@ -70,8 +70,7 @@ def __init__( self.http_methods_to_capture = tuple(map(str.upper, http_methods_to_capture)) @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: try: from quart import Quart # type: ignore @@ -93,8 +92,9 @@ def setup_once(): old_app = Flask.__call__ - def sentry_patched_wsgi_app(self, environ, start_response): - # type: (Any, Dict[str, str], Callable[..., Any]) -> _ScopedResponse + def sentry_patched_wsgi_app( + self: Any, environ: Dict[str, str], start_response: Callable[..., Any] + ) -> _ScopedResponse: if sentry_sdk.get_client().get_integration(FlaskIntegration) is None: return old_app(self, environ, start_response) @@ -114,8 +114,9 @@ def sentry_patched_wsgi_app(self, environ, start_response): Flask.__call__ = sentry_patched_wsgi_app -def _add_sentry_trace(sender, template, context, **extra): - # type: (Flask, Any, Dict[str, Any], **Any) -> None +def _add_sentry_trace( + sender: Flask, template: Any, context: Dict[str, Any], **extra: Any +) -> None: if "sentry_trace" in context: return @@ -125,8 +126,9 @@ def _add_sentry_trace(sender, template, context, **extra): context["sentry_trace_meta"] = trace_meta -def _set_transaction_name_and_source(scope, transaction_style, request): - # type: (sentry_sdk.Scope, str, Request) -> None +def _set_transaction_name_and_source( + scope: sentry_sdk.Scope, transaction_style: str, request: Request +) -> None: try: name_for_style = { "url": request.url_rule.rule, @@ -140,8 +142,7 @@ def _set_transaction_name_and_source(scope, transaction_style, request): pass -def _request_started(app, **kwargs): - # type: (Flask, **Any) -> None +def _request_started(app: Flask, **kwargs: Any) -> None: integration = sentry_sdk.get_client().get_integration(FlaskIntegration) if integration is None: return @@ -160,47 +161,39 @@ def _request_started(app, **kwargs): class FlaskRequestExtractor(RequestExtractor): - def env(self): - # type: () -> Dict[str, str] + def env(self) -> Dict[str, str]: return self.request.environ - def cookies(self): - # type: () -> Dict[Any, Any] + def cookies(self) -> Dict[Any, Any]: return { k: v[0] if isinstance(v, list) and len(v) == 1 else v for k, v in self.request.cookies.items() } - def raw_data(self): - # type: () -> bytes + def raw_data(self) -> bytes: return self.request.get_data() - def form(self): - # type: () -> ImmutableMultiDict[str, Any] + def form(self) -> ImmutableMultiDict[str, Any]: return self.request.form - def files(self): - # type: () -> ImmutableMultiDict[str, Any] + def files(self) -> ImmutableMultiDict[str, Any]: return self.request.files - def is_json(self): - # type: () -> bool + def is_json(self) -> bool: return self.request.is_json - def json(self): - # type: () -> Any + def json(self) -> Any: return self.request.get_json(silent=True) - def size_of_file(self, file): - # type: (FileStorage) -> int + def size_of_file(self, file: FileStorage) -> int: return file.content_length -def _make_request_event_processor(app, request, integration): - # type: (Flask, Callable[[], Request], FlaskIntegration) -> EventProcessor +def _make_request_event_processor( + app: Flask, request: Callable[[], Request], integration: FlaskIntegration +) -> EventProcessor: - def inner(event, hint): - # type: (Event, dict[str, Any]) -> Event + def inner(event: Event, hint: dict[str, Any]) -> Event: # if the request is gone we are fine not logging the data from # it. This might happen if the processor is pushed away to @@ -221,8 +214,9 @@ def inner(event, hint): @ensure_integration_enabled(FlaskIntegration) -def _capture_exception(sender, exception, **kwargs): - # type: (Flask, Union[ValueError, BaseException], **Any) -> None +def _capture_exception( + sender: Flask, exception: Union[ValueError, BaseException], **kwargs: Any +) -> None: event, hint = event_from_exception( exception, client_options=sentry_sdk.get_client().options, @@ -232,8 +226,7 @@ def _capture_exception(sender, exception, **kwargs): sentry_sdk.capture_event(event, hint=hint) -def _add_user_to_event(event): - # type: (Event) -> None +def _add_user_to_event(event: Event) -> None: if flask_login is None: return diff --git a/sentry_sdk/integrations/gcp.py b/sentry_sdk/integrations/gcp.py index 97b72ff1ce..a347ce3ffe 100644 --- a/sentry_sdk/integrations/gcp.py +++ b/sentry_sdk/integrations/gcp.py @@ -1,3 +1,4 @@ +from __future__ import annotations import functools import sys from copy import deepcopy @@ -39,11 +40,11 @@ F = TypeVar("F", bound=Callable[..., Any]) -def _wrap_func(func): - # type: (F) -> F +def _wrap_func(func: F) -> F: @functools.wraps(func) - def sentry_func(functionhandler, gcp_event, *args, **kwargs): - # type: (Any, Any, *Any, **Any) -> Any + def sentry_func( + functionhandler: Any, gcp_event: Any, *args: Any, **kwargs: Any + ) -> Any: client = sentry_sdk.get_client() integration = client.get_integration(GcpIntegration) @@ -118,13 +119,11 @@ class GcpIntegration(Integration): identifier = "gcp" origin = f"auto.function.{identifier}" - def __init__(self, timeout_warning=False): - # type: (bool) -> None + def __init__(self, timeout_warning: bool = False) -> None: self.timeout_warning = timeout_warning @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: import __main__ as gcp_functions if not hasattr(gcp_functions, "worker_v1"): @@ -140,11 +139,11 @@ def setup_once(): ) -def _make_request_event_processor(gcp_event, configured_timeout, initial_time): - # type: (Any, Any, Any) -> EventProcessor +def _make_request_event_processor( + gcp_event: Any, configured_timeout: Any, initial_time: Any +) -> EventProcessor: - def event_processor(event, hint): - # type: (Event, Hint) -> Optional[Event] + def event_processor(event: Event, hint: Hint) -> Optional[Event]: final_time = datetime.now(timezone.utc) time_diff = final_time - initial_time @@ -195,8 +194,7 @@ def event_processor(event, hint): return event_processor -def _get_google_cloud_logs_url(final_time): - # type: (datetime) -> str +def _get_google_cloud_logs_url(final_time: datetime) -> str: """ Generates a Google Cloud Logs console URL based on the environment variables Arguments: @@ -238,8 +236,7 @@ def _get_google_cloud_logs_url(final_time): } -def _prepopulate_attributes(gcp_event): - # type: (Any) -> dict[str, Any] +def _prepopulate_attributes(gcp_event: Any) -> dict[str, Any]: attributes = { "cloud.provider": "gcp", } diff --git a/sentry_sdk/integrations/gnu_backtrace.py b/sentry_sdk/integrations/gnu_backtrace.py index dc3dc80fe0..c9d2e51409 100644 --- a/sentry_sdk/integrations/gnu_backtrace.py +++ b/sentry_sdk/integrations/gnu_backtrace.py @@ -1,3 +1,4 @@ +from __future__ import annotations import re import sentry_sdk @@ -38,17 +39,14 @@ class GnuBacktraceIntegration(Integration): identifier = "gnu_backtrace" @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: @add_global_event_processor - def process_gnu_backtrace(event, hint): - # type: (Event, dict[str, Any]) -> Event + def process_gnu_backtrace(event: Event, hint: dict[str, Any]) -> Event: with capture_internal_exceptions(): return _process_gnu_backtrace(event, hint) -def _process_gnu_backtrace(event, hint): - # type: (Event, dict[str, Any]) -> Event +def _process_gnu_backtrace(event: Event, hint: dict[str, Any]) -> Event: if sentry_sdk.get_client().get_integration(GnuBacktraceIntegration) is None: return event diff --git a/sentry_sdk/integrations/gql.py b/sentry_sdk/integrations/gql.py index 5f4436f5b2..a43f04a062 100644 --- a/sentry_sdk/integrations/gql.py +++ b/sentry_sdk/integrations/gql.py @@ -1,3 +1,4 @@ +from __future__ import annotations import sentry_sdk from sentry_sdk.utils import ( event_from_exception, @@ -34,19 +35,17 @@ class GQLIntegration(Integration): identifier = "gql" @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: gql_version = parse_version(gql.__version__) _check_minimum_version(GQLIntegration, gql_version) _patch_execute() -def _data_from_document(document): - # type: (DocumentNode) -> EventDataType +def _data_from_document(document: DocumentNode) -> EventDataType: try: operation_ast = get_operation_ast(document) - data = {"query": print_ast(document)} # type: EventDataType + data: EventDataType = {"query": print_ast(document)} if operation_ast is not None: data["variables"] = operation_ast.variable_definitions @@ -58,8 +57,7 @@ def _data_from_document(document): return dict() -def _transport_method(transport): - # type: (Union[Transport, AsyncTransport]) -> str +def _transport_method(transport: Union[Transport, AsyncTransport]) -> str: """ The RequestsHTTPTransport allows defining the HTTP method; all other transports use POST. @@ -70,8 +68,9 @@ def _transport_method(transport): return "POST" -def _request_info_from_transport(transport): - # type: (Union[Transport, AsyncTransport, None]) -> Dict[str, str] +def _request_info_from_transport( + transport: Union[Transport, AsyncTransport, None], +) -> Dict[str, str]: if transport is None: return {} @@ -87,13 +86,13 @@ def _request_info_from_transport(transport): return request_info -def _patch_execute(): - # type: () -> None +def _patch_execute() -> None: real_execute = gql.Client.execute @ensure_integration_enabled(GQLIntegration, real_execute) - def sentry_patched_execute(self, document, *args, **kwargs): - # type: (gql.Client, DocumentNode, Any, Any) -> Any + def sentry_patched_execute( + self: gql.Client, document: DocumentNode, *args: Any, **kwargs: Any + ) -> Any: scope = sentry_sdk.get_isolation_scope() scope.add_event_processor(_make_gql_event_processor(self, document)) @@ -112,10 +111,10 @@ def sentry_patched_execute(self, document, *args, **kwargs): gql.Client.execute = sentry_patched_execute -def _make_gql_event_processor(client, document): - # type: (gql.Client, DocumentNode) -> EventProcessor - def processor(event, hint): - # type: (Event, dict[str, Any]) -> Event +def _make_gql_event_processor( + client: gql.Client, document: DocumentNode +) -> EventProcessor: + def processor(event: Event, hint: dict[str, Any]) -> Event: try: errors = hint["exc_info"][1].errors except (AttributeError, KeyError): diff --git a/sentry_sdk/integrations/graphene.py b/sentry_sdk/integrations/graphene.py index 9269a4403c..c0ea3adb53 100644 --- a/sentry_sdk/integrations/graphene.py +++ b/sentry_sdk/integrations/graphene.py @@ -1,3 +1,4 @@ +from __future__ import annotations from contextlib import contextmanager import sentry_sdk @@ -31,22 +32,21 @@ class GrapheneIntegration(Integration): identifier = "graphene" @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: version = package_version("graphene") _check_minimum_version(GrapheneIntegration, version) _patch_graphql() -def _patch_graphql(): - # type: () -> None +def _patch_graphql() -> None: old_graphql_sync = graphene_schema.graphql_sync old_graphql_async = graphene_schema.graphql @ensure_integration_enabled(GrapheneIntegration, old_graphql_sync) - def _sentry_patched_graphql_sync(schema, source, *args, **kwargs): - # type: (GraphQLSchema, Union[str, Source], Any, Any) -> ExecutionResult + def _sentry_patched_graphql_sync( + schema: GraphQLSchema, source: Union[str, Source], *args: Any, **kwargs: Any + ) -> ExecutionResult: scope = sentry_sdk.get_isolation_scope() scope.add_event_processor(_event_processor) @@ -68,8 +68,9 @@ def _sentry_patched_graphql_sync(schema, source, *args, **kwargs): return result - async def _sentry_patched_graphql_async(schema, source, *args, **kwargs): - # type: (GraphQLSchema, Union[str, Source], Any, Any) -> ExecutionResult + async def _sentry_patched_graphql_async( + schema: GraphQLSchema, source: Union[str, Source], *args: Any, **kwargs: Any + ) -> ExecutionResult: integration = sentry_sdk.get_client().get_integration(GrapheneIntegration) if integration is None: return await old_graphql_async(schema, source, *args, **kwargs) @@ -99,8 +100,7 @@ async def _sentry_patched_graphql_async(schema, source, *args, **kwargs): graphene_schema.graphql = _sentry_patched_graphql_async -def _event_processor(event, hint): - # type: (Event, Dict[str, Any]) -> Event +def _event_processor(event: Event, hint: Dict[str, Any]) -> Event: if should_send_default_pii(): request_info = event.setdefault("request", {}) request_info["api_target"] = "graphql" @@ -112,8 +112,9 @@ def _event_processor(event, hint): @contextmanager -def graphql_span(schema, source, kwargs): - # type: (GraphQLSchema, Union[str, Source], Dict[str, Any]) -> Generator[None, None, None] +def graphql_span( + schema: GraphQLSchema, source: Union[str, Source], kwargs: Dict[str, Any] +) -> Generator[None, None, None]: operation_name = kwargs.get("operation_name") operation_type = "query" diff --git a/sentry_sdk/integrations/httpx.py b/sentry_sdk/integrations/httpx.py index 61ce75734b..46e83d49a8 100644 --- a/sentry_sdk/integrations/httpx.py +++ b/sentry_sdk/integrations/httpx.py @@ -1,3 +1,4 @@ +from __future__ import annotations import sentry_sdk from sentry_sdk.consts import OP, SPANDATA, BAGGAGE_HEADER_NAME from sentry_sdk.integrations import Integration, DidNotEnable @@ -32,8 +33,7 @@ class HttpxIntegration(Integration): origin = f"auto.http.{identifier}" @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: """ httpx has its own transport layer and can be customized when needed, so patch Client.send and AsyncClient.send to support both synchronous and async interfaces. @@ -42,13 +42,11 @@ def setup_once(): _install_httpx_async_client() -def _install_httpx_client(): - # type: () -> None +def _install_httpx_client() -> None: real_send = Client.send @ensure_integration_enabled(HttpxIntegration, real_send) - def send(self, request, **kwargs): - # type: (Client, Request, **Any) -> Response + def send(self: Client, request: Request, **kwargs: Any) -> Response: parsed_url = None with capture_internal_exceptions(): parsed_url = parse_url(str(request.url), sanitize=False) @@ -112,12 +110,10 @@ def send(self, request, **kwargs): Client.send = send -def _install_httpx_async_client(): - # type: () -> None +def _install_httpx_async_client() -> None: real_send = AsyncClient.send - async def send(self, request, **kwargs): - # type: (AsyncClient, Request, **Any) -> Response + async def send(self: AsyncClient, request: Request, **kwargs: Any) -> Response: if sentry_sdk.get_client().get_integration(HttpxIntegration) is None: return await real_send(self, request, **kwargs) @@ -184,8 +180,9 @@ async def send(self, request, **kwargs): AsyncClient.send = send -def _add_sentry_baggage_to_headers(headers, sentry_baggage): - # type: (MutableMapping[str, str], str) -> None +def _add_sentry_baggage_to_headers( + headers: MutableMapping[str, str], sentry_baggage: str +) -> None: """Add the Sentry baggage to the headers. This function directly mutates the provided headers. The provided sentry_baggage diff --git a/sentry_sdk/integrations/huey.py b/sentry_sdk/integrations/huey.py index 1d1c498843..7bd766b413 100644 --- a/sentry_sdk/integrations/huey.py +++ b/sentry_sdk/integrations/huey.py @@ -1,3 +1,4 @@ +from __future__ import annotations import sys from datetime import datetime @@ -45,19 +46,16 @@ class HueyIntegration(Integration): origin = f"auto.queue.{identifier}" @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: patch_enqueue() patch_execute() -def patch_enqueue(): - # type: () -> None +def patch_enqueue() -> None: old_enqueue = Huey.enqueue @ensure_integration_enabled(HueyIntegration, old_enqueue) - def _sentry_enqueue(self, task): - # type: (Huey, Task) -> Optional[Union[Result, ResultGroup]] + def _sentry_enqueue(self: Huey, task: Task) -> Optional[Union[Result, ResultGroup]]: with sentry_sdk.start_span( op=OP.QUEUE_SUBMIT_HUEY, name=task.name, @@ -77,10 +75,8 @@ def _sentry_enqueue(self, task): Huey.enqueue = _sentry_enqueue -def _make_event_processor(task): - # type: (Any) -> EventProcessor - def event_processor(event, hint): - # type: (Event, Hint) -> Optional[Event] +def _make_event_processor(task: Any) -> EventProcessor: + def event_processor(event: Event, hint: Hint) -> Optional[Event]: with capture_internal_exceptions(): tags = event.setdefault("tags", {}) @@ -107,8 +103,7 @@ def event_processor(event, hint): return event_processor -def _capture_exception(exc_info): - # type: (ExcInfo) -> None +def _capture_exception(exc_info: ExcInfo) -> None: scope = sentry_sdk.get_current_scope() if scope.root_span is not None: @@ -126,12 +121,10 @@ def _capture_exception(exc_info): scope.capture_event(event, hint=hint) -def _wrap_task_execute(func): - # type: (F) -> F +def _wrap_task_execute(func: F) -> F: @ensure_integration_enabled(HueyIntegration, func) - def _sentry_execute(*args, **kwargs): - # type: (*Any, **Any) -> Any + def _sentry_execute(*args: Any, **kwargs: Any) -> Any: try: result = func(*args, **kwargs) except Exception: @@ -148,13 +141,13 @@ def _sentry_execute(*args, **kwargs): return _sentry_execute # type: ignore -def patch_execute(): - # type: () -> None +def patch_execute() -> None: old_execute = Huey._execute @ensure_integration_enabled(HueyIntegration, old_execute) - def _sentry_execute(self, task, timestamp=None): - # type: (Huey, Task, Optional[datetime]) -> Any + def _sentry_execute( + self: Huey, task: Task, timestamp: Optional[datetime] = None + ) -> Any: with sentry_sdk.isolation_scope() as scope: with capture_internal_exceptions(): scope._name = "huey" diff --git a/sentry_sdk/integrations/huggingface_hub.py b/sentry_sdk/integrations/huggingface_hub.py index d9a4c2563e..dc8cc68631 100644 --- a/sentry_sdk/integrations/huggingface_hub.py +++ b/sentry_sdk/integrations/huggingface_hub.py @@ -1,3 +1,4 @@ +from __future__ import annotations from functools import wraps from sentry_sdk import consts @@ -27,13 +28,11 @@ class HuggingfaceHubIntegration(Integration): identifier = "huggingface_hub" origin = f"auto.ai.{identifier}" - def __init__(self, include_prompts=True): - # type: (HuggingfaceHubIntegration, bool) -> None + def __init__(self: HuggingfaceHubIntegration, include_prompts: bool = True) -> None: self.include_prompts = include_prompts @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: huggingface_hub.inference._client.InferenceClient.text_generation = ( _wrap_text_generation( huggingface_hub.inference._client.InferenceClient.text_generation @@ -41,8 +40,7 @@ def setup_once(): ) -def _capture_exception(exc): - # type: (Any) -> None +def _capture_exception(exc: Any) -> None: event, hint = event_from_exception( exc, client_options=sentry_sdk.get_client().options, @@ -51,11 +49,9 @@ def _capture_exception(exc): sentry_sdk.capture_event(event, hint=hint) -def _wrap_text_generation(f): - # type: (Callable[..., Any]) -> Callable[..., Any] +def _wrap_text_generation(f: Callable[..., Any]) -> Callable[..., Any]: @wraps(f) - def new_text_generation(*args, **kwargs): - # type: (*Any, **Any) -> Any + def new_text_generation(*args: Any, **kwargs: Any) -> Any: integration = sentry_sdk.get_client().get_integration(HuggingfaceHubIntegration) if integration is None: return f(*args, **kwargs) @@ -124,8 +120,7 @@ def new_text_generation(*args, **kwargs): if kwargs.get("details", False): # res is Iterable[TextGenerationStreamOutput] - def new_details_iterator(): - # type: () -> Iterable[ChatCompletionStreamOutput] + def new_details_iterator() -> Iterable[ChatCompletionStreamOutput]: with capture_internal_exceptions(): tokens_used = 0 data_buf: list[str] = [] @@ -153,8 +148,7 @@ def new_details_iterator(): else: # res is Iterable[str] - def new_iterator(): - # type: () -> Iterable[str] + def new_iterator() -> Iterable[str]: data_buf: list[str] = [] with capture_internal_exceptions(): for s in res: From c98ca0bc6966ecd432b4d16c07610e99e0734a25 Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Fri, 27 Jun 2025 15:14:34 +0200 Subject: [PATCH 2/2] Migrate typing for integrations - part 3 --- sentry_sdk/integrations/langchain.py | 200 +++++++++++++++--------- sentry_sdk/integrations/launchdarkly.py | 23 +-- sentry_sdk/integrations/litestar.py | 67 ++++---- sentry_sdk/integrations/logging.py | 56 +++---- sentry_sdk/integrations/loguru.py | 34 ++-- sentry_sdk/integrations/modules.py | 7 +- sentry_sdk/integrations/openai.py | 80 ++++------ sentry_sdk/integrations/openfeature.py | 17 +- sentry_sdk/integrations/pure_eval.py | 16 +- sentry_sdk/integrations/pymongo.py | 30 ++-- sentry_sdk/integrations/pyramid.py | 67 ++++---- sentry_sdk/integrations/quart.py | 51 +++--- sentry_sdk/integrations/ray.py | 31 ++-- sentry_sdk/integrations/rq.py | 29 ++-- sentry_sdk/integrations/rust_tracing.py | 15 +- 15 files changed, 366 insertions(+), 357 deletions(-) diff --git a/sentry_sdk/integrations/langchain.py b/sentry_sdk/integrations/langchain.py index 5f1524e445..fc7e54af8f 100644 --- a/sentry_sdk/integrations/langchain.py +++ b/sentry_sdk/integrations/langchain.py @@ -1,3 +1,4 @@ +from __future__ import annotations import itertools from collections import OrderedDict from functools import wraps @@ -60,37 +61,41 @@ class LangchainIntegration(Integration): max_spans = 1024 def __init__( - self, include_prompts=True, max_spans=1024, tiktoken_encoding_name=None - ): - # type: (LangchainIntegration, bool, int, Optional[str]) -> None + self: LangchainIntegration, + include_prompts: bool = True, + max_spans: int = 1024, + tiktoken_encoding_name: Optional[str] = None, + ) -> None: self.include_prompts = include_prompts self.max_spans = max_spans self.tiktoken_encoding_name = tiktoken_encoding_name @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: manager._configure = _wrap_configure(manager._configure) class WatchedSpan: - num_completion_tokens = 0 # type: int - num_prompt_tokens = 0 # type: int - no_collect_tokens = False # type: bool - children = [] # type: List[WatchedSpan] - is_pipeline = False # type: bool - - def __init__(self, span): - # type: (Span) -> None + num_completion_tokens: int = 0 + num_prompt_tokens: int = 0 + no_collect_tokens: bool = False + children: List[WatchedSpan] = [] + is_pipeline: bool = False + + def __init__(self, span: Span) -> None: self.span = span class SentryLangchainCallback(BaseCallbackHandler): # type: ignore[misc] """Base callback handler that can be used to handle callbacks from langchain.""" - def __init__(self, max_span_map_size, include_prompts, tiktoken_encoding_name=None): - # type: (int, bool, Optional[str]) -> None - self.span_map = OrderedDict() # type: OrderedDict[UUID, WatchedSpan] + def __init__( + self, + max_span_map_size: int, + include_prompts: bool, + tiktoken_encoding_name: Optional[str] = None, + ) -> None: + self.span_map: OrderedDict[UUID, WatchedSpan] = OrderedDict() self.max_span_map_size = max_span_map_size self.include_prompts = include_prompts @@ -100,21 +105,18 @@ def __init__(self, max_span_map_size, include_prompts, tiktoken_encoding_name=No self.tiktoken_encoding = tiktoken.get_encoding(tiktoken_encoding_name) - def count_tokens(self, s): - # type: (str) -> int + def count_tokens(self, s: str) -> int: if self.tiktoken_encoding is not None: return len(self.tiktoken_encoding.encode_ordinary(s)) return 0 - def gc_span_map(self): - # type: () -> None + def gc_span_map(self) -> None: while len(self.span_map) > self.max_span_map_size: run_id, watched_span = self.span_map.popitem(last=False) self._exit_span(watched_span, run_id) - def _handle_error(self, run_id, error): - # type: (UUID, Any) -> None + def _handle_error(self, run_id: UUID, error: Any) -> None: if not run_id or run_id not in self.span_map: return @@ -126,14 +128,17 @@ def _handle_error(self, run_id, error): span_data.span.finish() del self.span_map[run_id] - def _normalize_langchain_message(self, message): - # type: (BaseMessage) -> Any + def _normalize_langchain_message(self, message: BaseMessage) -> Any: parsed = {"content": message.content, "role": message.type} parsed.update(message.additional_kwargs) return parsed - def _create_span(self, run_id, parent_id, **kwargs): - # type: (SentryLangchainCallback, UUID, Optional[Any], Any) -> WatchedSpan + def _create_span( + self: SentryLangchainCallback, + run_id: UUID, + parent_id: Optional[Any], + **kwargs: Any, + ) -> WatchedSpan: parent_watched_span = self.span_map.get(parent_id) if parent_id else None sentry_span = sentry_sdk.start_span( @@ -160,8 +165,9 @@ def _create_span(self, run_id, parent_id, **kwargs): self.gc_span_map() return watched_span - def _exit_span(self, span_data, run_id): - # type: (SentryLangchainCallback, WatchedSpan, UUID) -> None + def _exit_span( + self: SentryLangchainCallback, span_data: WatchedSpan, run_id: UUID + ) -> None: if span_data.is_pipeline: set_ai_pipeline_name(None) @@ -171,17 +177,16 @@ def _exit_span(self, span_data, run_id): del self.span_map[run_id] def on_llm_start( - self, - serialized, - prompts, + self: SentryLangchainCallback, + serialized: Dict[str, Any], + prompts: List[str], *, - run_id, - tags=None, - parent_run_id=None, - metadata=None, - **kwargs, - ): - # type: (SentryLangchainCallback, Dict[str, Any], List[str], UUID, Optional[List[str]], Optional[UUID], Optional[Dict[str, Any]], Any) -> Any + run_id: UUID, + tags: Optional[List[str]] = None, + parent_run_id: Optional[UUID] = None, + metadata: Optional[Dict[str, Any]] = None, + **kwargs: Any, + ) -> Any: """Run when LLM starts running.""" with capture_internal_exceptions(): if not run_id: @@ -202,8 +207,14 @@ def on_llm_start( if k in all_params: set_data_normalized(span, v, all_params[k]) - def on_chat_model_start(self, serialized, messages, *, run_id, **kwargs): - # type: (SentryLangchainCallback, Dict[str, Any], List[List[BaseMessage]], UUID, Any) -> Any + def on_chat_model_start( + self: SentryLangchainCallback, + serialized: Dict[str, Any], + messages: List[List[BaseMessage]], + *, + run_id: UUID, + **kwargs: Any, + ) -> Any: """Run when Chat Model starts running.""" with capture_internal_exceptions(): if not run_id: @@ -248,8 +259,9 @@ def on_chat_model_start(self, serialized, messages, *, run_id, **kwargs): message.content ) + self.count_tokens(message.type) - def on_llm_new_token(self, token, *, run_id, **kwargs): - # type: (SentryLangchainCallback, str, UUID, Any) -> Any + def on_llm_new_token( + self: SentryLangchainCallback, token: str, *, run_id: UUID, **kwargs: Any + ) -> Any: """Run on new LLM token. Only available when streaming is enabled.""" with capture_internal_exceptions(): if not run_id or run_id not in self.span_map: @@ -259,8 +271,13 @@ def on_llm_new_token(self, token, *, run_id, **kwargs): return span_data.num_completion_tokens += self.count_tokens(token) - def on_llm_end(self, response, *, run_id, **kwargs): - # type: (SentryLangchainCallback, LLMResult, UUID, Any) -> Any + def on_llm_end( + self: SentryLangchainCallback, + response: LLMResult, + *, + run_id: UUID, + **kwargs: Any, + ) -> Any: """Run when LLM ends running.""" with capture_internal_exceptions(): if not run_id: @@ -298,14 +315,25 @@ def on_llm_end(self, response, *, run_id, **kwargs): self._exit_span(span_data, run_id) - def on_llm_error(self, error, *, run_id, **kwargs): - # type: (SentryLangchainCallback, Union[Exception, KeyboardInterrupt], UUID, Any) -> Any + def on_llm_error( + self: SentryLangchainCallback, + error: Union[Exception, KeyboardInterrupt], + *, + run_id: UUID, + **kwargs: Any, + ) -> Any: """Run when LLM errors.""" with capture_internal_exceptions(): self._handle_error(run_id, error) - def on_chain_start(self, serialized, inputs, *, run_id, **kwargs): - # type: (SentryLangchainCallback, Dict[str, Any], Dict[str, Any], UUID, Any) -> Any + def on_chain_start( + self: SentryLangchainCallback, + serialized: Dict[str, Any], + inputs: Dict[str, Any], + *, + run_id: UUID, + **kwargs: Any, + ) -> Any: """Run when chain starts running.""" with capture_internal_exceptions(): if not run_id: @@ -325,8 +353,13 @@ def on_chain_start(self, serialized, inputs, *, run_id, **kwargs): if metadata: set_data_normalized(watched_span.span, SPANDATA.AI_METADATA, metadata) - def on_chain_end(self, outputs, *, run_id, **kwargs): - # type: (SentryLangchainCallback, Dict[str, Any], UUID, Any) -> Any + def on_chain_end( + self: SentryLangchainCallback, + outputs: Dict[str, Any], + *, + run_id: UUID, + **kwargs: Any, + ) -> Any: """Run when chain ends running.""" with capture_internal_exceptions(): if not run_id or run_id not in self.span_map: @@ -337,13 +370,23 @@ def on_chain_end(self, outputs, *, run_id, **kwargs): return self._exit_span(span_data, run_id) - def on_chain_error(self, error, *, run_id, **kwargs): - # type: (SentryLangchainCallback, Union[Exception, KeyboardInterrupt], UUID, Any) -> Any + def on_chain_error( + self: SentryLangchainCallback, + error: Union[Exception, KeyboardInterrupt], + *, + run_id: UUID, + **kwargs: Any, + ) -> Any: """Run when chain errors.""" self._handle_error(run_id, error) - def on_agent_action(self, action, *, run_id, **kwargs): - # type: (SentryLangchainCallback, AgentAction, UUID, Any) -> Any + def on_agent_action( + self: SentryLangchainCallback, + action: AgentAction, + *, + run_id: UUID, + **kwargs: Any, + ) -> Any: with capture_internal_exceptions(): if not run_id: return @@ -359,8 +402,13 @@ def on_agent_action(self, action, *, run_id, **kwargs): watched_span.span, SPANDATA.AI_INPUT_MESSAGES, action.tool_input ) - def on_agent_finish(self, finish, *, run_id, **kwargs): - # type: (SentryLangchainCallback, AgentFinish, UUID, Any) -> Any + def on_agent_finish( + self: SentryLangchainCallback, + finish: AgentFinish, + *, + run_id: UUID, + **kwargs: Any, + ) -> Any: with capture_internal_exceptions(): if not run_id: return @@ -374,8 +422,14 @@ def on_agent_finish(self, finish, *, run_id, **kwargs): ) self._exit_span(span_data, run_id) - def on_tool_start(self, serialized, input_str, *, run_id, **kwargs): - # type: (SentryLangchainCallback, Dict[str, Any], str, UUID, Any) -> Any + def on_tool_start( + self: SentryLangchainCallback, + serialized: Dict[str, Any], + input_str: str, + *, + run_id: UUID, + **kwargs: Any, + ) -> Any: """Run when tool starts running.""" with capture_internal_exceptions(): if not run_id: @@ -398,8 +452,9 @@ def on_tool_start(self, serialized, input_str, *, run_id, **kwargs): watched_span.span, SPANDATA.AI_METADATA, kwargs.get("metadata") ) - def on_tool_end(self, output, *, run_id, **kwargs): - # type: (SentryLangchainCallback, str, UUID, Any) -> Any + def on_tool_end( + self: SentryLangchainCallback, output: str, *, run_id: UUID, **kwargs: Any + ) -> Any: """Run when tool ends running.""" with capture_internal_exceptions(): if not run_id or run_id not in self.span_map: @@ -412,24 +467,27 @@ def on_tool_end(self, output, *, run_id, **kwargs): set_data_normalized(span_data.span, SPANDATA.AI_RESPONSES, output) self._exit_span(span_data, run_id) - def on_tool_error(self, error, *args, run_id, **kwargs): - # type: (SentryLangchainCallback, Union[Exception, KeyboardInterrupt], UUID, Any) -> Any + def on_tool_error( + self, + error: SentryLangchainCallback, + *args: Union[Exception, KeyboardInterrupt], + run_id: UUID, + **kwargs: Any, + ) -> Any: """Run when tool errors.""" self._handle_error(run_id, error) -def _wrap_configure(f): - # type: (Callable[..., Any]) -> Callable[..., Any] +def _wrap_configure(f: Callable[..., Any]) -> Callable[..., Any]: @wraps(f) def new_configure( - callback_manager_cls, # type: type - inheritable_callbacks=None, # type: Callbacks - local_callbacks=None, # type: Callbacks - *args, # type: Any - **kwargs, # type: Any - ): - # type: (...) -> Any + callback_manager_cls: type, + inheritable_callbacks: Callbacks = None, + local_callbacks: Callbacks = None, + *args: Any, + **kwargs: Any, + ) -> Any: integration = sentry_sdk.get_client().get_integration(LangchainIntegration) if integration is None: diff --git a/sentry_sdk/integrations/launchdarkly.py b/sentry_sdk/integrations/launchdarkly.py index d3c423e7be..18081e617a 100644 --- a/sentry_sdk/integrations/launchdarkly.py +++ b/sentry_sdk/integrations/launchdarkly.py @@ -1,3 +1,4 @@ +from __future__ import annotations from typing import TYPE_CHECKING from sentry_sdk.feature_flags import add_feature_flag @@ -20,8 +21,7 @@ class LaunchDarklyIntegration(Integration): identifier = "launchdarkly" - def __init__(self, ld_client=None): - # type: (LDClient | None) -> None + def __init__(self, ld_client: LDClient | None = None) -> None: """ :param client: An initialized LDClient instance. If a client is not provided, this integration will attempt to use the shared global instance. @@ -38,25 +38,28 @@ def __init__(self, ld_client=None): client.add_hook(LaunchDarklyHook()) @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: pass class LaunchDarklyHook(Hook): @property - def metadata(self): - # type: () -> Metadata + def metadata(self) -> Metadata: return Metadata(name="sentry-flag-auditor") - def after_evaluation(self, series_context, data, detail): - # type: (EvaluationSeriesContext, dict[Any, Any], EvaluationDetail) -> dict[Any, Any] + def after_evaluation( + self, + series_context: EvaluationSeriesContext, + data: dict[Any, Any], + detail: EvaluationDetail, + ) -> dict[Any, Any]: if isinstance(detail.value, bool): add_feature_flag(series_context.key, detail.value) return data - def before_evaluation(self, series_context, data): - # type: (EvaluationSeriesContext, dict[Any, Any]) -> dict[Any, Any] + def before_evaluation( + self, series_context: EvaluationSeriesContext, data: dict[Any, Any] + ) -> dict[Any, Any]: return data # No-op. diff --git a/sentry_sdk/integrations/litestar.py b/sentry_sdk/integrations/litestar.py index 267a1c89af..7b4740e74b 100644 --- a/sentry_sdk/integrations/litestar.py +++ b/sentry_sdk/integrations/litestar.py @@ -1,3 +1,4 @@ +from __future__ import annotations from collections.abc import Set import sentry_sdk from sentry_sdk.consts import OP, TransactionSource, SOURCE_FOR_STYLE @@ -52,13 +53,12 @@ class LitestarIntegration(Integration): def __init__( self, - failed_request_status_codes=_DEFAULT_FAILED_REQUEST_STATUS_CODES, # type: Set[int] + failed_request_status_codes: Set[int] = _DEFAULT_FAILED_REQUEST_STATUS_CODES, ) -> None: self.failed_request_status_codes = failed_request_status_codes @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: patch_app_init() patch_middlewares() patch_http_route_handle() @@ -75,8 +75,9 @@ def setup_once(): class SentryLitestarASGIMiddleware(SentryAsgiMiddleware): - def __init__(self, app, span_origin=LitestarIntegration.origin): - # type: (ASGIApp, str) -> None + def __init__( + self, app: ASGIApp, span_origin: str = LitestarIntegration.origin + ) -> None: super().__init__( app=app, @@ -86,8 +87,7 @@ def __init__(self, app, span_origin=LitestarIntegration.origin): span_origin=span_origin, ) - def _capture_request_exception(self, exc): - # type: (Exception) -> None + def _capture_request_exception(self, exc: Exception) -> None: """Avoid catching exceptions from request handlers. Those exceptions are already handled in Litestar.after_exception handler. @@ -96,8 +96,7 @@ def _capture_request_exception(self, exc): pass -def patch_app_init(): - # type: () -> None +def patch_app_init() -> None: """ Replaces the Litestar class's `__init__` function in order to inject `after_exception` handlers and set the `SentryLitestarASGIMiddleware` as the outmost middleware in the stack. @@ -108,8 +107,7 @@ def patch_app_init(): old__init__ = Litestar.__init__ @ensure_integration_enabled(LitestarIntegration, old__init__) - def injection_wrapper(self, *args, **kwargs): - # type: (Litestar, *Any, **Any) -> None + def injection_wrapper(self: Litestar, *args: Any, **kwargs: Any) -> None: kwargs["after_exception"] = [ exception_handler, *(kwargs.get("after_exception") or []), @@ -123,13 +121,11 @@ def injection_wrapper(self, *args, **kwargs): Litestar.__init__ = injection_wrapper -def patch_middlewares(): - # type: () -> None +def patch_middlewares() -> None: old_resolve_middleware_stack = BaseRouteHandler.resolve_middleware @ensure_integration_enabled(LitestarIntegration, old_resolve_middleware_stack) - def resolve_middleware_wrapper(self): - # type: (BaseRouteHandler) -> list[Middleware] + def resolve_middleware_wrapper(self: BaseRouteHandler) -> list[Middleware]: return [ enable_span_for_middleware(middleware) for middleware in old_resolve_middleware_stack(self) @@ -138,8 +134,7 @@ def resolve_middleware_wrapper(self): BaseRouteHandler.resolve_middleware = resolve_middleware_wrapper -def enable_span_for_middleware(middleware): - # type: (Middleware) -> Middleware +def enable_span_for_middleware(middleware: Middleware) -> Middleware: if ( not hasattr(middleware, "__call__") # noqa: B004 or middleware is SentryLitestarASGIMiddleware @@ -147,12 +142,13 @@ def enable_span_for_middleware(middleware): return middleware if isinstance(middleware, DefineMiddleware): - old_call = middleware.middleware.__call__ # type: ASGIApp + old_call: ASGIApp = middleware.middleware.__call__ else: old_call = middleware.__call__ - async def _create_span_call(self, scope, receive, send): - # type: (MiddlewareProtocol, LitestarScope, Receive, Send) -> None + async def _create_span_call( + self: MiddlewareProtocol, scope: LitestarScope, receive: Receive, send: Send + ) -> None: if sentry_sdk.get_client().get_integration(LitestarIntegration) is None: return await old_call(self, scope, receive, send) @@ -166,8 +162,9 @@ async def _create_span_call(self, scope, receive, send): middleware_span.set_tag("litestar.middleware_name", middleware_name) # Creating spans for the "receive" callback - async def _sentry_receive(*args, **kwargs): - # type: (*Any, **Any) -> Union[HTTPReceiveMessage, WebSocketReceiveMessage] + async def _sentry_receive( + *args: Any, **kwargs: Any + ) -> Union[HTTPReceiveMessage, WebSocketReceiveMessage]: if sentry_sdk.get_client().get_integration(LitestarIntegration) is None: return await receive(*args, **kwargs) with sentry_sdk.start_span( @@ -184,8 +181,7 @@ async def _sentry_receive(*args, **kwargs): new_receive = _sentry_receive if not receive_patched else receive # Creating spans for the "send" callback - async def _sentry_send(message): - # type: (Message) -> None + async def _sentry_send(message: Message) -> None: if sentry_sdk.get_client().get_integration(LitestarIntegration) is None: return await send(message) with sentry_sdk.start_span( @@ -214,19 +210,19 @@ async def _sentry_send(message): return middleware -def patch_http_route_handle(): - # type: () -> None +def patch_http_route_handle() -> None: old_handle = HTTPRoute.handle - async def handle_wrapper(self, scope, receive, send): - # type: (HTTPRoute, HTTPScope, Receive, Send) -> None + async def handle_wrapper( + self: HTTPRoute, scope: HTTPScope, receive: Receive, send: Send + ) -> None: if sentry_sdk.get_client().get_integration(LitestarIntegration) is None: return await old_handle(self, scope, receive, send) sentry_scope = sentry_sdk.get_isolation_scope() - request = scope["app"].request_class( + request: Request[Any, Any] = scope["app"].request_class( scope=scope, receive=receive, send=send - ) # type: Request[Any, Any] + ) extracted_request_data = ConnectionDataExtractor( parse_body=True, parse_query=True )(request) @@ -234,8 +230,7 @@ async def handle_wrapper(self, scope, receive, send): request_data = await body - def event_processor(event, _): - # type: (Event, Hint) -> Event + def event_processor(event: Event, _: Hint) -> Event: route_handler = scope.get("route_handler") request_info = event.get("request", {}) @@ -279,8 +274,7 @@ def event_processor(event, _): HTTPRoute.handle = handle_wrapper -def retrieve_user_from_scope(scope): - # type: (LitestarScope) -> Optional[dict[str, Any]] +def retrieve_user_from_scope(scope: LitestarScope) -> Optional[dict[str, Any]]: scope_user = scope.get("user") if isinstance(scope_user, dict): return scope_user @@ -291,9 +285,8 @@ def retrieve_user_from_scope(scope): @ensure_integration_enabled(LitestarIntegration) -def exception_handler(exc, scope): - # type: (Exception, LitestarScope) -> None - user_info = None # type: Optional[dict[str, Any]] +def exception_handler(exc: Exception, scope: LitestarScope) -> None: + user_info: Optional[dict[str, Any]] = None if should_send_default_pii(): user_info = retrieve_user_from_scope(scope) if user_info and isinstance(user_info, dict): diff --git a/sentry_sdk/integrations/logging.py b/sentry_sdk/integrations/logging.py index f807a62966..9b363ba510 100644 --- a/sentry_sdk/integrations/logging.py +++ b/sentry_sdk/integrations/logging.py @@ -1,3 +1,4 @@ +from __future__ import annotations import logging import sys from datetime import datetime, timezone @@ -64,9 +65,8 @@ def ignore_logger( - name, # type: str -): - # type: (...) -> None + name: str, +) -> None: """This disables recording (both in breadcrumbs and as events) calls to a logger of a specific name. Among other uses, many of our integrations use this to prevent their actions being recorded as breadcrumbs. Exposed @@ -82,11 +82,10 @@ class LoggingIntegration(Integration): def __init__( self, - level=DEFAULT_LEVEL, - event_level=DEFAULT_EVENT_LEVEL, - sentry_logs_level=DEFAULT_LEVEL, - ): - # type: (Optional[int], Optional[int], Optional[int]) -> None + level: Optional[int] = DEFAULT_LEVEL, + event_level: Optional[int] = DEFAULT_EVENT_LEVEL, + sentry_logs_level: Optional[int] = DEFAULT_LEVEL, + ) -> None: self._handler = None self._breadcrumb_handler = None self._sentry_logs_handler = None @@ -100,8 +99,7 @@ def __init__( if event_level is not None: self._handler = EventHandler(level=event_level) - def _handle_record(self, record): - # type: (LogRecord) -> None + def _handle_record(self, record: LogRecord) -> None: if self._handler is not None and record.levelno >= self._handler.level: self._handler.handle(record) @@ -118,12 +116,10 @@ def _handle_record(self, record): self._sentry_logs_handler.handle(record) @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: old_callhandlers = logging.Logger.callHandlers - def sentry_patched_callhandlers(self, record): - # type: (Any, LogRecord) -> Any + def sentry_patched_callhandlers(self: Any, record: LogRecord) -> Any: # keeping a local reference because the # global might be discarded on shutdown ignored_loggers = _IGNORED_LOGGERS @@ -179,22 +175,19 @@ class _BaseHandler(logging.Handler): ) ) - def _can_record(self, record): - # type: (LogRecord) -> bool + def _can_record(self, record: LogRecord) -> bool: """Prevents ignored loggers from recording""" for logger in _IGNORED_LOGGERS: if fnmatch(record.name.strip(), logger): return False return True - def _logging_to_event_level(self, record): - # type: (LogRecord) -> str + def _logging_to_event_level(self, record: LogRecord) -> str: return LOGGING_TO_EVENT_LEVEL.get( record.levelno, record.levelname.lower() if record.levelname else "" ) - def _extra_from_record(self, record): - # type: (LogRecord) -> MutableMapping[str, object] + def _extra_from_record(self, record: LogRecord) -> MutableMapping[str, object]: return { k: v for k, v in vars(record).items() @@ -210,14 +203,12 @@ class EventHandler(_BaseHandler): Note that you do not have to use this class if the logging integration is enabled, which it is by default. """ - def emit(self, record): - # type: (LogRecord) -> Any + def emit(self, record: LogRecord) -> Any: with capture_internal_exceptions(): self.format(record) return self._emit(record) - def _emit(self, record): - # type: (LogRecord) -> None + def _emit(self, record: LogRecord) -> None: if not self._can_record(record): return @@ -304,14 +295,12 @@ class BreadcrumbHandler(_BaseHandler): Note that you do not have to use this class if the logging integration is enabled, which it is by default. """ - def emit(self, record): - # type: (LogRecord) -> Any + def emit(self, record: LogRecord) -> Any: with capture_internal_exceptions(): self.format(record) return self._emit(record) - def _emit(self, record): - # type: (LogRecord) -> None + def _emit(self, record: LogRecord) -> None: if not self._can_record(record): return @@ -319,8 +308,7 @@ def _emit(self, record): self._breadcrumb_from_record(record), hint={"log_record": record} ) - def _breadcrumb_from_record(self, record): - # type: (LogRecord) -> Dict[str, Any] + def _breadcrumb_from_record(self, record: LogRecord) -> Dict[str, Any]: return { "type": "log", "level": self._logging_to_event_level(record), @@ -338,8 +326,7 @@ class SentryLogsHandler(_BaseHandler): Note that you do not have to use this class if the logging integration is enabled, which it is by default. """ - def emit(self, record): - # type: (LogRecord) -> Any + def emit(self, record: LogRecord) -> Any: with capture_internal_exceptions(): self.format(record) if not self._can_record(record): @@ -354,13 +341,12 @@ def emit(self, record): self._capture_log_from_record(client, record) - def _capture_log_from_record(self, client, record): - # type: (BaseClient, LogRecord) -> None + def _capture_log_from_record(self, client: BaseClient, record: LogRecord) -> None: otel_severity_number, otel_severity_text = _log_level_to_otel( record.levelno, SEVERITY_TO_OTEL_SEVERITY ) project_root = client.options["project_root"] - attrs = self._extra_from_record(record) # type: Any + attrs: Any = self._extra_from_record(record) attrs["sentry.origin"] = "auto.logger.log" if isinstance(record.msg, str): attrs["sentry.message.template"] = record.msg diff --git a/sentry_sdk/integrations/loguru.py b/sentry_sdk/integrations/loguru.py index df3ecf161a..6bcec10d8e 100644 --- a/sentry_sdk/integrations/loguru.py +++ b/sentry_sdk/integrations/loguru.py @@ -1,3 +1,4 @@ +from __future__ import annotations import enum import sentry_sdk @@ -65,21 +66,20 @@ class LoggingLevels(enum.IntEnum): class LoguruIntegration(Integration): identifier = "loguru" - level = DEFAULT_LEVEL # type: Optional[int] - event_level = DEFAULT_EVENT_LEVEL # type: Optional[int] + level: Optional[int] = DEFAULT_LEVEL + event_level: Optional[int] = DEFAULT_EVENT_LEVEL breadcrumb_format = DEFAULT_FORMAT event_format = DEFAULT_FORMAT - sentry_logs_level = DEFAULT_LEVEL # type: Optional[int] + sentry_logs_level: Optional[int] = DEFAULT_LEVEL def __init__( self, - level=DEFAULT_LEVEL, - event_level=DEFAULT_EVENT_LEVEL, - breadcrumb_format=DEFAULT_FORMAT, - event_format=DEFAULT_FORMAT, - sentry_logs_level=DEFAULT_LEVEL, - ): - # type: (Optional[int], Optional[int], str | loguru.FormatFunction, str | loguru.FormatFunction, Optional[int]) -> None + level: Optional[int] = DEFAULT_LEVEL, + event_level: Optional[int] = DEFAULT_EVENT_LEVEL, + breadcrumb_format: str | loguru.FormatFunction = DEFAULT_FORMAT, + event_format: str | loguru.FormatFunction = DEFAULT_FORMAT, + sentry_logs_level: Optional[int] = DEFAULT_LEVEL, + ) -> None: LoguruIntegration.level = level LoguruIntegration.event_level = event_level LoguruIntegration.breadcrumb_format = breadcrumb_format @@ -87,8 +87,7 @@ def __init__( LoguruIntegration.sentry_logs_level = sentry_logs_level @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: if LoguruIntegration.level is not None: logger.add( LoguruBreadcrumbHandler(level=LoguruIntegration.level), @@ -111,8 +110,7 @@ def setup_once(): class _LoguruBaseHandler(_BaseHandler): - def __init__(self, *args, **kwargs): - # type: (*Any, **Any) -> None + def __init__(self, *args: Any, **kwargs: Any) -> None: if kwargs.get("level"): kwargs["level"] = SENTRY_LEVEL_FROM_LOGURU_LEVEL.get( kwargs.get("level", ""), DEFAULT_LEVEL @@ -120,8 +118,7 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - def _logging_to_event_level(self, record): - # type: (LogRecord) -> str + def _logging_to_event_level(self, record: LogRecord) -> str: try: return SENTRY_LEVEL_FROM_LOGURU_LEVEL[ LoggingLevels(record.levelno).name @@ -142,8 +139,7 @@ class LoguruBreadcrumbHandler(_LoguruBaseHandler, BreadcrumbHandler): pass -def loguru_sentry_logs_handler(message): - # type: (Message) -> None +def loguru_sentry_logs_handler(message: Message) -> None: # This is intentionally a callable sink instead of a standard logging handler # since otherwise we wouldn't get direct access to message.record client = sentry_sdk.get_client() @@ -166,7 +162,7 @@ def loguru_sentry_logs_handler(message): record["level"].no, SEVERITY_TO_OTEL_SEVERITY ) - attrs = {"sentry.origin": "auto.logger.loguru"} # type: dict[str, Any] + attrs: dict[str, Any] = {"sentry.origin": "auto.logger.loguru"} project_root = client.options["project_root"] if record.get("file"): diff --git a/sentry_sdk/integrations/modules.py b/sentry_sdk/integrations/modules.py index ce3ee78665..a289ce1989 100644 --- a/sentry_sdk/integrations/modules.py +++ b/sentry_sdk/integrations/modules.py @@ -1,3 +1,4 @@ +from __future__ import annotations import sentry_sdk from sentry_sdk.integrations import Integration from sentry_sdk.scope import add_global_event_processor @@ -14,11 +15,9 @@ class ModulesIntegration(Integration): identifier = "modules" @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: @add_global_event_processor - def processor(event, hint): - # type: (Event, Any) -> Event + def processor(event: Event, hint: Any) -> Event: if event.get("type") == "transaction": return event diff --git a/sentry_sdk/integrations/openai.py b/sentry_sdk/integrations/openai.py index a4467c9782..dc9c1c1100 100644 --- a/sentry_sdk/integrations/openai.py +++ b/sentry_sdk/integrations/openai.py @@ -1,3 +1,4 @@ +from __future__ import annotations from functools import wraps import sentry_sdk @@ -32,8 +33,11 @@ class OpenAIIntegration(Integration): identifier = "openai" origin = f"auto.ai.{identifier}" - def __init__(self, include_prompts=True, tiktoken_encoding_name=None): - # type: (OpenAIIntegration, bool, Optional[str]) -> None + def __init__( + self: OpenAIIntegration, + include_prompts: bool = True, + tiktoken_encoding_name: Optional[str] = None, + ) -> None: self.include_prompts = include_prompts self.tiktoken_encoding = None @@ -43,8 +47,7 @@ def __init__(self, include_prompts=True, tiktoken_encoding_name=None): self.tiktoken_encoding = tiktoken.get_encoding(tiktoken_encoding_name) @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: Completions.create = _wrap_chat_completion_create(Completions.create) Embeddings.create = _wrap_embeddings_create(Embeddings.create) @@ -53,15 +56,13 @@ def setup_once(): ) AsyncEmbeddings.create = _wrap_async_embeddings_create(AsyncEmbeddings.create) - def count_tokens(self, s): - # type: (OpenAIIntegration, str) -> int + def count_tokens(self: OpenAIIntegration, s: str) -> int: if self.tiktoken_encoding is not None: return len(self.tiktoken_encoding.encode_ordinary(s)) return 0 -def _capture_exception(exc): - # type: (Any) -> None +def _capture_exception(exc: Any) -> None: event, hint = event_from_exception( exc, client_options=sentry_sdk.get_client().options, @@ -71,12 +72,15 @@ def _capture_exception(exc): def _calculate_chat_completion_usage( - messages, response, span, streaming_message_responses, count_tokens -): - # type: (Iterable[ChatCompletionMessageParam], Any, Span, Optional[List[str]], Callable[..., Any]) -> None - completion_tokens = 0 # type: Optional[int] - prompt_tokens = 0 # type: Optional[int] - total_tokens = 0 # type: Optional[int] + messages: Iterable[ChatCompletionMessageParam], + response: Any, + span: Span, + streaming_message_responses: Optional[List[str]], + count_tokens: Callable[..., Any], +) -> None: + completion_tokens: Optional[int] = 0 + prompt_tokens: Optional[int] = 0 + total_tokens: Optional[int] = 0 if hasattr(response, "usage"): if hasattr(response.usage, "completion_tokens") and isinstance( response.usage.completion_tokens, int @@ -114,8 +118,7 @@ def _calculate_chat_completion_usage( record_token_usage(span, prompt_tokens, completion_tokens, total_tokens) -def _new_chat_completion_common(f, *args, **kwargs): - # type: (Any, *Any, **Any) -> Any +def _new_chat_completion_common(f: Any, *args: Any, **kwargs: Any) -> Any: integration = sentry_sdk.get_client().get_integration(OpenAIIntegration) if integration is None: return f(*args, **kwargs) @@ -168,8 +171,7 @@ def _new_chat_completion_common(f, *args, **kwargs): old_iterator = res._iterator - def new_iterator(): - # type: () -> Iterator[ChatCompletionChunk] + def new_iterator() -> Iterator[ChatCompletionChunk]: with capture_internal_exceptions(): for x in old_iterator: if hasattr(x, "choices"): @@ -201,8 +203,7 @@ def new_iterator(): ) span.__exit__(None, None, None) - async def new_iterator_async(): - # type: () -> AsyncIterator[ChatCompletionChunk] + async def new_iterator_async() -> AsyncIterator[ChatCompletionChunk]: with capture_internal_exceptions(): async for x in old_iterator: if hasattr(x, "choices"): @@ -245,10 +246,8 @@ async def new_iterator_async(): return res -def _wrap_chat_completion_create(f): - # type: (Callable[..., Any]) -> Callable[..., Any] - def _execute_sync(f, *args, **kwargs): - # type: (Any, *Any, **Any) -> Any +def _wrap_chat_completion_create(f: Callable[..., Any]) -> Callable[..., Any]: + def _execute_sync(f: Any, *args: Any, **kwargs: Any) -> Any: gen = _new_chat_completion_common(f, *args, **kwargs) try: @@ -268,8 +267,7 @@ def _execute_sync(f, *args, **kwargs): return e.value @wraps(f) - def _sentry_patched_create_sync(*args, **kwargs): - # type: (*Any, **Any) -> Any + def _sentry_patched_create_sync(*args: Any, **kwargs: Any) -> Any: integration = sentry_sdk.get_client().get_integration(OpenAIIntegration) if integration is None or "messages" not in kwargs: # no "messages" means invalid call (in all versions of openai), let it return error @@ -280,10 +278,8 @@ def _sentry_patched_create_sync(*args, **kwargs): return _sentry_patched_create_sync -def _wrap_async_chat_completion_create(f): - # type: (Callable[..., Any]) -> Callable[..., Any] - async def _execute_async(f, *args, **kwargs): - # type: (Any, *Any, **Any) -> Any +def _wrap_async_chat_completion_create(f: Callable[..., Any]) -> Callable[..., Any]: + async def _execute_async(f: Any, *args: Any, **kwargs: Any) -> Any: gen = _new_chat_completion_common(f, *args, **kwargs) try: @@ -303,8 +299,7 @@ async def _execute_async(f, *args, **kwargs): return e.value @wraps(f) - async def _sentry_patched_create_async(*args, **kwargs): - # type: (*Any, **Any) -> Any + async def _sentry_patched_create_async(*args: Any, **kwargs: Any) -> Any: integration = sentry_sdk.get_client().get_integration(OpenAIIntegration) if integration is None or "messages" not in kwargs: # no "messages" means invalid call (in all versions of openai), let it return error @@ -315,8 +310,7 @@ async def _sentry_patched_create_async(*args, **kwargs): return _sentry_patched_create_async -def _new_embeddings_create_common(f, *args, **kwargs): - # type: (Any, *Any, **Any) -> Any +def _new_embeddings_create_common(f: Any, *args: Any, **kwargs: Any) -> Any: integration = sentry_sdk.get_client().get_integration(OpenAIIntegration) if integration is None: return f(*args, **kwargs) @@ -363,10 +357,8 @@ def _new_embeddings_create_common(f, *args, **kwargs): return response -def _wrap_embeddings_create(f): - # type: (Any) -> Any - def _execute_sync(f, *args, **kwargs): - # type: (Any, *Any, **Any) -> Any +def _wrap_embeddings_create(f: Any) -> Any: + def _execute_sync(f: Any, *args: Any, **kwargs: Any) -> Any: gen = _new_embeddings_create_common(f, *args, **kwargs) try: @@ -386,8 +378,7 @@ def _execute_sync(f, *args, **kwargs): return e.value @wraps(f) - def _sentry_patched_create_sync(*args, **kwargs): - # type: (*Any, **Any) -> Any + def _sentry_patched_create_sync(*args: Any, **kwargs: Any) -> Any: integration = sentry_sdk.get_client().get_integration(OpenAIIntegration) if integration is None: return f(*args, **kwargs) @@ -397,10 +388,8 @@ def _sentry_patched_create_sync(*args, **kwargs): return _sentry_patched_create_sync -def _wrap_async_embeddings_create(f): - # type: (Any) -> Any - async def _execute_async(f, *args, **kwargs): - # type: (Any, *Any, **Any) -> Any +def _wrap_async_embeddings_create(f: Any) -> Any: + async def _execute_async(f: Any, *args: Any, **kwargs: Any) -> Any: gen = _new_embeddings_create_common(f, *args, **kwargs) try: @@ -420,8 +409,7 @@ async def _execute_async(f, *args, **kwargs): return e.value @wraps(f) - async def _sentry_patched_create_async(*args, **kwargs): - # type: (*Any, **Any) -> Any + async def _sentry_patched_create_async(*args: Any, **kwargs: Any) -> Any: integration = sentry_sdk.get_client().get_integration(OpenAIIntegration) if integration is None: return await f(*args, **kwargs) diff --git a/sentry_sdk/integrations/openfeature.py b/sentry_sdk/integrations/openfeature.py index e2b33d83f2..613d7b5bd1 100644 --- a/sentry_sdk/integrations/openfeature.py +++ b/sentry_sdk/integrations/openfeature.py @@ -1,3 +1,4 @@ +from __future__ import annotations from typing import TYPE_CHECKING from sentry_sdk.feature_flags import add_feature_flag @@ -18,20 +19,24 @@ class OpenFeatureIntegration(Integration): identifier = "openfeature" @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: # Register the hook within the global openfeature hooks list. api.add_hooks(hooks=[OpenFeatureHook()]) class OpenFeatureHook(Hook): - def after(self, hook_context, details, hints): - # type: (HookContext, FlagEvaluationDetails[bool], HookHints) -> None + def after( + self, + hook_context: HookContext, + details: FlagEvaluationDetails[bool], + hints: HookHints, + ) -> None: if isinstance(details.value, bool): add_feature_flag(details.flag_key, details.value) - def error(self, hook_context, exception, hints): - # type: (HookContext, Exception, HookHints) -> None + def error( + self, hook_context: HookContext, exception: Exception, hints: HookHints + ) -> None: if isinstance(hook_context.default_value, bool): add_feature_flag(hook_context.flag_key, hook_context.default_value) diff --git a/sentry_sdk/integrations/pure_eval.py b/sentry_sdk/integrations/pure_eval.py index c1c3d63871..74cfa5a7c6 100644 --- a/sentry_sdk/integrations/pure_eval.py +++ b/sentry_sdk/integrations/pure_eval.py @@ -1,3 +1,4 @@ +from __future__ import annotations import ast import sentry_sdk @@ -35,12 +36,10 @@ class PureEvalIntegration(Integration): identifier = "pure_eval" @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: @add_global_event_processor - def add_executing_info(event, hint): - # type: (Event, Optional[Hint]) -> Optional[Event] + def add_executing_info(event: Event, hint: Optional[Hint]) -> Optional[Event]: if sentry_sdk.get_client().get_integration(PureEvalIntegration) is None: return event @@ -81,8 +80,7 @@ def add_executing_info(event, hint): return event -def pure_eval_frame(frame): - # type: (FrameType) -> Dict[str, Any] +def pure_eval_frame(frame: FrameType) -> Dict[str, Any]: source = executing.Source.for_frame(frame) if not source.tree: return {} @@ -103,16 +101,14 @@ def pure_eval_frame(frame): evaluator = pure_eval.Evaluator.from_frame(frame) expressions = evaluator.interesting_expressions_grouped(scope) - def closeness(expression): - # type: (Tuple[List[Any], Any]) -> Tuple[int, int] + def closeness(expression: Tuple[List[Any], Any]) -> Tuple[int, int]: # Prioritise expressions with a node closer to the statement executed # without being after that statement # A higher return value is better - the expression will appear # earlier in the list of values and is less likely to be trimmed nodes, _value = expression - def start(n): - # type: (ast.expr) -> Tuple[int, int] + def start(n: ast.expr) -> Tuple[int, int]: return (n.lineno, n.col_offset) nodes_before_stmt = [ diff --git a/sentry_sdk/integrations/pymongo.py b/sentry_sdk/integrations/pymongo.py index 32cb294075..d7a29b3e8b 100644 --- a/sentry_sdk/integrations/pymongo.py +++ b/sentry_sdk/integrations/pymongo.py @@ -1,3 +1,4 @@ +from __future__ import annotations import copy import sentry_sdk @@ -41,8 +42,7 @@ ] -def _strip_pii(command): - # type: (Dict[str, Any]) -> Dict[str, Any] +def _strip_pii(command: Dict[str, Any]) -> Dict[str, Any]: for key in command: is_safe_field = key in SAFE_COMMAND_ATTRIBUTES if is_safe_field: @@ -84,8 +84,7 @@ def _strip_pii(command): return command -def _get_db_data(event): - # type: (Any) -> Dict[str, Any] +def _get_db_data(event: Any) -> Dict[str, Any]: data = {} data[SPANDATA.DB_SYSTEM] = "mongodb" @@ -106,16 +105,16 @@ def _get_db_data(event): class CommandTracer(monitoring.CommandListener): - def __init__(self): - # type: () -> None - self._ongoing_operations = {} # type: Dict[int, Span] + def __init__(self) -> None: + self._ongoing_operations: Dict[int, Span] = {} - def _operation_key(self, event): - # type: (Union[CommandFailedEvent, CommandStartedEvent, CommandSucceededEvent]) -> int + def _operation_key( + self, + event: Union[CommandFailedEvent, CommandStartedEvent, CommandSucceededEvent], + ) -> int: return event.request_id - def started(self, event): - # type: (CommandStartedEvent) -> None + def started(self, event: CommandStartedEvent) -> None: if sentry_sdk.get_client().get_integration(PyMongoIntegration) is None: return @@ -172,8 +171,7 @@ def started(self, event): self._ongoing_operations[self._operation_key(event)] = span.__enter__() - def failed(self, event): - # type: (CommandFailedEvent) -> None + def failed(self, event: CommandFailedEvent) -> None: if sentry_sdk.get_client().get_integration(PyMongoIntegration) is None: return @@ -184,8 +182,7 @@ def failed(self, event): except KeyError: return - def succeeded(self, event): - # type: (CommandSucceededEvent) -> None + def succeeded(self, event: CommandSucceededEvent) -> None: if sentry_sdk.get_client().get_integration(PyMongoIntegration) is None: return @@ -202,6 +199,5 @@ class PyMongoIntegration(Integration): origin = f"auto.db.{identifier}" @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: monitoring.register(CommandTracer()) diff --git a/sentry_sdk/integrations/pyramid.py b/sentry_sdk/integrations/pyramid.py index a4d30e38a4..68a725451a 100644 --- a/sentry_sdk/integrations/pyramid.py +++ b/sentry_sdk/integrations/pyramid.py @@ -1,3 +1,4 @@ +from __future__ import annotations import functools import os import sys @@ -40,8 +41,7 @@ if getattr(Request, "authenticated_userid", None): - def authenticated_userid(request): - # type: (Request) -> Optional[Any] + def authenticated_userid(request: Request) -> Optional[Any]: return request.authenticated_userid else: @@ -58,8 +58,7 @@ class PyramidIntegration(Integration): transaction_style = "" - def __init__(self, transaction_style="route_name"): - # type: (str) -> None + def __init__(self, transaction_style: str = "route_name") -> None: if transaction_style not in TRANSACTION_STYLE_VALUES: raise ValueError( "Invalid value for transaction_style: %s (must be in %s)" @@ -68,15 +67,15 @@ def __init__(self, transaction_style="route_name"): self.transaction_style = transaction_style @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: from pyramid import router old_call_view = router._call_view @functools.wraps(old_call_view) - def sentry_patched_call_view(registry, request, *args, **kwargs): - # type: (Any, Request, *Any, **Any) -> Response + def sentry_patched_call_view( + registry: Any, request: Request, *args: Any, **kwargs: Any + ) -> Response: integration = sentry_sdk.get_client().get_integration(PyramidIntegration) if integration is None: return old_call_view(registry, request, *args, **kwargs) @@ -96,8 +95,9 @@ def sentry_patched_call_view(registry, request, *args, **kwargs): if hasattr(Request, "invoke_exception_view"): old_invoke_exception_view = Request.invoke_exception_view - def sentry_patched_invoke_exception_view(self, *args, **kwargs): - # type: (Request, *Any, **Any) -> Any + def sentry_patched_invoke_exception_view( + self: Request, *args: Any, **kwargs: Any + ) -> Any: rv = old_invoke_exception_view(self, *args, **kwargs) if ( @@ -116,10 +116,12 @@ def sentry_patched_invoke_exception_view(self, *args, **kwargs): old_wsgi_call = router.Router.__call__ @ensure_integration_enabled(PyramidIntegration, old_wsgi_call) - def sentry_patched_wsgi_call(self, environ, start_response): - # type: (Any, Dict[str, str], Callable[..., Any]) -> _ScopedResponse - def sentry_patched_inner_wsgi_call(environ, start_response): - # type: (Dict[str, Any], Callable[..., Any]) -> Any + def sentry_patched_wsgi_call( + self: Any, environ: Dict[str, str], start_response: Callable[..., Any] + ) -> _ScopedResponse: + def sentry_patched_inner_wsgi_call( + environ: Dict[str, Any], start_response: Callable[..., Any] + ) -> Any: try: return old_wsgi_call(self, environ, start_response) except Exception: @@ -137,8 +139,7 @@ def sentry_patched_inner_wsgi_call(environ, start_response): @ensure_integration_enabled(PyramidIntegration) -def _capture_exception(exc_info): - # type: (ExcInfo) -> None +def _capture_exception(exc_info: ExcInfo) -> None: if exc_info[0] is None or issubclass(exc_info[0], HTTPException): return @@ -151,8 +152,9 @@ def _capture_exception(exc_info): sentry_sdk.capture_event(event, hint=hint) -def _set_transaction_name_and_source(scope, transaction_style, request): - # type: (sentry_sdk.Scope, str, Request) -> None +def _set_transaction_name_and_source( + scope: sentry_sdk.Scope, transaction_style: str, request: Request +) -> None: try: name_for_style = { "route_name": request.matched_route.name, @@ -167,40 +169,33 @@ def _set_transaction_name_and_source(scope, transaction_style, request): class PyramidRequestExtractor(RequestExtractor): - def url(self): - # type: () -> str + def url(self) -> str: return self.request.path_url - def env(self): - # type: () -> Dict[str, str] + def env(self) -> Dict[str, str]: return self.request.environ - def cookies(self): - # type: () -> RequestCookies + def cookies(self) -> RequestCookies: return self.request.cookies - def raw_data(self): - # type: () -> str + def raw_data(self) -> str: return self.request.text - def form(self): - # type: () -> Dict[str, str] + def form(self) -> Dict[str, str]: return { key: value for key, value in self.request.POST.items() if not getattr(value, "filename", None) } - def files(self): - # type: () -> Dict[str, _FieldStorageWithFile] + def files(self) -> Dict[str, _FieldStorageWithFile]: return { key: value for key, value in self.request.POST.items() if getattr(value, "filename", None) } - def size_of_file(self, postdata): - # type: (_FieldStorageWithFile) -> int + def size_of_file(self, postdata: _FieldStorageWithFile) -> int: file = postdata.file try: return os.fstat(file.fileno()).st_size @@ -208,10 +203,10 @@ def size_of_file(self, postdata): return 0 -def _make_event_processor(weak_request, integration): - # type: (Callable[[], Request], PyramidIntegration) -> EventProcessor - def pyramid_event_processor(event, hint): - # type: (Event, Dict[str, Any]) -> Event +def _make_event_processor( + weak_request: Callable[[], Request], integration: PyramidIntegration +) -> EventProcessor: + def pyramid_event_processor(event: Event, hint: Dict[str, Any]) -> Event: request = weak_request() if request is None: return event diff --git a/sentry_sdk/integrations/quart.py b/sentry_sdk/integrations/quart.py index 68c1342216..eb7e117cc9 100644 --- a/sentry_sdk/integrations/quart.py +++ b/sentry_sdk/integrations/quart.py @@ -1,3 +1,4 @@ +from __future__ import annotations import asyncio import inspect from functools import wraps @@ -60,8 +61,7 @@ class QuartIntegration(Integration): transaction_style = "" - def __init__(self, transaction_style="endpoint"): - # type: (str) -> None + def __init__(self, transaction_style: str = "endpoint") -> None: if transaction_style not in TRANSACTION_STYLE_VALUES: raise ValueError( "Invalid value for transaction_style: %s (must be in %s)" @@ -70,8 +70,7 @@ def __init__(self, transaction_style="endpoint"): self.transaction_style = transaction_style @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: request_started.connect(_request_websocket_started) websocket_started.connect(_request_websocket_started) @@ -83,12 +82,12 @@ def setup_once(): patch_scaffold_route() -def patch_asgi_app(): - # type: () -> None +def patch_asgi_app() -> None: old_app = Quart.__call__ - async def sentry_patched_asgi_app(self, scope, receive, send): - # type: (Any, Any, Any, Any) -> Any + async def sentry_patched_asgi_app( + self: Any, scope: Any, receive: Any, send: Any + ) -> Any: if sentry_sdk.get_client().get_integration(QuartIntegration) is None: return await old_app(self, scope, receive, send) @@ -102,16 +101,13 @@ async def sentry_patched_asgi_app(self, scope, receive, send): Quart.__call__ = sentry_patched_asgi_app -def patch_scaffold_route(): - # type: () -> None +def patch_scaffold_route() -> None: old_route = Scaffold.route - def _sentry_route(*args, **kwargs): - # type: (*Any, **Any) -> Any + def _sentry_route(*args: Any, **kwargs: Any) -> Any: old_decorator = old_route(*args, **kwargs) - def decorator(old_func): - # type: (Any) -> Any + def decorator(old_func: Any) -> Any: if inspect.isfunction(old_func) and not asyncio.iscoroutinefunction( old_func @@ -119,8 +115,7 @@ def decorator(old_func): @wraps(old_func) @ensure_integration_enabled(QuartIntegration, old_func) - def _sentry_func(*args, **kwargs): - # type: (*Any, **Any) -> Any + def _sentry_func(*args: Any, **kwargs: Any) -> Any: current_scope = sentry_sdk.get_current_scope() if current_scope.root_span is not None: current_scope.root_span.update_active_thread() @@ -140,8 +135,9 @@ def _sentry_func(*args, **kwargs): Scaffold.route = _sentry_route -def _set_transaction_name_and_source(scope, transaction_style, request): - # type: (sentry_sdk.Scope, str, Request) -> None +def _set_transaction_name_and_source( + scope: sentry_sdk.Scope, transaction_style: str, request: Request +) -> None: try: name_for_style = { @@ -156,8 +152,7 @@ def _set_transaction_name_and_source(scope, transaction_style, request): pass -async def _request_websocket_started(app, **kwargs): - # type: (Quart, **Any) -> None +async def _request_websocket_started(app: Quart, **kwargs: Any) -> None: integration = sentry_sdk.get_client().get_integration(QuartIntegration) if integration is None: return @@ -178,10 +173,10 @@ async def _request_websocket_started(app, **kwargs): scope.add_event_processor(evt_processor) -def _make_request_event_processor(app, request, integration): - # type: (Quart, Request, QuartIntegration) -> EventProcessor - def inner(event, hint): - # type: (Event, dict[str, Any]) -> Event +def _make_request_event_processor( + app: Quart, request: Request, integration: QuartIntegration +) -> EventProcessor: + def inner(event: Event, hint: dict[str, Any]) -> Event: # if the request is gone we are fine not logging the data from # it. This might happen if the processor is pushed away to # another thread. @@ -207,8 +202,9 @@ def inner(event, hint): return inner -async def _capture_exception(sender, exception, **kwargs): - # type: (Quart, Union[ValueError, BaseException], **Any) -> None +async def _capture_exception( + sender: Quart, exception: Union[ValueError, BaseException], **kwargs: Any +) -> None: integration = sentry_sdk.get_client().get_integration(QuartIntegration) if integration is None: return @@ -222,8 +218,7 @@ async def _capture_exception(sender, exception, **kwargs): sentry_sdk.capture_event(event, hint=hint) -def _add_user_to_event(event): - # type: (Event) -> None +def _add_user_to_event(event: Event) -> None: if quart_auth is None: return diff --git a/sentry_sdk/integrations/ray.py b/sentry_sdk/integrations/ray.py index 1bb78c859f..46a9b65dcb 100644 --- a/sentry_sdk/integrations/ray.py +++ b/sentry_sdk/integrations/ray.py @@ -1,3 +1,4 @@ +from __future__ import annotations import inspect import sys @@ -29,8 +30,7 @@ DEFAULT_TRANSACTION_NAME = "unknown Ray function" -def _check_sentry_initialized(): - # type: () -> None +def _check_sentry_initialized() -> None: if sentry_sdk.get_client().is_active(): return @@ -39,13 +39,13 @@ def _check_sentry_initialized(): ) -def _patch_ray_remote(): - # type: () -> None +def _patch_ray_remote() -> None: old_remote = ray.remote @functools.wraps(old_remote) - def new_remote(f=None, *args, **kwargs): - # type: (Optional[Callable[..., Any]], *Any, **Any) -> Callable[..., Any] + def new_remote( + f: Optional[Callable[..., Any]] = None, *args: Any, **kwargs: Any + ) -> Callable[..., Any]: if inspect.isclass(f): # Ray Actors @@ -54,10 +54,10 @@ def new_remote(f=None, *args, **kwargs): # (Only Ray Tasks are supported) return old_remote(f, *args, **kwargs) - def wrapper(user_f): - # type: (Callable[..., Any]) -> Any - def new_func(*f_args, _tracing=None, **f_kwargs): - # type: (Any, Optional[dict[str, Any]], Any) -> Any + def wrapper(user_f: Callable[..., Any]) -> Any: + def new_func( + *f_args: Any, _tracing: Optional[dict[str, Any]] = None, **f_kwargs: Any + ) -> Any: _check_sentry_initialized() root_span_name = ( @@ -91,8 +91,9 @@ def new_func(*f_args, _tracing=None, **f_kwargs): rv = old_remote(*args, **kwargs)(new_func) old_remote_method = rv.remote - def _remote_method_with_header_propagation(*args, **kwargs): - # type: (*Any, **Any) -> Any + def _remote_method_with_header_propagation( + *args: Any, **kwargs: Any + ) -> Any: """ Ray Client """ @@ -129,8 +130,7 @@ def _remote_method_with_header_propagation(*args, **kwargs): ray.remote = new_remote -def _capture_exception(exc_info, **kwargs): - # type: (ExcInfo, **Any) -> None +def _capture_exception(exc_info: ExcInfo, **kwargs: Any) -> None: client = sentry_sdk.get_client() event, hint = event_from_exception( @@ -149,8 +149,7 @@ class RayIntegration(Integration): origin = f"auto.queue.{identifier}" @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: version = package_version("ray") _check_minimum_version(RayIntegration, version) diff --git a/sentry_sdk/integrations/rq.py b/sentry_sdk/integrations/rq.py index 33910ed476..43a943c272 100644 --- a/sentry_sdk/integrations/rq.py +++ b/sentry_sdk/integrations/rq.py @@ -1,3 +1,4 @@ +from __future__ import annotations import weakref import sentry_sdk @@ -49,16 +50,16 @@ class RqIntegration(Integration): origin = f"auto.queue.{identifier}" @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: version = parse_version(RQ_VERSION) _check_minimum_version(RqIntegration, version) old_perform_job = Worker.perform_job @ensure_integration_enabled(RqIntegration, old_perform_job) - def sentry_patched_perform_job(self, job, queue, *args, **kwargs): - # type: (Any, Job, Queue, *Any, **Any) -> bool + def sentry_patched_perform_job( + self: Any, job: Job, queue: Queue, *args: Any, **kwargs: Any + ) -> bool: with sentry_sdk.new_scope() as scope: try: transaction_name = job.func_name or DEFAULT_TRANSACTION_NAME @@ -95,8 +96,9 @@ def sentry_patched_perform_job(self, job, queue, *args, **kwargs): old_handle_exception = Worker.handle_exception - def sentry_patched_handle_exception(self, job, *exc_info, **kwargs): - # type: (Worker, Any, *Any, **Any) -> Any + def sentry_patched_handle_exception( + self: Worker, job: Any, *exc_info: Any, **kwargs: Any + ) -> Any: retry = ( hasattr(job, "retries_left") and job.retries_left @@ -113,8 +115,7 @@ def sentry_patched_handle_exception(self, job, *exc_info, **kwargs): old_enqueue_job = Queue.enqueue_job @ensure_integration_enabled(RqIntegration, old_enqueue_job) - def sentry_patched_enqueue_job(self, job, **kwargs): - # type: (Queue, Any, **Any) -> Any + def sentry_patched_enqueue_job(self: Queue, job: Any, **kwargs: Any) -> Any: job.meta["_sentry_trace_headers"] = dict( sentry_sdk.get_current_scope().iter_trace_propagation_headers() ) @@ -126,10 +127,8 @@ def sentry_patched_enqueue_job(self, job, **kwargs): ignore_logger("rq.worker") -def _make_event_processor(weak_job): - # type: (Callable[[], Job]) -> EventProcessor - def event_processor(event, hint): - # type: (Event, dict[str, Any]) -> Event +def _make_event_processor(weak_job: Callable[[], Job]) -> EventProcessor: + def event_processor(event: Event, hint: dict[str, Any]) -> Event: job = weak_job() if job is not None: with capture_internal_exceptions(): @@ -159,8 +158,7 @@ def event_processor(event, hint): return event_processor -def _capture_exception(exc_info, **kwargs): - # type: (ExcInfo, **Any) -> None +def _capture_exception(exc_info: ExcInfo, **kwargs: Any) -> None: client = sentry_sdk.get_client() event, hint = event_from_exception( @@ -172,8 +170,7 @@ def _capture_exception(exc_info, **kwargs): sentry_sdk.capture_event(event, hint=hint) -def _prepopulate_attributes(job, queue): - # type: (Job, Queue) -> dict[str, Any] +def _prepopulate_attributes(job: Job, queue: Queue) -> dict[str, Any]: attributes = { "messaging.system": "rq", "rq.job.id": job.id, diff --git a/sentry_sdk/integrations/rust_tracing.py b/sentry_sdk/integrations/rust_tracing.py index acfe9bd7f4..3af40bc1fd 100644 --- a/sentry_sdk/integrations/rust_tracing.py +++ b/sentry_sdk/integrations/rust_tracing.py @@ -30,9 +30,13 @@ Each native extension requires its own integration. """ +from __future__ import annotations import json from enum import Enum, auto -from typing import Any, Callable, Dict, Optional +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from typing import Any, Callable, Dict, Optional import sentry_sdk from sentry_sdk.integrations import Integration @@ -56,8 +60,7 @@ class EventTypeMapping(Enum): Event = auto() -def tracing_level_to_sentry_level(level): - # type: (str) -> sentry_sdk._types.LogLevelStr +def tracing_level_to_sentry_level(level: str) -> sentry_sdk._types.LogLevelStr: level = RustTracingLevel(level) if level in (RustTracingLevel.Trace, RustTracingLevel.Debug): return "debug" @@ -97,15 +100,15 @@ def process_event(event: Dict[str, Any]) -> None: logger = metadata.get("target") level = tracing_level_to_sentry_level(metadata.get("level")) - message = event.get("message") # type: sentry_sdk._types.Any + message: sentry_sdk._types.Any = event.get("message") contexts = extract_contexts(event) - sentry_event = { + sentry_event: sentry_sdk._types.Event = { "logger": logger, "level": level, "message": message, "contexts": contexts, - } # type: sentry_sdk._types.Event + } sentry_sdk.capture_event(sentry_event)