Skip to content

Commit e8f494d

Browse files
extract iscoroutinefunction into common
1 parent e0585e5 commit e8f494d

File tree

7 files changed

+42
-46
lines changed

7 files changed

+42
-46
lines changed

sentry_sdk/integrations/_asgi_common.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import asyncio
2+
import inspect
13
import urllib
24

35
from sentry_sdk.scope import should_send_default_pii
@@ -9,11 +11,30 @@
911
from typing import Any
1012
from typing import Dict
1113
from typing import Optional
14+
from typing import TypeVar
1215
from typing import Union
1316
from typing_extensions import Literal
1417

1518
from sentry_sdk.utils import AnnotatedValue
1619

20+
_F = TypeVar("_F")
21+
22+
23+
# Python 3.12 deprecates asyncio.iscoroutinefunction() as an alias for
24+
# inspect.iscoroutinefunction(), whilst also removing the _is_coroutine marker.
25+
# The latter is replaced with inspect.markcoroutinefunction().
26+
# Until 3.12 is the minimum supported Python version, provide a shim.
27+
# This was copied from https://github.com/django/asgiref/blob/main/asgiref/sync.py
28+
if hasattr(inspect, "markcoroutinefunction"):
29+
_iscoroutinefunction = inspect.iscoroutinefunction
30+
_markcoroutinefunction = inspect.markcoroutinefunction
31+
else:
32+
_iscoroutinefunction = asyncio.iscoroutinefunction # type: ignore[assignment]
33+
34+
def _markcoroutinefunction(func: "_F") -> "_F":
35+
func._is_coroutine = asyncio.coroutines._is_coroutine # type: ignore[attr-defined]
36+
return func
37+
1738

1839
def _get_headers(asgi_scope: "Any") -> "Dict[str, str]":
1940
"""

sentry_sdk/integrations/asgi.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
"""
66

