Skip to content

Commit

Permalink
Merge branch 'master' into langchain-2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
antonpirker authored Apr 30, 2024
2 parents 1643bdb + fb1b746 commit b74e52f
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 27 deletions.
2 changes: 1 addition & 1 deletion checkouts/data-schemas
2 changes: 1 addition & 1 deletion scripts/runtox.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,4 @@ if [ -z "${ENV}" ]; then
exit 0
fi

exec $TOXPATH -e "$ENV" -- "${@:2}"
exec $TOXPATH -p auto -o -e "$ENV" -- "${@:2}"
28 changes: 23 additions & 5 deletions sentry_sdk/integrations/django/asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import asyncio
import functools
import inspect

from django.core.handlers.wsgi import WSGIRequest

Expand All @@ -25,14 +26,31 @@


if TYPE_CHECKING:
from collections.abc import Callable
from typing import Any, Union
from typing import Any, Callable, Union, TypeVar

from django.core.handlers.asgi import ASGIRequest
from django.http.response import HttpResponse

from sentry_sdk._types import Event, EventProcessor

_F = TypeVar("_F", bound=Callable[..., Any])


# Python 3.12 deprecates asyncio.iscoroutinefunction() as an alias for
# inspect.iscoroutinefunction(), whilst also removing the _is_coroutine marker.
# The latter is replaced with the inspect.markcoroutinefunction decorator.
# 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
return func


