prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Django 3.1 async views do not work
  When using sentry versions greater than 0.16.3, (tested on 0.18.0), Django 3.1 aysnc views do not work.
  
  ```
  log.py                     224 ERROR    Internal Server Error: /async_ok
  Traceback (most recent call last):
    File "/Users/williamchu/dev/sentry-python/.tox/py3.8-django-3.1/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
      response = get_response(request)
    File "/Users/williamchu/dev/sentry-python/.tox/py3.8-django-3.1/lib/python3.8/site-packages/django/core/handlers/base.py", line 186, in _get_response
      self.check_response(response, callback)
    File "/Users/williamchu/dev/sentry-python/.tox/py3.8-django-3.1/lib/python3.8/site-packages/django/core/handlers/base.py", line 312, in check_response
      raise ValueError(
  ValueError: The view tests.integrations.django.myapp.views.async_ok didn't return an HttpResponse object. It returned an unawaited coroutine instead. You may need to add an 'await' into your view.
  ```
  
  I have made a branch with a test case to demonstrate this: https://github.com/uptickmetachu/sentry-python/tree/django3.1-test-async-view
  
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `sentry_sdk/integrations/django/views.py`
  Content:
  ```
  1 from sentry_sdk.hub import Hub
  2 from sentry_sdk._types import MYPY
  3 from sentry_sdk import _functools
  4 
  5 if MYPY:
  6     from typing import Any
  7 
  8 
  9 def patch_views():
  10     # type: () -> None
  11 
  12     from django.core.handlers.base import BaseHandler
  13     from sentry_sdk.integrations.django import DjangoIntegration
  14 
  15     old_make_view_atomic = BaseHandler.make_view_atomic
  16 
  17     @_functools.wraps(old_make_view_atomic)
  18     def sentry_patched_make_view_atomic(self, *args, **kwargs):
  19         # type: (Any, *Any, **Any) -> Any
  20         callback = old_make_view_atomic(self, *args, **kwargs)
  21 
  22         # XXX: The wrapper function is created for every request. Find more
  23         # efficient way to wrap views (or build a cache?)
  24 
  25         hub = Hub.current
  26         integration = hub.get_integration(DjangoIntegration)
  27 
  28         if integration is not None and integration.middleware_spans:
  29 
  30             @_functools.wraps(callback)
  31             def sentry_wrapped_callback(request, *args, **kwargs):
  32                 # type: (Any, *Any, **Any) -> Any
  33                 with hub.start_span(
  34                     op="django.view", description=request.resolver_match.view_name
  35                 ):
  36                     return callback(request, *args, **kwargs)
  37 
  38         else:
  39             sentry_wrapped_callback = callback
  40 
  41         return sentry_wrapped_callback
  42 
  43     BaseHandler.make_view_atomic = sentry_patched_make_view_atomic
  44
  ```
  
  Path: `sentry_sdk/integrations/django/asgi.py`
  Content:
  ```
  1 """
  2 Instrumentation for Django 3.0
  3 
  4 Since this file contains `async def` it is conditionally imported in
  5 `sentry_sdk.integrations.django` (depending on the existence of
  6 `django.core.handlers.asgi`.
  7 """
  8 
  9 from sentry_sdk import Hub
  10 from sentry_sdk._types import MYPY
  11 
  12 from sentry_sdk.integrations.django import DjangoIntegration
  13 from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
  14 
  15 if MYPY:
  16     from typing import Any
  17     from typing import Union
  18 
  19     from django.http.response import HttpResponse
  20 
  21 
  22 def patch_django_asgi_handler_impl(cls):
  23     # type: (Any) -> None
  24     old_app = cls.__call__
  25 
  26     async def sentry_patched_asgi_handler(self, scope, receive, send):
  27         # type: (Any, Any, Any, Any) -> Any
  28         if Hub.current.get_integration(DjangoIntegration) is None:
  29             return await old_app(self, scope, receive, send)
  30 
  31         middleware = SentryAsgiMiddleware(
  32             old_app.__get__(self, cls), unsafe_context_data=True
  33         )._run_asgi3
  34         return await middleware(scope, receive, send)
  35 
  36     cls.__call__ = sentry_patched_asgi_handler
  37 
  38 
  39 def patch_get_response_async(cls, _before_get_response):
  40     # type: (Any, Any) -> None
  41     old_get_response_async = cls.get_response_async
  42 
  43     async def sentry_patched_get_response_async(self, request):
  44         # type: (Any, Any) -> Union[HttpResponse, BaseException]
  45         _before_get_response(request)
  46         return await old_get_response_async(self, request)
  47 
  48     cls.get_response_async = sentry_patched_get_response_async
  49 
  50 
  51 def patch_channels_asgi_handler_impl(cls):
  52     # type: (Any) -> None
  53     old_app = cls.__call__
  54 
  55     async def sentry_patched_asgi_handler(self, receive, send):
  56         # type: (Any, Any, Any) -> Any
  57         if Hub.current.get_integration(DjangoIntegration) is None:
  58             return await old_app(self, receive, send)
  59 
  60         middleware = SentryAsgiMiddleware(
  61             lambda _scope: old_app.__get__(self, cls), unsafe_context_data=True
  62         )
  63 
  64         return await middleware(self.scope)(receive, send)
  65 
  66     cls.__call__ = sentry_patched_asgi_handler
  67
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/sentry_sdk/integrations/django/asgi.py b/sentry_sdk/integrations/django/asgi.py
  --- a/sentry_sdk/integrations/django/asgi.py
  +++ b/sentry_sdk/integrations/django/asgi.py
  @@ -6,10 +6,9 @@
   `django.core.handlers.asgi`.
   """
   
  -from sentry_sdk import Hub
  +from sentry_sdk import Hub, _functools
   from sentry_sdk._types import MYPY
   
  -from sentry_sdk.integrations.django import DjangoIntegration
   from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
   
   if MYPY:
  @@ -21,6 +20,9 @@
   
   def patch_django_asgi_handler_impl(cls):
       # type: (Any) -> None
  +
  +    from sentry_sdk.integrations.django import DjangoIntegration
  +
       old_app = cls.__call__
   
       async def sentry_patched_asgi_handler(self, scope, receive, send):
  @@ -50,6 +52,9 @@
   
   def patch_channels_asgi_handler_impl(cls):
       # type: (Any) -> None
  +
  +    from sentry_sdk.integrations.django import DjangoIntegration
  +
       old_app = cls.__call__
   
       async def sentry_patched_asgi_handler(self, receive, send):
  @@ -64,3 +69,17 @@
           return await middleware(self.scope)(receive, send)
   
       cls.__call__ = sentry_patched_asgi_handler
  +
  +
  +def wrap_async_view(hub, callback):
  +    # type: (Hub, Any) -> Any
  +    @_functools.wraps(callback)
  +    async def sentry_wrapped_callback(request, *args, **kwargs):
  +        # type: (Any, *Any, **Any) -> Any
  +
  +        with hub.start_span(
  +            op="django.view", description=request.resolver_match.view_name
  +        ):
  +            return await callback(request, *args, **kwargs)
  +
  +    return sentry_wrapped_callback
  diff --git a/sentry_sdk/integrations/django/views.py b/sentry_sdk/integrations/django/views.py
  --- a/sentry_sdk/integrations/django/views.py
  +++ b/sentry_sdk/integrations/django/views.py
  @@ -6,6 +6,18 @@
       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):
  +    wrap_async_view = None  # type: ignore
  +
  +
   def patch_views():
       # type: () -> None
   
  @@ -27,13 +39,14 @@
   
           if integration is not None and integration.middleware_spans:
   
  -            @_functools.wraps(callback)
  -            def sentry_wrapped_callback(request, *args, **kwargs):
  -                # type: (Any, *Any, **Any) -> Any
  -                with hub.start_span(
  -                    op="django.view", description=request.resolver_match.view_name
  -                ):
  -                    return callback(request, *args, **kwargs)
  +            if (
  +                iscoroutinefunction is not None
  +                and wrap_async_view is not None
  +                and iscoroutinefunction(callback)
  +            ):
  +                sentry_wrapped_callback = wrap_async_view(hub, callback)
  +            else:
  +                sentry_wrapped_callback = _wrap_sync_view(hub, callback)
   
           else:
               sentry_wrapped_callback = callback
  @@ -41,3 +54,16 @@
           return sentry_wrapped_callback
   
       BaseHandler.make_view_atomic = sentry_patched_make_view_atomic
  +
  +
  +def _wrap_sync_view(hub, callback):
  +    # type: (Hub, Any) -> Any
  +    @_functools.wraps(callback)
  +    def sentry_wrapped_callback(request, *args, **kwargs):
  +        # type: (Any, *Any, **Any) -> Any
  +        with hub.start_span(
  +            op="django.view", description=request.resolver_match.view_name
  +        ):
  +            return callback(request, *args, **kwargs)
  +
  +    return sentry_wrapped_callback
  
verification_info: {"golden_diff": "diff --git a/sentry_sdk/integrations/django/asgi.py b/sentry_sdk/integrations/django/asgi.py\n--- a/sentry_sdk/integrations/django/asgi.py\n+++ b/sentry_sdk/integrations/django/asgi.py\n@@ -6,10 +6,9 @@\n `django.core.handlers.asgi`.\n \"\"\"\n \n-from sentry_sdk import Hub\n+from sentry_sdk import Hub, _functools\n from sentry_sdk._types import MYPY\n \n-from sentry_sdk.integrations.django import DjangoIntegration\n from sentry_sdk.integrations.asgi import SentryAsgiMiddleware\n \n if MYPY:\n@@ -21,6 +20,9 @@\n \n def patch_django_asgi_handler_impl(cls):\n     # type: (Any) -> None\n+\n+    from sentry_sdk.integrations.django import DjangoIntegration\n+\n     old_app = cls.__call__\n \n     async def sentry_patched_asgi_handler(self, scope, receive, send):\n@@ -50,6 +52,9 @@\n \n def patch_channels_asgi_handler_impl(cls):\n     # type: (Any) -> None\n+\n+    from sentry_sdk.integrations.django import DjangoIntegration\n+\n     old_app = cls.__call__\n \n     async def sentry_patched_asgi_handler(self, receive, send):\n@@ -64,3 +69,17 @@\n         return await middleware(self.scope)(receive, send)\n \n     cls.__call__ = sentry_patched_asgi_handler\n+\n+\n+def wrap_async_view(hub, callback):\n+    # type: (Hub, Any) -> Any\n+    @_functools.wraps(callback)\n+    async def sentry_wrapped_callback(request, *args, **kwargs):\n+        # type: (Any, *Any, **Any) -> Any\n+\n+        with hub.start_span(\n+            op=\"django.view\", description=request.resolver_match.view_name\n+        ):\n+            return await callback(request, *args, **kwargs)\n+\n+    return sentry_wrapped_callback\ndiff --git a/sentry_sdk/integrations/django/views.py b/sentry_sdk/integrations/django/views.py\n--- a/sentry_sdk/integrations/django/views.py\n+++ b/sentry_sdk/integrations/django/views.py\n@@ -6,6 +6,18 @@\n     from typing import Any\n \n \n+try:\n+    from asyncio import iscoroutinefunction\n+except ImportError:\n+    iscoroutinefunction = None  # type: ignore\n+\n+\n+try:\n+    from sentry_sdk.integrations.django.asgi import wrap_async_view\n+except (ImportError, SyntaxError):\n+    wrap_async_view = None  # type: ignore\n+\n+\n def patch_views():\n     # type: () -> None\n \n@@ -27,13 +39,14 @@\n \n         if integration is not None and integration.middleware_spans:\n \n-            @_functools.wraps(callback)\n-            def sentry_wrapped_callback(request, *args, **kwargs):\n-                # type: (Any, *Any, **Any) -> Any\n-                with hub.start_span(\n-                    op=\"django.view\", description=request.resolver_match.view_name\n-                ):\n-                    return callback(request, *args, **kwargs)\n+            if (\n+                iscoroutinefunction is not None\n+                and wrap_async_view is not None\n+                and iscoroutinefunction(callback)\n+            ):\n+                sentry_wrapped_callback = wrap_async_view(hub, callback)\n+            else:\n+                sentry_wrapped_callback = _wrap_sync_view(hub, callback)\n \n         else:\n             sentry_wrapped_callback = callback\n@@ -41,3 +54,16 @@\n         return sentry_wrapped_callback\n \n     BaseHandler.make_view_atomic = sentry_patched_make_view_atomic\n+\n+\n+def _wrap_sync_view(hub, callback):\n+    # type: (Hub, Any) -> Any\n+    @_functools.wraps(callback)\n+    def sentry_wrapped_callback(request, *args, **kwargs):\n+        # type: (Any, *Any, **Any) -> Any\n+        with hub.start_span(\n+            op=\"django.view\", description=request.resolver_match.view_name\n+        ):\n+            return callback(request, *args, **kwargs)\n+\n+    return sentry_wrapped_callback\n", "issue": "Django 3.1 async views do not work\nWhen using sentry versions greater than 0.16.3, (tested on 0.18.0), Django 3.1 aysnc views do not work.\r\n\r\n```\r\nlog.py                     224 ERROR    Internal Server Error: /async_ok\r\nTraceback (most recent call last):\r\n  File \"/Users/williamchu/dev/sentry-python/.tox/py3.8-django-3.1/lib/python3.8/site-packages/django/core/handlers/exception.py\", line 47, in inner\r\n    response = get_response(request)\r\n  File \"/Users/williamchu/dev/sentry-python/.tox/py3.8-django-3.1/lib/python3.8/site-packages/django/core/handlers/base.py\", line 186, in _get_response\r\n    self.check_response(response, callback)\r\n  File \"/Users/williamchu/dev/sentry-python/.tox/py3.8-django-3.1/lib/python3.8/site-packages/django/core/handlers/base.py\", line 312, in check_response\r\n    raise ValueError(\r\nValueError: The view tests.integrations.django.myapp.views.async_ok didn't return an HttpResponse object. It returned an unawaited coroutine instead. You may need to add an 'await' into your view.\r\n```\r\n\r\nI have made a branch with a test case to demonstrate this: https://github.com/uptickmetachu/sentry-python/tree/django3.1-test-async-view\r\n\r\n\n", "before_files": [{"content": "from sentry_sdk.hub import Hub\nfrom sentry_sdk._types import MYPY\nfrom sentry_sdk import _functools\n\nif MYPY:\n    from typing import Any\n\n\ndef patch_views():\n    # type: () -> None\n\n    from django.core.handlers.base import BaseHandler\n    from sentry_sdk.integrations.django import DjangoIntegration\n\n    old_make_view_atomic = BaseHandler.make_view_atomic\n\n    @_functools.wraps(old_make_view_atomic)\n    def sentry_patched_make_view_atomic(self, *args, **kwargs):\n        # type: (Any, *Any, **Any) -> Any\n        callback = old_make_view_atomic(self, *args, **kwargs)\n\n        # XXX: The wrapper function is created for every request. Find more\n        # efficient way to wrap views (or build a cache?)\n\n        hub = Hub.current\n        integration = hub.get_integration(DjangoIntegration)\n\n        if integration is not None and integration.middleware_spans:\n\n            @_functools.wraps(callback)\n            def sentry_wrapped_callback(request, *args, **kwargs):\n                # type: (Any, *Any, **Any) -> Any\n                with hub.start_span(\n                    op=\"django.view\", description=request.resolver_match.view_name\n                ):\n                    return callback(request, *args, **kwargs)\n\n        else:\n            sentry_wrapped_callback = callback\n\n        return sentry_wrapped_callback\n\n    BaseHandler.make_view_atomic = sentry_patched_make_view_atomic\n", "path": "sentry_sdk/integrations/django/views.py"}, {"content": "\"\"\"\nInstrumentation for Django 3.0\n\nSince this file contains `async def` it is conditionally imported in\n`sentry_sdk.integrations.django` (depending on the existence of\n`django.core.handlers.asgi`.\n\"\"\"\n\nfrom sentry_sdk import Hub\nfrom sentry_sdk._types import MYPY\n\nfrom sentry_sdk.integrations.django import DjangoIntegration\nfrom sentry_sdk.integrations.asgi import SentryAsgiMiddleware\n\nif MYPY:\n    from typing import Any\n    from typing import Union\n\n    from django.http.response import HttpResponse\n\n\ndef patch_django_asgi_handler_impl(cls):\n    # type: (Any) -> None\n    old_app = cls.__call__\n\n    async def sentry_patched_asgi_handler(self, scope, receive, send):\n        # type: (Any, Any, Any, Any) -> Any\n        if Hub.current.get_integration(DjangoIntegration) is None:\n            return await old_app(self, scope, receive, send)\n\n        middleware = SentryAsgiMiddleware(\n            old_app.__get__(self, cls), unsafe_context_data=True\n        )._run_asgi3\n        return await middleware(scope, receive, send)\n\n    cls.__call__ = sentry_patched_asgi_handler\n\n\ndef patch_get_response_async(cls, _before_get_response):\n    # type: (Any, Any) -> None\n    old_get_response_async = cls.get_response_async\n\n    async def sentry_patched_get_response_async(self, request):\n        # type: (Any, Any) -> Union[HttpResponse, BaseException]\n        _before_get_response(request)\n        return await old_get_response_async(self, request)\n\n    cls.get_response_async = sentry_patched_get_response_async\n\n\ndef patch_channels_asgi_handler_impl(cls):\n    # type: (Any) -> None\n    old_app = cls.__call__\n\n    async def sentry_patched_asgi_handler(self, receive, send):\n        # type: (Any, Any, Any) -> Any\n        if Hub.current.get_integration(DjangoIntegration) is None:\n            return await old_app(self, receive, send)\n\n        middleware = SentryAsgiMiddleware(\n            lambda _scope: old_app.__get__(self, cls), unsafe_context_data=True\n        )\n\n        return await middleware(self.scope)(receive, send)\n\n    cls.__call__ = sentry_patched_asgi_handler\n", "path": "sentry_sdk/integrations/django/asgi.py"}], "after_files": [{"content": "from sentry_sdk.hub import Hub\nfrom sentry_sdk._types import MYPY\nfrom sentry_sdk import _functools\n\nif MYPY:\n    from typing import Any\n\n\ntry:\n    from asyncio import iscoroutinefunction\nexcept ImportError:\n    iscoroutinefunction = None  # type: ignore\n\n\ntry:\n    from sentry_sdk.integrations.django.asgi import wrap_async_view\nexcept (ImportError, SyntaxError):\n    wrap_async_view = None  # type: ignore\n\n\ndef patch_views():\n    # type: () -> None\n\n    from django.core.handlers.base import BaseHandler\n    from sentry_sdk.integrations.django import DjangoIntegration\n\n    old_make_view_atomic = BaseHandler.make_view_atomic\n\n    @_functools.wraps(old_make_view_atomic)\n    def sentry_patched_make_view_atomic(self, *args, **kwargs):\n        # type: (Any, *Any, **Any) -> Any\n        callback = old_make_view_atomic(self, *args, **kwargs)\n\n        # XXX: The wrapper function is created for every request. Find more\n        # efficient way to wrap views (or build a cache?)\n\n        hub = Hub.current\n        integration = hub.get_integration(DjangoIntegration)\n\n        if integration is not None and integration.middleware_spans:\n\n            if (\n                iscoroutinefunction is not None\n                and wrap_async_view is not None\n                and iscoroutinefunction(callback)\n            ):\n                sentry_wrapped_callback = wrap_async_view(hub, callback)\n            else:\n                sentry_wrapped_callback = _wrap_sync_view(hub, callback)\n\n        else:\n            sentry_wrapped_callback = callback\n\n        return sentry_wrapped_callback\n\n    BaseHandler.make_view_atomic = sentry_patched_make_view_atomic\n\n\ndef _wrap_sync_view(hub, callback):\n    # type: (Hub, Any) -> Any\n    @_functools.wraps(callback)\n    def sentry_wrapped_callback(request, *args, **kwargs):\n        # type: (Any, *Any, **Any) -> Any\n        with hub.start_span(\n            op=\"django.view\", description=request.resolver_match.view_name\n        ):\n            return callback(request, *args, **kwargs)\n\n    return sentry_wrapped_callback\n", "path": "sentry_sdk/integrations/django/views.py"}, {"content": "\"\"\"\nInstrumentation for Django 3.0\n\nSince this file contains `async def` it is conditionally imported in\n`sentry_sdk.integrations.django` (depending on the existence of\n`django.core.handlers.asgi`.\n\"\"\"\n\nfrom sentry_sdk import Hub, _functools\nfrom sentry_sdk._types import MYPY\n\nfrom sentry_sdk.integrations.asgi import SentryAsgiMiddleware\n\nif MYPY:\n    from typing import Any\n    from typing import Union\n\n    from django.http.response import HttpResponse\n\n\ndef patch_django_asgi_handler_impl(cls):\n    # type: (Any) -> None\n\n    from sentry_sdk.integrations.django import DjangoIntegration\n\n    old_app = cls.__call__\n\n    async def sentry_patched_asgi_handler(self, scope, receive, send):\n        # type: (Any, Any, Any, Any) -> Any\n        if Hub.current.get_integration(DjangoIntegration) is None:\n            return await old_app(self, scope, receive, send)\n\n        middleware = SentryAsgiMiddleware(\n            old_app.__get__(self, cls), unsafe_context_data=True\n        )._run_asgi3\n        return await middleware(scope, receive, send)\n\n    cls.__call__ = sentry_patched_asgi_handler\n\n\ndef patch_get_response_async(cls, _before_get_response):\n    # type: (Any, Any) -> None\n    old_get_response_async = cls.get_response_async\n\n    async def sentry_patched_get_response_async(self, request):\n        # type: (Any, Any) -> Union[HttpResponse, BaseException]\n        _before_get_response(request)\n        return await old_get_response_async(self, request)\n\n    cls.get_response_async = sentry_patched_get_response_async\n\n\ndef patch_channels_asgi_handler_impl(cls):\n    # type: (Any) -> None\n\n    from sentry_sdk.integrations.django import DjangoIntegration\n\n    old_app = cls.__call__\n\n    async def sentry_patched_asgi_handler(self, receive, send):\n        # type: (Any, Any, Any) -> Any\n        if Hub.current.get_integration(DjangoIntegration) is None:\n            return await old_app(self, receive, send)\n\n        middleware = SentryAsgiMiddleware(\n            lambda _scope: old_app.__get__(self, cls), unsafe_context_data=True\n        )\n\n        return await middleware(self.scope)(receive, send)\n\n    cls.__call__ = sentry_patched_asgi_handler\n\n\ndef wrap_async_view(hub, callback):\n    # type: (Hub, Any) -> Any\n    @_functools.wraps(callback)\n    async def sentry_wrapped_callback(request, *args, **kwargs):\n        # type: (Any, *Any, **Any) -> Any\n\n        with hub.start_span(\n            op=\"django.view\", description=request.resolver_match.view_name\n        ):\n            return await callback(request, *args, **kwargs)\n\n    return sentry_wrapped_callback\n", "path": "sentry_sdk/integrations/django/asgi.py"}]}