77
import sys
8-
import asyncio
98
import inspect
109
from copy import deepcopy
1110
from functools import partial
@@ -18,6 +17,7 @@
1817
_get_request_attributes,
1918
_get_request_data,
2019
_get_url,
20+
_iscoroutinefunction,
2121
)
2222
from sentry_sdk.integrations._wsgi_common import (
2323
DEFAULT_HTTP_METHODS_TO_CAPTURE,
@@ -87,10 +87,10 @@ def _looks_like_asgi3(app: "Any") -> bool:
8787
if inspect.isclass(app):
8888
return hasattr(app, "__await__")
8989
elif inspect.isfunction(app):
90-
return asyncio.iscoroutinefunction(app)
90+
return _iscoroutinefunction(app)
9191
else:
9292
call = getattr(app, "__call__", None) # noqa
93-
return asyncio.iscoroutinefunction(call)
93+
return _iscoroutinefunction(call)
9494

9595

9696
class SentryAsgiMiddleware:

sentry_sdk/integrations/django/asgi.py

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,18 @@
66
`django.core.handlers.asgi`.
77
"""
88

9-
import asyncio
109
import functools
11-
import inspect
1210

1311
from django.core.handlers.wsgi import WSGIRequest
1412

1513
import sentry_sdk
1614
from sentry_sdk.consts import OP
1715

1816
from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
17+
from sentry_sdk.integrations._asgi_common import (
18+
_iscoroutinefunction,
19+
_markcoroutinefunction,
20+
)
1921
from sentry_sdk.scope import should_send_default_pii
2022
from sentry_sdk.utils import (
2123
capture_internal_exceptions,
@@ -25,31 +27,13 @@
2527
from typing import TYPE_CHECKING
2628

2729
if TYPE_CHECKING:
28-
from typing import Any, Callable, Union, TypeVar
30+
from typing import Any, Callable, Union
2931

3032
from django.core.handlers.asgi import ASGIRequest
3133
from django.http.response import HttpResponse
3234

3335
from sentry_sdk._types import Event, EventProcessor
3436

35-
_F = TypeVar("_F", bound=Callable[..., Any])
36-
37-
38-
# Python 3.12 deprecates asyncio.iscoroutinefunction() as an alias for
39-
# inspect.iscoroutinefunction(), whilst also removing the _is_coroutine marker.
40-
# The latter is replaced with the inspect.markcoroutinefunction decorator.
41-
# Until 3.12 is the minimum supported Python version, provide a shim.
42-
# This was copied from https://github.com/django/asgiref/blob/main/asgiref/sync.py
43-
if hasattr(inspect, "markcoroutinefunction"):
44-
iscoroutinefunction = inspect.iscoroutinefunction
45-
markcoroutinefunction = inspect.markcoroutinefunction
46-
else:
47-
iscoroutinefunction = asyncio.iscoroutinefunction # type: ignore[assignment]
48-
49-
def markcoroutinefunction(func: "_F") -> "_F":
50-
func._is_coroutine = asyncio.coroutines._is_coroutine # type: ignore
51-
return func
52-
5337

5438
def _make_asgi_request_event_processor(request: "ASGIRequest") -> "EventProcessor":
5539
def asgi_request_event_processor(event: "Event", hint: "dict[str, Any]") -> "Event":
@@ -215,15 +199,15 @@ def _async_check(self) -> None:
215199
a thread is not consumed during a whole request.
216200
Taken from django.utils.deprecation::MiddlewareMixin._async_check
217201
"""
218-
if iscoroutinefunction(self.get_response):
219-
markcoroutinefunction(self)
202+
if _iscoroutinefunction(self.get_response):
203+
_markcoroutinefunction(self)
220204

221205
def async_route_check(self) -> bool:
222206
"""
223207
Function that checks if we are in async mode,
224208
and if we are forwards the handling of requests to __acall__
225209
"""
226-
return iscoroutinefunction(self.get_response)
210+
return _iscoroutinefunction(self.get_response)
227211

228212
async def __acall__(self, *args: "Any", **kwargs: "Any") -> "Any":
229213
f = self._acall_method

sentry_sdk/integrations/django/views.py

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,14 @@
22

33
import sentry_sdk
44
from sentry_sdk.consts import OP
5+
from sentry_sdk.integrations._asgi_common import _iscoroutinefunction
56

67
from typing import TYPE_CHECKING
78

89
if TYPE_CHECKING:
910
from typing import Any
1011

1112

12-
try:
13-
from asyncio import iscoroutinefunction
14-
except ImportError:
15-
iscoroutinefunction = None # type: ignore
16-
17-
1813
try:
1914
from sentry_sdk.integrations.django.asgi import wrap_async_view
2015
except (ImportError, SyntaxError):
@@ -48,10 +43,8 @@ def sentry_patched_make_view_atomic(
4843

4944
integration = sentry_sdk.get_client().get_integration(DjangoIntegration)
5045
if integration is not None:
51-
is_async_view = (
52-
iscoroutinefunction is not None
53-
and wrap_async_view is not None
54-
and iscoroutinefunction(callback)
46+
is_async_view = wrap_async_view is not None and _iscoroutinefunction(
47+
callback
5548
)
5649
if is_async_view:
5750
sentry_wrapped_callback = wrap_async_view(callback)

sentry_sdk/integrations/fastapi.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import inspect
21
from copy import deepcopy
32
from functools import wraps
43

54
import sentry_sdk
65
from sentry_sdk.integrations import DidNotEnable
6+
from sentry_sdk.integrations._asgi_common import _iscoroutinefunction
77
from sentry_sdk.scope import should_send_default_pii
88
from sentry_sdk.tracing import SOURCE_FOR_STYLE, TransactionSource
99
from sentry_sdk.utils import transaction_from_function
@@ -73,7 +73,7 @@ def _sentry_get_request_handler(*args: "Any", **kwargs: "Any") -> "Any":
7373
if (
7474
dependant
7575
and dependant.call is not None
76-
and not inspect.iscoroutinefunction(dependant.call)
76+
and not _iscoroutinefunction(dependant.call)
7777
):
7878
old_call = dependant.call
7979

sentry_sdk/integrations/quart.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import asyncio
21
import inspect
32
from functools import wraps
43

54
import sentry_sdk
65
from sentry_sdk.integrations import DidNotEnable, Integration
6+
from sentry_sdk.integrations._asgi_common import _iscoroutinefunction
77
from sentry_sdk.integrations._wsgi_common import _filter_headers
88
from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
99
from sentry_sdk.scope import should_send_default_pii
@@ -106,9 +106,7 @@ def _sentry_route(*args: "Any", **kwargs: "Any") -> "Any":
106106
old_decorator = old_route(*args, **kwargs)
107107

108108
def decorator(old_func: "Any") -> "Any":
109-
if inspect.isfunction(old_func) and not asyncio.iscoroutinefunction(
110-
old_func
111-
):
109+
if inspect.isfunction(old_func) and not _iscoroutinefunction(old_func):
112110

113111
@wraps(old_func)
114112
@ensure_integration_enabled(QuartIntegration, old_func)

sentry_sdk/integrations/starlette.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import inspect
21
import functools
32
import warnings
43
from collections.abc import Set
@@ -12,6 +11,7 @@
1211
Integration,
1312
_DEFAULT_FAILED_REQUEST_STATUS_CODES,
1413
)
14+
from sentry_sdk.integrations._asgi_common import _iscoroutinefunction
1515
from sentry_sdk.integrations._wsgi_common import (
1616
DEFAULT_HTTP_METHODS_TO_CAPTURE,
1717
HttpCodeRangeContainer,
@@ -424,8 +424,8 @@ def _is_async_callable(obj: "Any") -> bool:
424424
while isinstance(obj, functools.partial):
425425
obj = obj.func
426426

427-
return inspect.iscoroutinefunction(obj) or (
428-
callable(obj) and inspect.iscoroutinefunction(obj.__call__)
427+
return _iscoroutinefunction(obj) or (
428+
callable(obj) and _iscoroutinefunction(obj.__call__)
429429
)
430430

431431

0 commit comments

Comments
 (0)