Skip to content
1 change: 1 addition & 0 deletions sentry_sdk/_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
PY38 = sys.version_info[0] == 3 and sys.version_info[1] >= 8
PY310 = sys.version_info[0] == 3 and sys.version_info[1] >= 10
PY311 = sys.version_info[0] == 3 and sys.version_info[1] >= 11
PY313 = sys.version_info[0] == 3 and sys.version_info[1] >= 13


def with_metaclass(meta: "Any", *bases: "Any") -> "Any":
Expand Down
7 changes: 7 additions & 0 deletions sentry_sdk/integrations/_asgi_common.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import asyncio
import inspect
import urllib

from sentry_sdk._compat import PY313
from sentry_sdk.scope import should_send_default_pii
from sentry_sdk.integrations._wsgi_common import _filter_headers

Expand All @@ -14,6 +17,10 @@

from sentry_sdk.utils import AnnotatedValue

_iscoroutinefunction = (
inspect.iscoroutinefunction if PY313 else asyncio.iscoroutinefunction
)


def _get_headers(asgi_scope: "Any") -> "Dict[str, str]":
"""
Expand Down
6 changes: 3 additions & 3 deletions sentry_sdk/integrations/asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
"""

import sys
import asyncio
import inspect
from copy import deepcopy
from functools import partial
Expand All @@ -18,6 +17,7 @@
_get_request_attributes,
_get_request_data,
_get_url,
_iscoroutinefunction,
)
from sentry_sdk.integrations._wsgi_common import (
DEFAULT_HTTP_METHODS_TO_CAPTURE,
Expand Down Expand Up @@ -87,10 +87,10 @@ def _looks_like_asgi3(app: "Any") -> bool:
if inspect.isclass(app):
return hasattr(app, "__await__")
elif inspect.isfunction(app):
return asyncio.iscoroutinefunction(app)
return _iscoroutinefunction(app)
else:
call = getattr(app, "__call__", None) # noqa
return asyncio.iscoroutinefunction(call)
return _iscoroutinefunction(call)


class SentryAsgiMiddleware:
Expand Down
7 changes: 3 additions & 4 deletions sentry_sdk/integrations/django/asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from sentry_sdk.consts import OP

from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
from sentry_sdk.integrations._asgi_common import _iscoroutinefunction
from sentry_sdk.scope import should_send_default_pii
from sentry_sdk.utils import (
capture_internal_exceptions,
Expand All @@ -41,10 +42,8 @@
# Until 3.12 is the minimum supported Python version, provide a shim.
# This was copied from https://github.com/django/asgiref/blob/main/asgiref/sync.py
if hasattr(inspect, "markcoroutinefunction"):
iscoroutinefunction = inspect.iscoroutinefunction
markcoroutinefunction = inspect.markcoroutinefunction
else:
iscoroutinefunction = asyncio.iscoroutinefunction # type: ignore[assignment]

def markcoroutinefunction(func: "_F") -> "_F":
func._is_coroutine = asyncio.coroutines._is_coroutine # type: ignore
Expand Down Expand Up @@ -215,15 +214,15 @@ def _async_check(self) -> None:
a thread is not consumed during a whole request.
Taken from django.utils.deprecation::MiddlewareMixin._async_check
"""
if iscoroutinefunction(self.get_response):
if _iscoroutinefunction(self.get_response):
markcoroutinefunction(self)

def async_route_check(self) -> bool:
"""
Function that checks if we are in async mode,
and if we are forwards the handling of requests to __acall__
"""
return iscoroutinefunction(self.get_response)
return _iscoroutinefunction(self.get_response)

async def __acall__(self, *args: "Any", **kwargs: "Any") -> "Any":
f = self._acall_method
Expand Down
13 changes: 3 additions & 10 deletions sentry_sdk/integrations/django/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,14 @@

import sentry_sdk
from sentry_sdk.consts import OP
from sentry_sdk.integrations._asgi_common import _iscoroutinefunction

from typing import TYPE_CHECKING

if TYPE_CHECKING:
from typing import Any


try:
from asyncio import iscoroutinefunction
except ImportError:
iscoroutinefunction = None # type: ignore


try:
from sentry_sdk.integrations.django.asgi import wrap_async_view
except (ImportError, SyntaxError):
Expand Down Expand Up @@ -48,10 +43,8 @@ def sentry_patched_make_view_atomic(

integration = sentry_sdk.get_client().get_integration(DjangoIntegration)
if integration is not None:
is_async_view = (
iscoroutinefunction is not None
and wrap_async_view is not None
and iscoroutinefunction(callback)
is_async_view = wrap_async_view is not None and _iscoroutinefunction(
callback
)
if is_async_view:
sentry_wrapped_callback = wrap_async_view(callback)
Expand Down
4 changes: 2 additions & 2 deletions sentry_sdk/integrations/fastapi.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import asyncio
from copy import deepcopy
from functools import wraps

import sentry_sdk
from sentry_sdk.integrations import DidNotEnable
from sentry_sdk.integrations._asgi_common import _iscoroutinefunction
from sentry_sdk.scope import should_send_default_pii
from sentry_sdk.traces import NoOpStreamedSpan, StreamedSpan
from sentry_sdk.tracing import SOURCE_FOR_STYLE, TransactionSource
Expand Down Expand Up @@ -74,7 +74,7 @@ def _sentry_get_request_handler(*args: "Any", **kwargs: "Any") -> "Any":
if (
dependant
and dependant.call is not None
and not asyncio.iscoroutinefunction(dependant.call)
and not _iscoroutinefunction(dependant.call)
):
old_call = dependant.call

Expand Down
6 changes: 2 additions & 4 deletions sentry_sdk/integrations/quart.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import asyncio
import inspect
from functools import wraps

import sentry_sdk
from sentry_sdk.integrations import DidNotEnable, Integration
from sentry_sdk.integrations._asgi_common import _iscoroutinefunction
from sentry_sdk.integrations._wsgi_common import _filter_headers
from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
from sentry_sdk.scope import should_send_default_pii
Expand Down Expand Up @@ -106,9 +106,7 @@ def _sentry_route(*args: "Any", **kwargs: "Any") -> "Any":
old_decorator = old_route(*args, **kwargs)

def decorator(old_func: "Any") -> "Any":
if inspect.isfunction(old_func) and not asyncio.iscoroutinefunction(
old_func
):
if inspect.isfunction(old_func) and not _iscoroutinefunction(old_func):

@wraps(old_func)
@ensure_integration_enabled(QuartIntegration, old_func)
Expand Down
6 changes: 3 additions & 3 deletions sentry_sdk/integrations/starlette.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import asyncio
import functools
import warnings
from collections.abc import Set
Expand All @@ -12,6 +11,7 @@
Integration,
_DEFAULT_FAILED_REQUEST_STATUS_CODES,
)
from sentry_sdk.integrations._asgi_common import _iscoroutinefunction
from sentry_sdk.integrations._wsgi_common import (
DEFAULT_HTTP_METHODS_TO_CAPTURE,
HttpCodeRangeContainer,
Expand Down Expand Up @@ -424,8 +424,8 @@ def _is_async_callable(obj: "Any") -> bool:
while isinstance(obj, functools.partial):
obj = obj.func

return asyncio.iscoroutinefunction(obj) or (
callable(obj) and asyncio.iscoroutinefunction(obj.__call__)
return _iscoroutinefunction(obj) or (
callable(obj) and _iscoroutinefunction(obj.__call__)
)


Expand Down