diff --git a/sentry_sdk/integrations/sanic.py b/sentry_sdk/integrations/sanic.py index 06e30ffe31..1eed090332 100644 --- a/sentry_sdk/integrations/sanic.py +++ b/sentry_sdk/integrations/sanic.py @@ -1,3 +1,4 @@ +from __future__ import annotations import sys import weakref from inspect import isawaitable @@ -59,8 +60,9 @@ class SanicIntegration(Integration): origin = f"auto.http.{identifier}" version = None - def __init__(self, unsampled_statuses=frozenset({404})): - # type: (Optional[Container[int]]) -> None + def __init__( + self, unsampled_statuses: Optional[Container[int]] = frozenset({404}) + ) -> None: """ The unsampled_statuses parameter can be used to specify for which HTTP statuses the transactions should not be sent to Sentry. By default, transactions are sent for all @@ -70,8 +72,7 @@ def __init__(self, unsampled_statuses=frozenset({404})): self._unsampled_statuses = unsampled_statuses or set() @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: SanicIntegration.version = parse_version(SANIC_VERSION) _check_minimum_version(SanicIntegration, SanicIntegration.version) @@ -103,56 +104,45 @@ def setup_once(): class SanicRequestExtractor(RequestExtractor): - def content_length(self): - # type: () -> int + def content_length(self) -> int: if self.request.body is None: return 0 return len(self.request.body) - def cookies(self): - # type: () -> Dict[str, str] + def cookies(self) -> Dict[str, str]: return dict(self.request.cookies) - def raw_data(self): - # type: () -> bytes + def raw_data(self) -> bytes: return self.request.body - def form(self): - # type: () -> RequestParameters + def form(self) -> RequestParameters: return self.request.form - def is_json(self): - # type: () -> bool + def is_json(self) -> bool: raise NotImplementedError() - def json(self): - # type: () -> Optional[Any] + def json(self) -> Optional[Any]: return self.request.json - def files(self): - # type: () -> RequestParameters + def files(self) -> RequestParameters: return self.request.files - def size_of_file(self, file): - # type: (Any) -> int + def size_of_file(self, file: Any) -> int: return len(file.body or ()) -def _setup_sanic(): - # type: () -> None +def _setup_sanic() -> None: Sanic._startup = _startup ErrorHandler.lookup = _sentry_error_handler_lookup -def _setup_legacy_sanic(): - # type: () -> None +def _setup_legacy_sanic() -> None: Sanic.handle_request = _legacy_handle_request Router.get = _legacy_router_get ErrorHandler.lookup = _sentry_error_handler_lookup -async def _startup(self): - # type: (Sanic) -> None +async def _startup(self: Sanic) -> None: # This happens about as early in the lifecycle as possible, just after the # Request object is created. The body has not yet been consumed. self.signal("http.lifecycle.request")(_context_enter) @@ -171,8 +161,7 @@ async def _startup(self): await old_startup(self) -async def _context_enter(request): - # type: (Request) -> None +async def _context_enter(request: Request) -> None: request.ctx._sentry_do_integration = ( sentry_sdk.get_client().get_integration(SanicIntegration) is not None ) @@ -203,8 +192,9 @@ async def _context_enter(request): ).__enter__() -async def _context_exit(request, response=None): - # type: (Request, Optional[BaseHTTPResponse]) -> None +async def _context_exit( + request: Request, response: Optional[BaseHTTPResponse] = None +) -> None: with capture_internal_exceptions(): if not request.ctx._sentry_do_integration: return @@ -233,8 +223,7 @@ async def _context_exit(request, response=None): request.ctx._sentry_scope_manager.__exit__(None, None, None) -async def _set_transaction(request, route, **_): - # type: (Request, Route, **Any) -> None +async def _set_transaction(request: Request, route: Route, **_: Any) -> None: if request.ctx._sentry_do_integration: with capture_internal_exceptions(): scope = sentry_sdk.get_current_scope() @@ -242,8 +231,9 @@ async def _set_transaction(request, route, **_): scope.set_transaction_name(route_name, source=TransactionSource.COMPONENT) -def _sentry_error_handler_lookup(self, exception, *args, **kwargs): - # type: (Any, Exception, *Any, **Any) -> Optional[object] +def _sentry_error_handler_lookup( + self: Any, exception: Exception, *args: Any, **kwargs: Any +) -> Optional[object]: _capture_exception(exception) old_error_handler = old_error_handler_lookup(self, exception, *args, **kwargs) @@ -253,8 +243,9 @@ def _sentry_error_handler_lookup(self, exception, *args, **kwargs): if sentry_sdk.get_client().get_integration(SanicIntegration) is None: return old_error_handler - async def sentry_wrapped_error_handler(request, exception): - # type: (Request, Exception) -> Any + async def sentry_wrapped_error_handler( + request: Request, exception: Exception + ) -> Any: try: response = old_error_handler(request, exception) if isawaitable(response): @@ -276,8 +267,9 @@ async def sentry_wrapped_error_handler(request, exception): return sentry_wrapped_error_handler -async def _legacy_handle_request(self, request, *args, **kwargs): - # type: (Any, Request, *Any, **Any) -> Any +async def _legacy_handle_request( + self: Any, request: Request, *args: Any, **kwargs: Any +) -> Any: if sentry_sdk.get_client().get_integration(SanicIntegration) is None: return await old_handle_request(self, request, *args, **kwargs) @@ -294,8 +286,7 @@ async def _legacy_handle_request(self, request, *args, **kwargs): return response -def _legacy_router_get(self, *args): - # type: (Any, Union[Any, Request]) -> Any +def _legacy_router_get(self: Any, *args: Union[Any, Request]) -> Any: rv = old_router_get(self, *args) if sentry_sdk.get_client().get_integration(SanicIntegration) is not None: with capture_internal_exceptions(): @@ -325,8 +316,7 @@ def _legacy_router_get(self, *args): @ensure_integration_enabled(SanicIntegration) -def _capture_exception(exception): - # type: (Union[ExcInfo, BaseException]) -> None +def _capture_exception(exception: Union[ExcInfo, BaseException]) -> None: with capture_internal_exceptions(): event, hint = event_from_exception( exception, @@ -340,10 +330,8 @@ def _capture_exception(exception): sentry_sdk.capture_event(event, hint=hint) -def _make_request_processor(weak_request): - # type: (Callable[[], Request]) -> EventProcessor - def sanic_processor(event, hint): - # type: (Event, Optional[Hint]) -> Optional[Event] +def _make_request_processor(weak_request: Callable[[], Request]) -> EventProcessor: + def sanic_processor(event: Event, hint: Optional[Hint]) -> Optional[Event]: try: if hint and issubclass(hint["exc_info"][0], SanicException): diff --git a/sentry_sdk/integrations/serverless.py b/sentry_sdk/integrations/serverless.py index 760c07ffad..5cf160691d 100644 --- a/sentry_sdk/integrations/serverless.py +++ b/sentry_sdk/integrations/serverless.py @@ -1,10 +1,11 @@ +from __future__ import annotations import sys from functools import wraps import sentry_sdk from sentry_sdk.utils import event_from_exception, reraise -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, overload if TYPE_CHECKING: from typing import Any @@ -12,36 +13,24 @@ from typing import TypeVar from typing import Union from typing import Optional - from typing import overload F = TypeVar("F", bound=Callable[..., Any]) -else: + @overload + def serverless_function(f: F, flush: bool = True) -> F: + pass - def overload(x): - # type: (F) -> F - return x + @overload + def serverless_function(f: None = None, flush: bool = True) -> Callable[[F], F]: + pass -@overload -def serverless_function(f, flush=True): - # type: (F, bool) -> F - pass - - -@overload -def serverless_function(f=None, flush=True): # noqa: F811 - # type: (None, bool) -> Callable[[F], F] - pass - - -def serverless_function(f=None, flush=True): # noqa - # type: (Optional[F], bool) -> Union[F, Callable[[F], F]] - def wrapper(f): - # type: (F) -> F +def serverless_function( + f: Optional[F] = None, flush: bool = True +) -> Union[F, Callable[[F], F]]: + def wrapper(f: F) -> F: @wraps(f) - def inner(*args, **kwargs): - # type: (*Any, **Any) -> Any + def inner(*args: Any, **kwargs: Any) -> Any: with sentry_sdk.isolation_scope() as scope: scope.clear_breadcrumbs() @@ -61,8 +50,7 @@ def inner(*args, **kwargs): return wrapper(f) -def _capture_and_reraise(): - # type: () -> None +def _capture_and_reraise() -> None: exc_info = sys.exc_info() client = sentry_sdk.get_client() if client.is_active(): diff --git a/sentry_sdk/integrations/socket.py b/sentry_sdk/integrations/socket.py index 544a63c0f0..67e2feb2b2 100644 --- a/sentry_sdk/integrations/socket.py +++ b/sentry_sdk/integrations/socket.py @@ -1,3 +1,4 @@ +from __future__ import annotations import socket import sentry_sdk @@ -17,8 +18,7 @@ class SocketIntegration(Integration): origin = f"auto.socket.{identifier}" @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: """ patches two of the most used functions of socket: create_connection and getaddrinfo(dns resolver) """ @@ -26,8 +26,9 @@ def setup_once(): _patch_getaddrinfo() -def _get_span_description(host, port): - # type: (Union[bytes, str, None], Union[bytes, str, int, None]) -> str +def _get_span_description( + host: Union[bytes, str, None], port: Union[bytes, str, int, None] +) -> str: try: host = host.decode() # type: ignore @@ -43,16 +44,14 @@ def _get_span_description(host, port): return description -def _patch_create_connection(): - # type: () -> None +def _patch_create_connection() -> None: real_create_connection = socket.create_connection def create_connection( - address, - timeout=socket._GLOBAL_DEFAULT_TIMEOUT, # type: ignore - source_address=None, - ): - # type: (Tuple[Optional[str], int], Optional[float], Optional[Tuple[Union[bytearray, bytes, str], int]])-> socket.socket + address: Tuple[Optional[str], int], + timeout: Optional[float] = socket._GLOBAL_DEFAULT_TIMEOUT, # type: ignore + source_address: Optional[Tuple[Union[bytearray, bytes, str], int]] = None, + ) -> socket.socket: integration = sentry_sdk.get_client().get_integration(SocketIntegration) if integration is None: return real_create_connection(address, timeout, source_address) @@ -76,12 +75,25 @@ def create_connection( socket.create_connection = create_connection # type: ignore -def _patch_getaddrinfo(): - # type: () -> None +def _patch_getaddrinfo() -> None: real_getaddrinfo = socket.getaddrinfo - def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): - # type: (Union[bytes, str, None], Union[bytes, str, int, None], int, int, int, int) -> List[Tuple[AddressFamily, SocketKind, int, str, Union[Tuple[str, int], Tuple[str, int, int, int], Tuple[int, bytes]]]] + def getaddrinfo( + host: Union[bytes, str, None], + port: Union[bytes, str, int, None], + family: int = 0, + type: int = 0, + proto: int = 0, + flags: int = 0, + ) -> List[ + Tuple[ + AddressFamily, + SocketKind, + int, + str, + Union[Tuple[str, int], Tuple[str, int, int, int], Tuple[int, bytes]], + ] + ]: integration = sentry_sdk.get_client().get_integration(SocketIntegration) if integration is None: return real_getaddrinfo(host, port, family, type, proto, flags) diff --git a/sentry_sdk/integrations/sqlalchemy.py b/sentry_sdk/integrations/sqlalchemy.py index 4c4d8fde8c..658d10b3ca 100644 --- a/sentry_sdk/integrations/sqlalchemy.py +++ b/sentry_sdk/integrations/sqlalchemy.py @@ -1,3 +1,4 @@ +from __future__ import annotations from sentry_sdk.consts import SPANSTATUS, SPANDATA from sentry_sdk.integrations import _check_minimum_version, Integration, DidNotEnable from sentry_sdk.tracing_utils import add_query_source, record_sql_queries @@ -29,8 +30,7 @@ class SqlalchemyIntegration(Integration): origin = f"auto.db.{identifier}" @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: version = parse_version(SQLALCHEMY_VERSION) _check_minimum_version(SqlalchemyIntegration, version) @@ -41,9 +41,14 @@ def setup_once(): @ensure_integration_enabled(SqlalchemyIntegration) def _before_cursor_execute( - conn, cursor, statement, parameters, context, executemany, *args -): - # type: (Any, Any, Any, Any, Any, bool, *Any) -> None + conn: Any, + cursor: Any, + statement: Any, + parameters: Any, + context: Any, + executemany: bool, + *args: Any, +) -> None: ctx_mgr = record_sql_queries( cursor, statement, @@ -62,13 +67,14 @@ def _before_cursor_execute( @ensure_integration_enabled(SqlalchemyIntegration) -def _after_cursor_execute(conn, cursor, statement, parameters, context, *args): - # type: (Any, Any, Any, Any, Any, *Any) -> None - ctx_mgr = getattr( +def _after_cursor_execute( + conn: Any, cursor: Any, statement: Any, parameters: Any, context: Any, *args: Any +) -> None: + ctx_mgr: Optional[ContextManager[Any]] = getattr( context, "_sentry_sql_span_manager", None - ) # type: Optional[ContextManager[Any]] + ) - span = getattr(context, "_sentry_sql_span", None) # type: Optional[Span] + span: Optional[Span] = getattr(context, "_sentry_sql_span", None) if span is not None: with capture_internal_exceptions(): add_query_source(span) @@ -78,13 +84,12 @@ def _after_cursor_execute(conn, cursor, statement, parameters, context, *args): ctx_mgr.__exit__(None, None, None) -def _handle_error(context, *args): - # type: (Any, *Any) -> None +def _handle_error(context: Any, *args: Any) -> None: execution_context = context.execution_context if execution_context is None: return - span = getattr(execution_context, "_sentry_sql_span", None) # type: Optional[Span] + span: Optional[Span] = getattr(execution_context, "_sentry_sql_span", None) if span is not None: span.set_status(SPANSTATUS.INTERNAL_ERROR) @@ -92,9 +97,9 @@ def _handle_error(context, *args): # _after_cursor_execute does not get called for crashing SQL stmts. Judging # from SQLAlchemy codebase it does seem like any error coming into this # handler is going to be fatal. - ctx_mgr = getattr( + ctx_mgr: Optional[ContextManager[Any]] = getattr( execution_context, "_sentry_sql_span_manager", None - ) # type: Optional[ContextManager[Any]] + ) if ctx_mgr is not None: execution_context._sentry_sql_span_manager = None @@ -102,8 +107,7 @@ def _handle_error(context, *args): # See: https://docs.sqlalchemy.org/en/20/dialects/index.html -def _get_db_system(name): - # type: (str) -> Optional[str] +def _get_db_system(name: str) -> Optional[str]: name = str(name) if "sqlite" in name: @@ -124,8 +128,7 @@ def _get_db_system(name): return None -def _set_db_data(span, conn): - # type: (Span, Any) -> None +def _set_db_data(span: Span, conn: Any) -> None: db_system = _get_db_system(conn.engine.name) if db_system is not None: span.set_attribute(SPANDATA.DB_SYSTEM, db_system) diff --git a/sentry_sdk/integrations/starlette.py b/sentry_sdk/integrations/starlette.py index e6016a3624..117a0b0031 100644 --- a/sentry_sdk/integrations/starlette.py +++ b/sentry_sdk/integrations/starlette.py @@ -1,3 +1,4 @@ +from __future__ import annotations import asyncio import functools from collections.abc import Set @@ -82,12 +83,11 @@ class StarletteIntegration(Integration): def __init__( self, - transaction_style="url", # type: str - failed_request_status_codes=_DEFAULT_FAILED_REQUEST_STATUS_CODES, # type: Set[int] - middleware_spans=True, # type: bool - http_methods_to_capture=DEFAULT_HTTP_METHODS_TO_CAPTURE, # type: tuple[str, ...] - ): - # type: (...) -> None + transaction_style: str = "url", + failed_request_status_codes: Set[int] = _DEFAULT_FAILED_REQUEST_STATUS_CODES, + middleware_spans: bool = True, + 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)" @@ -100,8 +100,7 @@ def __init__( self.failed_request_status_codes = failed_request_status_codes @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: version = parse_version(STARLETTE_VERSION) if version is None: @@ -117,12 +116,16 @@ def setup_once(): patch_templates() -def _enable_span_for_middleware(middleware_class): - # type: (Any) -> type +def _enable_span_for_middleware(middleware_class: Any) -> type: old_call = middleware_class.__call__ - async def _create_span_call(app, scope, receive, send, **kwargs): - # type: (Any, Dict[str, Any], Callable[[], Awaitable[Dict[str, Any]]], Callable[[Dict[str, Any]], Awaitable[None]], Any) -> None + async def _create_span_call( + app: Any, + scope: Dict[str, Any], + receive: Callable[[], Awaitable[Dict[str, Any]]], + send: Callable[[Dict[str, Any]], Awaitable[None]], + **kwargs: Any, + ) -> None: integration = sentry_sdk.get_client().get_integration(StarletteIntegration) if integration is None or not integration.middleware_spans: return await old_call(app, scope, receive, send, **kwargs) @@ -146,8 +149,7 @@ async def _create_span_call(app, scope, receive, send, **kwargs): middleware_span.set_tag("starlette.middleware_name", middleware_name) # Creating spans for the "receive" callback - async def _sentry_receive(*args, **kwargs): - # type: (*Any, **Any) -> Any + async def _sentry_receive(*args: Any, **kwargs: Any) -> Any: with sentry_sdk.start_span( op=OP.MIDDLEWARE_STARLETTE_RECEIVE, name=getattr(receive, "__qualname__", str(receive)), @@ -162,8 +164,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(*args, **kwargs): - # type: (*Any, **Any) -> Any + async def _sentry_send(*args: Any, **kwargs: Any) -> Any: with sentry_sdk.start_span( op=OP.MIDDLEWARE_STARLETTE_SEND, name=getattr(send, "__qualname__", str(send)), @@ -192,8 +193,7 @@ async def _sentry_send(*args, **kwargs): @ensure_integration_enabled(StarletteIntegration) -def _capture_exception(exception, handled=False): - # type: (BaseException, **Any) -> None +def _capture_exception(exception: BaseException, handled: Any = False) -> None: event, hint = event_from_exception( exception, client_options=sentry_sdk.get_client().options, @@ -203,8 +203,7 @@ def _capture_exception(exception, handled=False): sentry_sdk.capture_event(event, hint=hint) -def patch_exception_middleware(middleware_class): - # type: (Any) -> None +def patch_exception_middleware(middleware_class: Any) -> None: """ Capture all exceptions in Starlette app and also extract user information. @@ -215,15 +214,15 @@ def patch_exception_middleware(middleware_class): if not_yet_patched: - def _sentry_middleware_init(self, *args, **kwargs): - # type: (Any, Any, Any) -> None + def _sentry_middleware_init(self: Any, *args: Any, **kwargs: Any) -> None: old_middleware_init(self, *args, **kwargs) # Patch existing exception handlers old_handlers = self._exception_handlers.copy() - async def _sentry_patched_exception_handler(self, *args, **kwargs): - # type: (Any, Any, Any) -> None + async def _sentry_patched_exception_handler( + self: Any, *args: Any, **kwargs: Any + ) -> None: integration = sentry_sdk.get_client().get_integration( StarletteIntegration ) @@ -261,8 +260,12 @@ async def _sentry_patched_exception_handler(self, *args, **kwargs): old_call = middleware_class.__call__ - async def _sentry_exceptionmiddleware_call(self, scope, receive, send): - # type: (Dict[str, Any], Dict[str, Any], Callable[[], Awaitable[Dict[str, Any]]], Callable[[Dict[str, Any]], Awaitable[None]]) -> None + async def _sentry_exceptionmiddleware_call( + self: Dict[str, Any], + scope: Dict[str, Any], + receive: Callable[[], Awaitable[Dict[str, Any]]], + send: Callable[[Dict[str, Any]], Awaitable[None]], + ) -> None: # Also add the user (that was eventually set by be Authentication middle # that was called before this middleware). This is done because the authentication # middleware sets the user in the scope and then (in the same function) @@ -281,8 +284,7 @@ async def _sentry_exceptionmiddleware_call(self, scope, receive, send): @ensure_integration_enabled(StarletteIntegration) -def _add_user_to_sentry_scope(scope): - # type: (Dict[str, Any]) -> None +def _add_user_to_sentry_scope(scope: Dict[str, Any]) -> None: """ Extracts user information from the ASGI scope and adds it to Sentry's scope. @@ -293,7 +295,7 @@ def _add_user_to_sentry_scope(scope): if not should_send_default_pii(): return - user_info = {} # type: Dict[str, Any] + user_info: Dict[str, Any] = {} starlette_user = scope["user"] username = getattr(starlette_user, "username", None) @@ -312,8 +314,7 @@ def _add_user_to_sentry_scope(scope): sentry_scope.set_user(user_info) -def patch_authentication_middleware(middleware_class): - # type: (Any) -> None +def patch_authentication_middleware(middleware_class: Any) -> None: """ Add user information to Sentry scope. """ @@ -323,16 +324,19 @@ def patch_authentication_middleware(middleware_class): if not_yet_patched: - async def _sentry_authenticationmiddleware_call(self, scope, receive, send): - # type: (Dict[str, Any], Dict[str, Any], Callable[[], Awaitable[Dict[str, Any]]], Callable[[Dict[str, Any]], Awaitable[None]]) -> None + async def _sentry_authenticationmiddleware_call( + self: Dict[str, Any], + scope: Dict[str, Any], + receive: Callable[[], Awaitable[Dict[str, Any]]], + send: Callable[[Dict[str, Any]], Awaitable[None]], + ) -> None: await old_call(self, scope, receive, send) _add_user_to_sentry_scope(scope) middleware_class.__call__ = _sentry_authenticationmiddleware_call -def patch_middlewares(): - # type: () -> None +def patch_middlewares() -> None: """ Patches Starlettes `Middleware` class to record spans for every middleware invoked. @@ -343,8 +347,9 @@ def patch_middlewares(): if not_yet_patched: - def _sentry_middleware_init(self, cls, *args, **kwargs): - # type: (Any, Any, Any, Any) -> None + def _sentry_middleware_init( + self: Any, cls: Any, *args: Any, **kwargs: Any + ) -> None: if cls == SentryAsgiMiddleware: return old_middleware_init(self, cls, *args, **kwargs) @@ -360,15 +365,15 @@ def _sentry_middleware_init(self, cls, *args, **kwargs): Middleware.__init__ = _sentry_middleware_init -def patch_asgi_app(): - # type: () -> None +def patch_asgi_app() -> None: """ Instrument Starlette ASGI app using the SentryAsgiMiddleware. """ old_app = Starlette.__call__ - async def _sentry_patched_asgi_app(self, scope, receive, send): - # type: (Starlette, StarletteScope, Receive, Send) -> None + async def _sentry_patched_asgi_app( + self: Starlette, scope: StarletteScope, receive: Receive, send: Send + ) -> None: integration = sentry_sdk.get_client().get_integration(StarletteIntegration) if integration is None: return await old_app(self, scope, receive, send) @@ -393,8 +398,7 @@ async def _sentry_patched_asgi_app(self, scope, receive, send): # This was vendored in from Starlette to support Starlette 0.19.1 because # this function was only introduced in 0.20.x -def _is_async_callable(obj): - # type: (Any) -> bool +def _is_async_callable(obj: Any) -> bool: while isinstance(obj, functools.partial): obj = obj.func @@ -403,19 +407,16 @@ def _is_async_callable(obj): ) -def patch_request_response(): - # type: () -> None +def patch_request_response() -> None: old_request_response = starlette.routing.request_response - def _sentry_request_response(func): - # type: (Callable[[Any], Any]) -> ASGIApp + def _sentry_request_response(func: Callable[[Any], Any]) -> ASGIApp: old_func = func is_coroutine = _is_async_callable(old_func) if is_coroutine: - async def _sentry_async_func(*args, **kwargs): - # type: (*Any, **Any) -> Any + async def _sentry_async_func(*args: Any, **kwargs: Any) -> Any: integration = sentry_sdk.get_client().get_integration( StarletteIntegration ) @@ -434,10 +435,10 @@ async def _sentry_async_func(*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: # Add info from request to event request_info = event.get("request", {}) @@ -464,8 +465,7 @@ def event_processor(event, hint): else: @functools.wraps(old_func) - def _sentry_sync_func(*args, **kwargs): - # type: (*Any, **Any) -> Any + def _sentry_sync_func(*args: Any, **kwargs: Any) -> Any: integration = sentry_sdk.get_client().get_integration( StarletteIntegration ) @@ -489,10 +489,10 @@ def _sentry_sync_func(*args, **kwargs): extractor = StarletteRequestExtractor(request) cookies = extractor.extract_cookies_from_request() - 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", {}) @@ -519,8 +519,7 @@ def event_processor(event, hint): starlette.routing.request_response = _sentry_request_response -def patch_templates(): - # type: () -> None +def patch_templates() -> None: # If markupsafe is not installed, then Jinja2 is not installed # (markupsafe is a dependency of Jinja2) @@ -540,10 +539,10 @@ def patch_templates(): if not_yet_patched: - def _sentry_jinja2templates_init(self, *args, **kwargs): - # type: (Jinja2Templates, *Any, **Any) -> None - def add_sentry_trace_meta(request): - # type: (Request) -> Dict[str, Any] + def _sentry_jinja2templates_init( + self: Jinja2Templates, *args: Any, **kwargs: Any + ) -> None: + def add_sentry_trace_meta(request: Request) -> Dict[str, Any]: trace_meta = Markup( sentry_sdk.get_current_scope().trace_propagation_meta() ) @@ -567,25 +566,26 @@ class StarletteRequestExtractor: (like form data or cookies) and adds it to the Sentry event. """ - request = None # type: Request + request: Request = None - def __init__(self, request): - # type: (StarletteRequestExtractor, Request) -> None + def __init__(self: StarletteRequestExtractor, request: Request) -> None: self.request = request - def extract_cookies_from_request(self): - # type: (StarletteRequestExtractor) -> Optional[Dict[str, Any]] - cookies = None # type: Optional[Dict[str, Any]] + def extract_cookies_from_request( + self: StarletteRequestExtractor, + ) -> Optional[Dict[str, Any]]: + cookies: Optional[Dict[str, Any]] = None if should_send_default_pii(): cookies = self.cookies() return cookies - async def extract_request_info(self): - # type: (StarletteRequestExtractor) -> Optional[Dict[str, Any]] + async def extract_request_info( + self: StarletteRequestExtractor, + ) -> Optional[Dict[str, Any]]: client = sentry_sdk.get_client() - request_info = {} # type: Dict[str, Any] + request_info: Dict[str, Any] = {} with capture_internal_exceptions(): # Add cookies @@ -629,19 +629,16 @@ async def extract_request_info(self): request_info["data"] = AnnotatedValue.removed_because_raw_data() return request_info - async def content_length(self): - # type: (StarletteRequestExtractor) -> Optional[int] + async def content_length(self: StarletteRequestExtractor) -> Optional[int]: if "content-length" in self.request.headers: return int(self.request.headers["content-length"]) return None - def cookies(self): - # type: (StarletteRequestExtractor) -> Dict[str, Any] + def cookies(self: StarletteRequestExtractor) -> Dict[str, Any]: return self.request.cookies - async def form(self): - # type: (StarletteRequestExtractor) -> Any + async def form(self: StarletteRequestExtractor) -> Any: if multipart is None: return None @@ -653,12 +650,10 @@ async def form(self): return await self.request.form() - def is_json(self): - # type: (StarletteRequestExtractor) -> bool + def is_json(self: StarletteRequestExtractor) -> bool: return _is_json_content_type(self.request.headers.get("content-type")) - async def json(self): - # type: (StarletteRequestExtractor) -> Optional[Dict[str, Any]] + async def json(self: StarletteRequestExtractor) -> Optional[Dict[str, Any]]: if not self.is_json(): return None try: @@ -667,8 +662,7 @@ async def json(self): return None -def _transaction_name_from_router(scope): - # type: (StarletteScope) -> Optional[str] +def _transaction_name_from_router(scope: StarletteScope) -> Optional[str]: router = scope.get("router") if not router: return None @@ -685,8 +679,9 @@ def _transaction_name_from_router(scope): return None -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 = None source = SOURCE_FOR_STYLE[transaction_style] @@ -708,8 +703,9 @@ def _set_transaction_name_and_source(scope, transaction_style, request): ) -def _get_transaction_from_middleware(app, asgi_scope, integration): - # type: (Any, Dict[str, Any], StarletteIntegration) -> Tuple[Optional[str], Optional[str]] +def _get_transaction_from_middleware( + app: Any, asgi_scope: Dict[str, Any], integration: StarletteIntegration +) -> Tuple[Optional[str], Optional[str]]: name = None source = None diff --git a/sentry_sdk/integrations/starlite.py b/sentry_sdk/integrations/starlite.py index 928c697373..e9b42f29b4 100644 --- a/sentry_sdk/integrations/starlite.py +++ b/sentry_sdk/integrations/starlite.py @@ -1,3 +1,4 @@ +from __future__ import annotations import sentry_sdk from sentry_sdk.consts import OP, SOURCE_FOR_STYLE, TransactionSource from sentry_sdk.integrations import DidNotEnable, Integration @@ -48,16 +49,16 @@ class StarliteIntegration(Integration): origin = f"auto.http.{identifier}" @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: patch_app_init() patch_middlewares() patch_http_route_handle() class SentryStarliteASGIMiddleware(SentryAsgiMiddleware): - def __init__(self, app, span_origin=StarliteIntegration.origin): - # type: (ASGIApp, str) -> None + def __init__( + self, app: ASGIApp, span_origin: str = StarliteIntegration.origin + ) -> None: super().__init__( app=app, unsafe_context_data=False, @@ -67,8 +68,7 @@ def __init__(self, app, span_origin=StarliteIntegration.origin): ) -def patch_app_init(): - # type: () -> None +def patch_app_init() -> None: """ Replaces the Starlite class's `__init__` function in order to inject `after_exception` handlers and set the `SentryStarliteASGIMiddleware` as the outmost middleware in the stack. @@ -79,8 +79,7 @@ def patch_app_init(): old__init__ = Starlite.__init__ @ensure_integration_enabled(StarliteIntegration, old__init__) - def injection_wrapper(self, *args, **kwargs): - # type: (Starlite, *Any, **Any) -> None + def injection_wrapper(self: Starlite, *args: Any, **kwargs: Any) -> None: after_exception = kwargs.pop("after_exception", []) kwargs.update( after_exception=[ @@ -101,13 +100,11 @@ def injection_wrapper(self, *args, **kwargs): Starlite.__init__ = injection_wrapper -def patch_middlewares(): - # type: () -> None +def patch_middlewares() -> None: old_resolve_middleware_stack = BaseRouteHandler.resolve_middleware @ensure_integration_enabled(StarliteIntegration, 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) @@ -116,8 +113,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 SentryStarliteASGIMiddleware @@ -125,12 +121,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, StarliteScope, Receive, Send) -> None + async def _create_span_call( + self: MiddlewareProtocol, scope: StarliteScope, receive: Receive, send: Send + ) -> None: if sentry_sdk.get_client().get_integration(StarliteIntegration) is None: return await old_call(self, scope, receive, send) @@ -144,8 +141,9 @@ async def _create_span_call(self, scope, receive, send): middleware_span.set_tag("starlite.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(StarliteIntegration) is None: return await receive(*args, **kwargs) with sentry_sdk.start_span( @@ -162,8 +160,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(StarliteIntegration) is None: return await send(message) with sentry_sdk.start_span( @@ -192,19 +189,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(StarliteIntegration) 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) @@ -212,8 +209,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", {}) @@ -256,8 +252,7 @@ def event_processor(event, _): HTTPRoute.handle = handle_wrapper -def retrieve_user_from_scope(scope): - # type: (StarliteScope) -> Optional[dict[str, Any]] +def retrieve_user_from_scope(scope: StarliteScope) -> Optional[dict[str, Any]]: scope_user = scope.get("user") if not scope_user: return None @@ -276,9 +271,8 @@ def retrieve_user_from_scope(scope): @ensure_integration_enabled(StarliteIntegration) -def exception_handler(exc, scope, _): - # type: (Exception, StarliteScope, State) -> None - user_info = None # type: Optional[dict[str, Any]] +def exception_handler(exc: Exception, scope: StarliteScope, _: State) -> 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/statsig.py b/sentry_sdk/integrations/statsig.py index 1d84eb8aa2..9a62e3d18f 100644 --- a/sentry_sdk/integrations/statsig.py +++ b/sentry_sdk/integrations/statsig.py @@ -1,3 +1,4 @@ +from __future__ import annotations from functools import wraps from typing import Any, TYPE_CHECKING @@ -19,8 +20,7 @@ class StatsigIntegration(Integration): identifier = "statsig" @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: version = parse_version(STATSIG_VERSION) _check_minimum_version(StatsigIntegration, version, "statsig") @@ -28,8 +28,9 @@ def setup_once(): old_check_gate = statsig_module.check_gate @wraps(old_check_gate) - def sentry_check_gate(user, gate, *args, **kwargs): - # type: (StatsigUser, str, *Any, **Any) -> Any + def sentry_check_gate( + user: StatsigUser, gate: str, *args: Any, **kwargs: Any + ) -> Any: enabled = old_check_gate(user, gate, *args, **kwargs) add_feature_flag(gate, enabled) return enabled diff --git a/sentry_sdk/integrations/stdlib.py b/sentry_sdk/integrations/stdlib.py index 2507eb7895..9058939c04 100644 --- a/sentry_sdk/integrations/stdlib.py +++ b/sentry_sdk/integrations/stdlib.py @@ -1,3 +1,4 @@ +from __future__ import annotations import os import subprocess import sys @@ -34,25 +35,23 @@ from sentry_sdk._types import Event, Hint -_RUNTIME_CONTEXT = { +_RUNTIME_CONTEXT: dict[str, object] = { "name": platform.python_implementation(), "version": "%s.%s.%s" % (sys.version_info[:3]), "build": sys.version, -} # type: dict[str, object] +} class StdlibIntegration(Integration): identifier = "stdlib" @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: _install_httplib() _install_subprocess() @add_global_event_processor - def add_python_runtime_context(event, hint): - # type: (Event, Hint) -> Optional[Event] + def add_python_runtime_context(event: Event, hint: Hint) -> Optional[Event]: if sentry_sdk.get_client().get_integration(StdlibIntegration) is not None: contexts = event.setdefault("contexts", {}) if isinstance(contexts, dict) and "runtime" not in contexts: @@ -61,13 +60,13 @@ def add_python_runtime_context(event, hint): return event -def _install_httplib(): - # type: () -> None +def _install_httplib() -> None: real_putrequest = HTTPConnection.putrequest real_getresponse = HTTPConnection.getresponse - def putrequest(self, method, url, *args, **kwargs): - # type: (HTTPConnection, str, str, *Any, **Any) -> Any + def putrequest( + self: HTTPConnection, method: str, url: str, *args: Any, **kwargs: Any + ) -> Any: host = self.host port = self.port default_port = self.default_port @@ -134,8 +133,7 @@ def putrequest(self, method, url, *args, **kwargs): return rv - def getresponse(self, *args, **kwargs): - # type: (HTTPConnection, *Any, **Any) -> Any + def getresponse(self: HTTPConnection, *args: Any, **kwargs: Any) -> Any: span = getattr(self, "_sentrysdk_span", None) if span is None: @@ -167,8 +165,13 @@ def getresponse(self, *args, **kwargs): HTTPConnection.getresponse = getresponse # type: ignore[method-assign] -def _init_argument(args, kwargs, name, position, setdefault_callback=None): - # type: (List[Any], Dict[Any, Any], str, int, Optional[Callable[[Any], Any]]) -> Any +def _init_argument( + args: List[Any], + kwargs: Dict[Any, Any], + name: str, + position: int, + setdefault_callback: Optional[Callable[[Any], Any]] = None, +) -> Any: """ given (*args, **kwargs) of a function call, retrieve (and optionally set a default for) an argument by either name or position. @@ -198,13 +201,13 @@ def _init_argument(args, kwargs, name, position, setdefault_callback=None): return rv -def _install_subprocess(): - # type: () -> None +def _install_subprocess() -> None: old_popen_init = subprocess.Popen.__init__ @ensure_integration_enabled(StdlibIntegration, old_popen_init) - def sentry_patched_popen_init(self, *a, **kw): - # type: (subprocess.Popen[Any], *Any, **Any) -> None + def sentry_patched_popen_init( + self: subprocess.Popen[Any], *a: Any, **kw: Any + ) -> None: # Convert from tuple to list to be able to set values. a = list(a) @@ -279,8 +282,9 @@ def sentry_patched_popen_init(self, *a, **kw): old_popen_wait = subprocess.Popen.wait @ensure_integration_enabled(StdlibIntegration, old_popen_wait) - def sentry_patched_popen_wait(self, *a, **kw): - # type: (subprocess.Popen[Any], *Any, **Any) -> Any + def sentry_patched_popen_wait( + self: subprocess.Popen[Any], *a: Any, **kw: Any + ) -> Any: with sentry_sdk.start_span( op=OP.SUBPROCESS_WAIT, origin="auto.subprocess.stdlib.subprocess", @@ -294,8 +298,9 @@ def sentry_patched_popen_wait(self, *a, **kw): old_popen_communicate = subprocess.Popen.communicate @ensure_integration_enabled(StdlibIntegration, old_popen_communicate) - def sentry_patched_popen_communicate(self, *a, **kw): - # type: (subprocess.Popen[Any], *Any, **Any) -> Any + def sentry_patched_popen_communicate( + self: subprocess.Popen[Any], *a: Any, **kw: Any + ) -> Any: with sentry_sdk.start_span( op=OP.SUBPROCESS_COMMUNICATE, origin="auto.subprocess.stdlib.subprocess", @@ -307,6 +312,5 @@ def sentry_patched_popen_communicate(self, *a, **kw): subprocess.Popen.communicate = sentry_patched_popen_communicate # type: ignore -def get_subprocess_traceparent_headers(): - # type: () -> EnvironHeaders +def get_subprocess_traceparent_headers() -> EnvironHeaders: return EnvironHeaders(os.environ, prefix="SUBPROCESS_") diff --git a/sentry_sdk/integrations/strawberry.py b/sentry_sdk/integrations/strawberry.py index 274ae8d1c9..7994daded6 100644 --- a/sentry_sdk/integrations/strawberry.py +++ b/sentry_sdk/integrations/strawberry.py @@ -1,3 +1,4 @@ +from __future__ import annotations import functools import hashlib from inspect import isawaitable @@ -62,8 +63,7 @@ class StrawberryIntegration(Integration): identifier = "strawberry" origin = f"auto.graphql.{identifier}" - def __init__(self, async_execution=None): - # type: (Optional[bool]) -> None + def __init__(self, async_execution: Optional[bool] = None) -> None: if async_execution not in (None, False, True): raise ValueError( 'Invalid value for async_execution: "{}" (must be bool)'.format( @@ -73,8 +73,7 @@ def __init__(self, async_execution=None): self.async_execution = async_execution @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: version = package_version("strawberry-graphql") _check_minimum_version(StrawberryIntegration, version, "strawberry-graphql") @@ -82,13 +81,11 @@ def setup_once(): _patch_views() -def _patch_schema_init(): - # type: () -> None +def _patch_schema_init() -> None: old_schema_init = Schema.__init__ @functools.wraps(old_schema_init) - def _sentry_patched_schema_init(self, *args, **kwargs): - # type: (Schema, Any, Any) -> None + def _sentry_patched_schema_init(self: Schema, *args: Any, **kwargs: Any) -> None: integration = sentry_sdk.get_client().get_integration(StrawberryIntegration) if integration is None: return old_schema_init(self, *args, **kwargs) @@ -121,17 +118,15 @@ def _sentry_patched_schema_init(self, *args, **kwargs): class SentryAsyncExtension(SchemaExtension): def __init__( - self, + self: Any, *, - execution_context=None, - ): - # type: (Any, Optional[ExecutionContext]) -> None + execution_context: Optional[ExecutionContext] = None, + ) -> None: if execution_context: self.execution_context = execution_context @cached_property - def _resource_name(self): - # type: () -> str + def _resource_name(self) -> str: query_hash = self.hash_query(self.execution_context.query) # type: ignore if self.execution_context.operation_name: @@ -139,12 +134,10 @@ def _resource_name(self): return query_hash - def hash_query(self, query): - # type: (str) -> str + def hash_query(self, query: str) -> str: return hashlib.md5(query.encode("utf-8")).hexdigest() - def on_operation(self): - # type: () -> Generator[None, None, None] + def on_operation(self) -> Generator[None, None, None]: self._operation_name = self.execution_context.operation_name operation_type = "query" @@ -205,8 +198,7 @@ def on_operation(self): if root_span: root_span.op = op - def on_validate(self): - # type: () -> Generator[None, None, None] + def on_validate(self) -> Generator[None, None, None]: with sentry_sdk.start_span( op=OP.GRAPHQL_VALIDATE, name="validation", @@ -214,8 +206,7 @@ def on_validate(self): ): yield - def on_parse(self): - # type: () -> Generator[None, None, None] + def on_parse(self) -> Generator[None, None, None]: with sentry_sdk.start_span( op=OP.GRAPHQL_PARSE, name="parsing", @@ -223,12 +214,21 @@ def on_parse(self): ): yield - def should_skip_tracing(self, _next, info): - # type: (Callable[[Any, GraphQLResolveInfo, Any, Any], Any], GraphQLResolveInfo) -> bool + def should_skip_tracing( + self, + _next: Callable[[Any, GraphQLResolveInfo, Any, Any], Any], + info: GraphQLResolveInfo, + ) -> bool: return strawberry_should_skip_tracing(_next, info) - async def _resolve(self, _next, root, info, *args, **kwargs): - # type: (Callable[[Any, GraphQLResolveInfo, Any, Any], Any], Any, GraphQLResolveInfo, str, Any) -> Any + async def _resolve( + self, + _next: Callable[[Any, GraphQLResolveInfo, Any, Any], Any], + root: Any, + info: GraphQLResolveInfo, + *args: str, + **kwargs: Any, + ) -> Any: result = _next(root, info, *args, **kwargs) if isawaitable(result): @@ -236,8 +236,14 @@ async def _resolve(self, _next, root, info, *args, **kwargs): return result - async def resolve(self, _next, root, info, *args, **kwargs): - # type: (Callable[[Any, GraphQLResolveInfo, Any, Any], Any], Any, GraphQLResolveInfo, str, Any) -> Any + async def resolve( + self, + _next: Callable[[Any, GraphQLResolveInfo, Any, Any], Any], + root: Any, + info: GraphQLResolveInfo, + *args: str, + **kwargs: Any, + ) -> Any: if self.should_skip_tracing(_next, info): return await self._resolve(_next, root, info, *args, **kwargs) @@ -257,8 +263,14 @@ async def resolve(self, _next, root, info, *args, **kwargs): class SentrySyncExtension(SentryAsyncExtension): - def resolve(self, _next, root, info, *args, **kwargs): - # type: (Callable[[Any, Any, Any, Any], Any], Any, GraphQLResolveInfo, str, Any) -> Any + def resolve( + self, + _next: Callable[[Any, Any, Any, Any], Any], + root: Any, + info: GraphQLResolveInfo, + *args: str, + **kwargs: Any, + ) -> Any: if self.should_skip_tracing(_next, info): return _next(root, info, *args, **kwargs) @@ -277,24 +289,26 @@ def resolve(self, _next, root, info, *args, **kwargs): return _next(root, info, *args, **kwargs) -def _patch_views(): - # type: () -> None +def _patch_views() -> None: old_async_view_handle_errors = async_base_view.AsyncBaseHTTPView._handle_errors old_sync_view_handle_errors = sync_base_view.SyncBaseHTTPView._handle_errors - def _sentry_patched_async_view_handle_errors(self, errors, response_data): - # type: (Any, List[GraphQLError], GraphQLHTTPResponse) -> None + def _sentry_patched_async_view_handle_errors( + self: Any, errors: List[GraphQLError], response_data: GraphQLHTTPResponse + ) -> None: old_async_view_handle_errors(self, errors, response_data) _sentry_patched_handle_errors(self, errors, response_data) - def _sentry_patched_sync_view_handle_errors(self, errors, response_data): - # type: (Any, List[GraphQLError], GraphQLHTTPResponse) -> None + def _sentry_patched_sync_view_handle_errors( + self: Any, errors: List[GraphQLError], response_data: GraphQLHTTPResponse + ) -> None: old_sync_view_handle_errors(self, errors, response_data) _sentry_patched_handle_errors(self, errors, response_data) @ensure_integration_enabled(StrawberryIntegration) - def _sentry_patched_handle_errors(self, errors, response_data): - # type: (Any, List[GraphQLError], GraphQLHTTPResponse) -> None + def _sentry_patched_handle_errors( + self: Any, errors: List[GraphQLError], response_data: GraphQLHTTPResponse + ) -> None: if not errors: return @@ -322,18 +336,18 @@ def _sentry_patched_handle_errors(self, errors, response_data): ) -def _make_request_event_processor(execution_context): - # type: (ExecutionContext) -> EventProcessor +def _make_request_event_processor( + execution_context: ExecutionContext, +) -> EventProcessor: - def inner(event, hint): - # type: (Event, dict[str, Any]) -> Event + def inner(event: Event, hint: dict[str, Any]) -> Event: with capture_internal_exceptions(): if should_send_default_pii(): request_data = event.setdefault("request", {}) request_data["api_target"] = "graphql" if not request_data.get("data"): - data = {"query": execution_context.query} # type: dict[str, Any] + data: dict[str, Any] = {"query": execution_context.query} if execution_context.variables: data["variables"] = execution_context.variables if execution_context.operation_name: @@ -352,11 +366,11 @@ def inner(event, hint): return inner -def _make_response_event_processor(response_data): - # type: (GraphQLHTTPResponse) -> EventProcessor +def _make_response_event_processor( + response_data: GraphQLHTTPResponse, +) -> EventProcessor: - def inner(event, hint): - # type: (Event, dict[str, Any]) -> Event + def inner(event: Event, hint: dict[str, Any]) -> Event: with capture_internal_exceptions(): if should_send_default_pii(): contexts = event.setdefault("contexts", {}) @@ -367,8 +381,7 @@ def inner(event, hint): return inner -def _guess_if_using_async(extensions): - # type: (List[SchemaExtension]) -> bool +def _guess_if_using_async(extensions: List[SchemaExtension]) -> bool: return bool( {"starlette", "starlite", "litestar", "fastapi"} & set(_get_installed_modules()) ) diff --git a/sentry_sdk/integrations/sys_exit.py b/sentry_sdk/integrations/sys_exit.py index 2341e11359..ff1a97d5b6 100644 --- a/sentry_sdk/integrations/sys_exit.py +++ b/sentry_sdk/integrations/sys_exit.py @@ -1,3 +1,4 @@ +from __future__ import annotations import functools import sys @@ -24,23 +25,19 @@ class SysExitIntegration(Integration): identifier = "sys_exit" - def __init__(self, *, capture_successful_exits=False): - # type: (bool) -> None + def __init__(self, *, capture_successful_exits: bool = False) -> None: self._capture_successful_exits = capture_successful_exits @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: SysExitIntegration._patch_sys_exit() @staticmethod - def _patch_sys_exit(): - # type: () -> None - old_exit = sys.exit # type: Callable[[Union[str, int, None]], NoReturn] + def _patch_sys_exit() -> None: + old_exit: Callable[[Union[str, int, None]], NoReturn] = sys.exit @functools.wraps(old_exit) - def sentry_patched_exit(__status=0): - # type: (Union[str, int, None]) -> NoReturn + def sentry_patched_exit(__status: Union[str, int, None] = 0) -> NoReturn: # @ensure_integration_enabled ensures that this is non-None integration = sentry_sdk.get_client().get_integration(SysExitIntegration) if integration is None: @@ -60,8 +57,7 @@ def sentry_patched_exit(__status=0): sys.exit = sentry_patched_exit -def _capture_exception(exc): - # type: (SystemExit) -> None +def _capture_exception(exc: SystemExit) -> None: event, hint = event_from_exception( exc, client_options=sentry_sdk.get_client().options, diff --git a/sentry_sdk/integrations/threading.py b/sentry_sdk/integrations/threading.py index 8d0bb69f9d..1f4ea080f6 100644 --- a/sentry_sdk/integrations/threading.py +++ b/sentry_sdk/integrations/threading.py @@ -1,3 +1,4 @@ +from __future__ import annotations import sys import warnings from functools import wraps @@ -28,13 +29,11 @@ class ThreadingIntegration(Integration): identifier = "threading" - def __init__(self, propagate_scope=True): - # type: (bool) -> None + def __init__(self, propagate_scope: bool = True) -> None: self.propagate_scope = propagate_scope @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: old_start = Thread.start try: @@ -47,8 +46,7 @@ def setup_once(): channels_version = None @wraps(old_start) - def sentry_start(self, *a, **kw): - # type: (Thread, *Any, **Any) -> Any + def sentry_start(self: Thread, *a: Any, **kw: Any) -> Any: integration = sentry_sdk.get_client().get_integration(ThreadingIntegration) if integration is None: return old_start(self, *a, **kw) @@ -98,13 +96,14 @@ def sentry_start(self, *a, **kw): Thread.start = sentry_start # type: ignore -def _wrap_run(isolation_scope_to_use, current_scope_to_use, old_run_func): - # type: (sentry_sdk.Scope, sentry_sdk.Scope, F) -> F +def _wrap_run( + isolation_scope_to_use: sentry_sdk.Scope, + current_scope_to_use: sentry_sdk.Scope, + old_run_func: F, +) -> F: @wraps(old_run_func) - def run(*a, **kw): - # type: (*Any, **Any) -> Any - def _run_old_run_func(): - # type: () -> Any + def run(*a: Any, **kw: Any) -> Any: + def _run_old_run_func() -> Any: try: self = current_thread() return old_run_func(self, *a, **kw) @@ -118,8 +117,7 @@ def _run_old_run_func(): return run # type: ignore -def _capture_exception(): - # type: () -> ExcInfo +def _capture_exception() -> ExcInfo: exc_info = sys.exc_info() client = sentry_sdk.get_client() diff --git a/sentry_sdk/integrations/tornado.py b/sentry_sdk/integrations/tornado.py index 07f3e6575c..cb5ceab061 100644 --- a/sentry_sdk/integrations/tornado.py +++ b/sentry_sdk/integrations/tornado.py @@ -1,3 +1,4 @@ +from __future__ import annotations import weakref import contextlib from inspect import iscoroutinefunction @@ -56,8 +57,7 @@ class TornadoIntegration(Integration): origin = f"auto.http.{identifier}" @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: _check_minimum_version(TornadoIntegration, TORNADO_VERSION) if not HAS_REAL_CONTEXTVARS: @@ -77,16 +77,18 @@ def setup_once(): if awaitable: # Starting Tornado 6 RequestHandler._execute method is a standard Python coroutine (async/await) # In that case our method should be a coroutine function too - async def sentry_execute_request_handler(self, *args, **kwargs): - # type: (RequestHandler, *Any, **Any) -> Any + async def sentry_execute_request_handler( + self: RequestHandler, *args: Any, **kwargs: Any + ) -> Any: with _handle_request_impl(self): return await old_execute(self, *args, **kwargs) else: @coroutine # type: ignore - def sentry_execute_request_handler(self, *args, **kwargs): - # type: (RequestHandler, *Any, **Any) -> Any + def sentry_execute_request_handler( + self: RequestHandler, *args: Any, **kwargs: Any + ) -> Any: with _handle_request_impl(self): result = yield from old_execute(self, *args, **kwargs) return result @@ -95,8 +97,14 @@ def sentry_execute_request_handler(self, *args, **kwargs): old_log_exception = RequestHandler.log_exception - def sentry_log_exception(self, ty, value, tb, *args, **kwargs): - # type: (Any, type, BaseException, Any, *Any, **Any) -> Optional[Any] + def sentry_log_exception( + self: Any, + ty: type, + value: BaseException, + tb: Any, + *args: Any, + **kwargs: Any, + ) -> Optional[Any]: _capture_exception(ty, value, tb) return old_log_exception(self, ty, value, tb, *args, **kwargs) @@ -104,8 +112,7 @@ def sentry_log_exception(self, ty, value, tb, *args, **kwargs): @contextlib.contextmanager -def _handle_request_impl(self): - # type: (RequestHandler) -> Generator[None, None, None] +def _handle_request_impl(self: RequestHandler) -> Generator[None, None, None]: integration = sentry_sdk.get_client().get_integration(TornadoIntegration) if integration is None: @@ -136,8 +143,7 @@ def _handle_request_impl(self): @ensure_integration_enabled(TornadoIntegration) -def _capture_exception(ty, value, tb): - # type: (type, BaseException, Any) -> None +def _capture_exception(ty: type, value: BaseException, tb: Any) -> None: if isinstance(value, HTTPError): return @@ -150,10 +156,8 @@ def _capture_exception(ty, value, tb): sentry_sdk.capture_event(event, hint=hint) -def _make_event_processor(weak_handler): - # type: (Callable[[], RequestHandler]) -> EventProcessor - def tornado_processor(event, hint): - # type: (Event, dict[str, Any]) -> Event +def _make_event_processor(weak_handler: Callable[[], RequestHandler]) -> EventProcessor: + def tornado_processor(event: Event, hint: dict[str, Any]) -> Event: handler = weak_handler() if handler is None: return event @@ -192,42 +196,34 @@ def tornado_processor(event, hint): class TornadoRequestExtractor(RequestExtractor): - def content_length(self): - # type: () -> int + def content_length(self) -> int: if self.request.body is None: return 0 return len(self.request.body) - def cookies(self): - # type: () -> Dict[str, str] + def cookies(self) -> Dict[str, str]: return {k: v.value for k, v in self.request.cookies.items()} - def raw_data(self): - # type: () -> bytes + def raw_data(self) -> bytes: return self.request.body - def form(self): - # type: () -> Dict[str, Any] + def form(self) -> Dict[str, Any]: return { k: [v.decode("latin1", "replace") for v in vs] for k, vs in self.request.body_arguments.items() } - def is_json(self): - # type: () -> bool + def is_json(self) -> bool: return _is_json_content_type(self.request.headers.get("content-type")) - def files(self): - # type: () -> Dict[str, Any] + def files(self) -> Dict[str, Any]: return {k: v[0] for k, v in self.request.files.items() if v} - def size_of_file(self, file): - # type: (Any) -> int + def size_of_file(self, file: Any) -> int: return len(file.body or ()) -def _prepopulate_attributes(request): - # type: (HTTPServerRequest) -> dict[str, Any] +def _prepopulate_attributes(request: HTTPServerRequest) -> dict[str, Any]: # https://www.tornadoweb.org/en/stable/httputil.html#tornado.httputil.HTTPServerRequest attributes = {} diff --git a/sentry_sdk/integrations/trytond.py b/sentry_sdk/integrations/trytond.py index fd2c6f389f..91ed51180c 100644 --- a/sentry_sdk/integrations/trytond.py +++ b/sentry_sdk/integrations/trytond.py @@ -1,3 +1,4 @@ +from __future__ import annotations import sentry_sdk from sentry_sdk.integrations import _check_minimum_version, Integration from sentry_sdk.integrations.wsgi import SentryWsgiMiddleware @@ -15,11 +16,11 @@ class TrytondWSGIIntegration(Integration): identifier = "trytond_wsgi" origin = f"auto.http.{identifier}" - def __init__(self): # type: () -> None + def __init__(self) -> None: pass @staticmethod - def setup_once(): # type: () -> None + def setup_once() -> None: _check_minimum_version(TrytondWSGIIntegration, trytond_version) app.wsgi_app = SentryWsgiMiddleware( @@ -28,7 +29,7 @@ def setup_once(): # type: () -> None ) @ensure_integration_enabled(TrytondWSGIIntegration) - def error_handler(e): # type: (Exception) -> None + def error_handler(e: Exception) -> None: if isinstance(e, TrytonException): return else: diff --git a/sentry_sdk/integrations/typer.py b/sentry_sdk/integrations/typer.py index 8879d6d0d0..ab3a22a6ff 100644 --- a/sentry_sdk/integrations/typer.py +++ b/sentry_sdk/integrations/typer.py @@ -1,3 +1,4 @@ +from __future__ import annotations import sentry_sdk from sentry_sdk.utils import ( capture_internal_exceptions, @@ -30,15 +31,16 @@ class TyperIntegration(Integration): identifier = "typer" @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: typer.main.except_hook = _make_excepthook(typer.main.except_hook) # type: ignore -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(TyperIntegration) # Note: If we replace this with ensure_integration_enabled then diff --git a/sentry_sdk/integrations/unleash.py b/sentry_sdk/integrations/unleash.py index 6daa0a411f..6dc63cc5a8 100644 --- a/sentry_sdk/integrations/unleash.py +++ b/sentry_sdk/integrations/unleash.py @@ -1,3 +1,4 @@ +from __future__ import annotations from functools import wraps from typing import Any @@ -14,14 +15,14 @@ class UnleashIntegration(Integration): identifier = "unleash" @staticmethod - def setup_once(): - # type: () -> None + def setup_once() -> None: # Wrap and patch evaluation methods (class methods) old_is_enabled = UnleashClient.is_enabled @wraps(old_is_enabled) - def sentry_is_enabled(self, feature, *args, **kwargs): - # type: (UnleashClient, str, *Any, **Any) -> Any + def sentry_is_enabled( + self: UnleashClient, feature: str, *args: Any, **kwargs: Any + ) -> Any: enabled = old_is_enabled(self, feature, *args, **kwargs) # We have no way of knowing what type of unleash feature this is, so we have to treat diff --git a/sentry_sdk/integrations/wsgi.py b/sentry_sdk/integrations/wsgi.py index 88708d6080..37f6946dd4 100644 --- a/sentry_sdk/integrations/wsgi.py +++ b/sentry_sdk/integrations/wsgi.py @@ -1,3 +1,4 @@ +from __future__ import annotations import sys from functools import partial @@ -25,22 +26,26 @@ from typing import Callable from typing import Dict from typing import Iterator + from typing import Iterable from typing import Any from typing import Tuple + from typing import List from typing import Optional - from typing import TypeVar from typing import Protocol from sentry_sdk.utils import ExcInfo from sentry_sdk._types import Event, EventProcessor - WsgiResponseIter = TypeVar("WsgiResponseIter") - WsgiResponseHeaders = TypeVar("WsgiResponseHeaders") - WsgiExcInfo = TypeVar("WsgiExcInfo") + WsgiResponseIter = Iterable[bytes] + WsgiResponseHeaders = List[Tuple[str, str]] class StartResponse(Protocol): - def __call__(self, status, response_headers, exc_info=None): # type: ignore - # type: (str, WsgiResponseHeaders, Optional[WsgiExcInfo]) -> WsgiResponseIter + def __call__( + self, + status: str, + response_headers: WsgiResponseHeaders, + exc_info: Optional[ExcInfo] = None, + ) -> WsgiResponseIter: pass @@ -58,13 +63,11 @@ def __call__(self, status, response_headers, exc_info=None): # type: ignore } -def wsgi_decoding_dance(s, charset="utf-8", errors="replace"): - # type: (str, str, str) -> str +def wsgi_decoding_dance(s: str, charset: str = "utf-8", errors: str = "replace") -> str: return s.encode("latin1").decode(charset, errors) -def get_request_url(environ, use_x_forwarded_for=False): - # type: (Dict[str, str], bool) -> str +def get_request_url(environ: Dict[str, str], use_x_forwarded_for: bool = False) -> str: """Return the absolute URL without query string for the given WSGI environment.""" script_name = environ.get("SCRIPT_NAME", "").rstrip("/") @@ -88,19 +91,19 @@ class SentryWsgiMiddleware: def __init__( self, - app, # type: Callable[[Dict[str, str], Callable[..., Any]], Any] - use_x_forwarded_for=False, # type: bool - span_origin=None, # type: Optional[str] - http_methods_to_capture=DEFAULT_HTTP_METHODS_TO_CAPTURE, # type: Tuple[str, ...] - ): - # type: (...) -> None + app: Callable[[Dict[str, str], Callable[..., Any]], Any], + use_x_forwarded_for: bool = False, + span_origin: Optional[str] = None, + http_methods_to_capture: Tuple[str, ...] = DEFAULT_HTTP_METHODS_TO_CAPTURE, + ) -> None: self.app = app self.use_x_forwarded_for = use_x_forwarded_for self.span_origin = span_origin self.http_methods_to_capture = http_methods_to_capture - def __call__(self, environ, start_response): - # type: (Dict[str, str], Callable[..., Any]) -> _ScopedResponse + def __call__( + self, environ: Dict[str, str], start_response: Callable[..., Any] + ) -> _ScopedResponse: if _wsgi_middleware_applied.get(False): return self.app(environ, start_response) @@ -144,8 +147,12 @@ def __call__(self, environ, start_response): return _ScopedResponse(scope, response) - def _run_original_app(self, environ, start_response, span): - # type: (dict[str, str], StartResponse, Optional[Span]) -> Any + def _run_original_app( + self, + environ: dict[str, str], + start_response: StartResponse, + span: Optional[Span], + ) -> Any: try: return self.app( environ, @@ -159,14 +166,13 @@ def _run_original_app(self, environ, start_response, span): reraise(*_capture_exception()) -def _sentry_start_response( # type: ignore - old_start_response, # type: StartResponse - span, # type: Optional[Span] - status, # type: str - response_headers, # type: WsgiResponseHeaders - exc_info=None, # type: Optional[WsgiExcInfo] -): - # type: (...) -> WsgiResponseIter +def _sentry_start_response( + old_start_response: StartResponse, + span: Optional[Span], + status: str, + response_headers: WsgiResponseHeaders, + exc_info: Optional[ExcInfo] = None, +) -> WsgiResponseIter: with capture_internal_exceptions(): status_int = int(status.split(" ", 1)[0]) if span is not None: @@ -181,8 +187,7 @@ def _sentry_start_response( # type: ignore return old_start_response(status, response_headers, exc_info) -def _get_environ(environ): - # type: (Dict[str, str]) -> Iterator[Tuple[str, str]] +def _get_environ(environ: Dict[str, str]) -> Iterator[Tuple[str, str]]: """ Returns our explicitly included environment variables we want to capture (server name, port and remote addr if pii is enabled). @@ -198,8 +203,7 @@ def _get_environ(environ): yield key, environ[key] -def get_client_ip(environ): - # type: (Dict[str, str]) -> Optional[Any] +def get_client_ip(environ: Dict[str, str]) -> Optional[Any]: """ Infer the user IP address from various headers. This cannot be used in security sensitive situations since the value may be forged from a client, @@ -218,8 +222,7 @@ def get_client_ip(environ): return environ.get("REMOTE_ADDR") -def _capture_exception(): - # type: () -> ExcInfo +def _capture_exception() -> ExcInfo: """ Captures the current exception and sends it to Sentry. Returns the ExcInfo tuple to it can be reraised afterwards. @@ -253,13 +256,11 @@ class _ScopedResponse: __slots__ = ("_response", "_scope") - def __init__(self, scope, response): - # type: (sentry_sdk.Scope, Iterator[bytes]) -> None + def __init__(self, scope: sentry_sdk.Scope, response: Iterator[bytes]) -> None: self._scope = scope self._response = response - def __iter__(self): - # type: () -> Iterator[bytes] + def __iter__(self) -> Iterator[bytes]: iterator = iter(self._response) while True: @@ -273,8 +274,7 @@ def __iter__(self): yield chunk - def close(self): - # type: () -> None + def close(self) -> None: with sentry_sdk.use_isolation_scope(self._scope): try: self._response.close() # type: ignore @@ -284,8 +284,9 @@ def close(self): reraise(*_capture_exception()) -def _make_wsgi_event_processor(environ, use_x_forwarded_for): - # type: (Dict[str, str], bool) -> EventProcessor +def _make_wsgi_event_processor( + environ: Dict[str, str], use_x_forwarded_for: bool +) -> EventProcessor: # It's a bit unfortunate that we have to extract and parse the request data # from the environ so eagerly, but there are a few good reasons for this. # @@ -305,8 +306,7 @@ def _make_wsgi_event_processor(environ, use_x_forwarded_for): env = dict(_get_environ(environ)) headers = _filter_headers(dict(_get_headers(environ))) - def event_processor(event, hint): - # type: (Event, Dict[str, Any]) -> Event + def event_processor(event: Event, hint: Dict[str, Any]) -> Event: with capture_internal_exceptions(): # if the code below fails halfway through we at least have some data request_info = event.setdefault("request", {}) @@ -327,8 +327,9 @@ def event_processor(event, hint): return event_processor -def _prepopulate_attributes(wsgi_environ, use_x_forwarded_for=False): - # type: (dict[str, str], bool) -> dict[str, str] +def _prepopulate_attributes( + wsgi_environ: dict[str, str], use_x_forwarded_for: bool = False +) -> dict[str, str]: """Extract span attributes from the WSGI environment.""" attributes = {}