def _make_asgi_request_event_processor(request):
# type: (ASGIRequest) -> EventProcessor
Expand Down Expand Up @@ -181,16 +199,16 @@ def _async_check(self):
a thread is not consumed during a whole request.
Taken from django.utils.deprecation::MiddlewareMixin._async_check
"""
if asyncio.iscoroutinefunction(self.get_response):
self._is_coroutine = asyncio.coroutines._is_coroutine # type: ignore
if iscoroutinefunction(self.get_response):
markcoroutinefunction(self)

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

async def __acall__(self, *args, **kwargs):
# type: (*Any, **Any) -> Any
Expand Down
66 changes: 66 additions & 0 deletions tests/integrations/django/asgi/test_asgi.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import base64
import sys
import json
import inspect
import asyncio
import os
from unittest import mock

Expand All @@ -8,6 +11,7 @@
from channels.testing import HttpCommunicator
from sentry_sdk import capture_message
from sentry_sdk.integrations.django import DjangoIntegration
from sentry_sdk.integrations.django.asgi import _asgi_middleware_mixin_factory
from tests.integrations.django.myapp.asgi import channels_application

try:
Expand Down Expand Up @@ -526,3 +530,65 @@ async def test_asgi_request_body(
assert event["request"]["data"] == expected_data
else:
assert "data" not in event["request"]


@pytest.mark.asyncio
@pytest.mark.skipif(
sys.version_info >= (3, 12),
reason=(
"asyncio.iscoroutinefunction has been replaced in 3.12 by inspect.iscoroutinefunction"
),
)
async def test_asgi_mixin_iscoroutinefunction_before_3_12():
sentry_asgi_mixin = _asgi_middleware_mixin_factory(lambda: None)

async def get_response(): ...

instance = sentry_asgi_mixin(get_response)
assert asyncio.iscoroutinefunction(instance)


@pytest.mark.skipif(
sys.version_info >= (3, 12),
reason=(
"asyncio.iscoroutinefunction has been replaced in 3.12 by inspect.iscoroutinefunction"
),
)
def test_asgi_mixin_iscoroutinefunction_when_not_async_before_3_12():
sentry_asgi_mixin = _asgi_middleware_mixin_factory(lambda: None)

def get_response(): ...

instance = sentry_asgi_mixin(get_response)
assert not asyncio.iscoroutinefunction(instance)


@pytest.mark.asyncio
@pytest.mark.skipif(
sys.version_info < (3, 12),
reason=(
"asyncio.iscoroutinefunction has been replaced in 3.12 by inspect.iscoroutinefunction"
),
)
async def test_asgi_mixin_iscoroutinefunction_after_3_12():
sentry_asgi_mixin = _asgi_middleware_mixin_factory(lambda: None)

async def get_response(): ...

instance = sentry_asgi_mixin(get_response)
assert inspect.iscoroutinefunction(instance)


@pytest.mark.skipif(
sys.version_info < (3, 12),
reason=(
"asyncio.iscoroutinefunction has been replaced in 3.12 by inspect.iscoroutinefunction"
),
)
def test_asgi_mixin_iscoroutinefunction_when_not_async_after_3_12():
sentry_asgi_mixin = _asgi_middleware_mixin_factory(lambda: None)

def get_response(): ...

instance = sentry_asgi_mixin(get_response)
assert not inspect.iscoroutinefunction(instance)
6 changes: 4 additions & 2 deletions tests/integrations/trytond/test_trytond.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
from trytond.wsgi import app as trytond_app

from werkzeug.test import Client

from sentry_sdk.integrations.trytond import TrytondWSGIIntegration
from tests.conftest import unpack_werkzeug_response


@pytest.fixture(scope="function")
Expand Down Expand Up @@ -118,8 +120,8 @@ def _(app, request, e):
"/rpcerror", content_type="application/json", data=json.dumps(_data)
)

(content, status, headers) = response
data = json.loads(next(content))
(content, status, headers) = unpack_werkzeug_response(response)
data = json.loads(content)
assert status == "200 OK"
assert headers.get("Content-Type") == "application/json"
assert data == dict(id=42, error=["UserError", ["Sentry error.", "foo", None]])
35 changes: 17 additions & 18 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ deps =

# === Common ===
py3.8-common: hypothesis
{py3.6,py3.7,py3.8,py3.9,py3.10,py3.11,py3.12}-common: pytest-asyncio<=0.21.1
{py3.6,py3.7,py3.8,py3.9,py3.10,py3.11,py3.12}-common: pytest-asyncio
# See https://github.com/pytest-dev/pytest/issues/9621
# and https://github.com/pytest-dev/pytest-forked/issues/67
# for justification of the upper bound on pytest
Expand All @@ -268,8 +268,8 @@ deps =
aiohttp-v3.8: aiohttp~=3.8.0
aiohttp-latest: aiohttp
aiohttp: pytest-aiohttp
aiohttp-v3.8: pytest-asyncio<=0.21.1
aiohttp-latest: pytest-asyncio<=0.21.1
aiohttp-v3.8: pytest-asyncio
aiohttp-latest: pytest-asyncio

# Ariadne
ariadne-v0.20: ariadne~=0.20.0
Expand All @@ -283,17 +283,17 @@ deps =
arq-v0.23: pydantic<2
arq-latest: arq
arq: fakeredis>=2.2.0,<2.8
arq: pytest-asyncio<=0.21.1
arq: pytest-asyncio
arq: async-timeout

# Asgi
asgi: pytest-asyncio<=0.21.1
asgi: pytest-asyncio
asgi: async-asgi-testclient

# Asyncpg
asyncpg-v0.23: asyncpg~=0.23.0
asyncpg-latest: asyncpg
asyncpg: pytest-asyncio<=0.21.1
asyncpg: pytest-asyncio

# AWS Lambda
aws_lambda: boto3
Expand Down Expand Up @@ -345,10 +345,10 @@ deps =
django-v{1.11,2.0,2.2,3.0}: pytest-django<4.0
django-v{3.2,4.0,4.1,4.2,5.0}: pytest-django
django-v{4.0,4.1,4.2,5.0}: djangorestframework
django-v{4.0,4.1,4.2,5.0}: pytest-asyncio<=0.21.1
django-v{4.0,4.1,4.2,5.0}: pytest-asyncio
django-v{4.0,4.1,4.2,5.0}: Werkzeug
django-latest: djangorestframework
django-latest: pytest-asyncio<=0.21.1
django-latest: pytest-asyncio
django-latest: pytest-django
django-latest: Werkzeug
django-latest: channels[daphne]
Expand All @@ -375,7 +375,7 @@ deps =
fastapi: httpx
# (this is a dependency of httpx)
fastapi: anyio<4.0.0
fastapi: pytest-asyncio<=0.21.1
fastapi: pytest-asyncio
fastapi: python-multipart
fastapi: requests
fastapi-v{0.79}: fastapi~=0.79.0
Expand Down Expand Up @@ -407,7 +407,7 @@ deps =
grpc: protobuf
grpc: mypy-protobuf
grpc: types-protobuf
grpc: pytest-asyncio<=0.21.1
grpc: pytest-asyncio
grpc-v1.39: grpcio~=1.39.0
grpc-v1.49: grpcio~=1.49.1
grpc-v1.59: grpcio~=1.59.0
Expand Down Expand Up @@ -480,7 +480,7 @@ deps =

# Quart
quart: quart-auth
quart: pytest-asyncio<=0.21.1
quart: pytest-asyncio
quart-v0.16: blinker<1.6
quart-v0.16: jinja2<3.1.0
quart-v0.16: Werkzeug<2.1.0
Expand All @@ -493,7 +493,7 @@ deps =
# Redis
redis: fakeredis!=1.7.4
redis: pytest<8.0.0
{py3.7,py3.8,py3.9,py3.10,py3.11}-redis: pytest-asyncio<=0.21.1
{py3.7,py3.8,py3.9,py3.10,py3.11}-redis: pytest-asyncio
redis-v3: redis~=3.0
redis-v4: redis~=4.0
redis-v5: redis~=5.0
Expand Down Expand Up @@ -534,7 +534,7 @@ deps =
sanic-latest: sanic

# Starlette
starlette: pytest-asyncio<=0.21.1
starlette: pytest-asyncio
starlette: python-multipart
starlette: requests
starlette: httpx
Expand All @@ -549,7 +549,7 @@ deps =
starlette-latest: starlette

# Starlite
starlite: pytest-asyncio<=0.21.1
starlite: pytest-asyncio
starlite: python-multipart
starlite: requests
starlite: cryptography
Expand All @@ -571,21 +571,20 @@ deps =
strawberry-latest: strawberry-graphql[fastapi,flask]

# Tornado
tornado: pytest<8.2
tornado-v6.0: tornado~=6.0.0
tornado-v6: tornado~=6.0
tornado-latest: tornado

# Trytond
trytond: werkzeug
trytond-v4: werkzeug<1.0
trytond-v4: trytond~=4.0
trytond-v5: trytond~=5.0
trytond-v6: trytond~=6.0
trytond-v7: trytond~=7.0
trytond-latest: trytond

trytond-v{4}: werkzeug<1.0
trytond-v{5,6,7}: werkzeug<2.0
trytond-latest: werkzeug<2.0

setenv =
PYTHONDONTWRITEBYTECODE=1
OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
Expand Down

0 comments on commit b74e52f

Please sign in to comment.