We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Make sure everything works with Django-Rest-Framework
We should django-rest-framework's `request.data` instead of trying to extract a structured body ourselves

--- 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/__init__.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 from __future__ import absolute_import
3 
4 import sys
5 import weakref
6 
7 from django import VERSION as DJANGO_VERSION  # type: ignore
8 from django.db.models.query import QuerySet  # type: ignore
9 from django.core import signals  # type: ignore
10 
11 if False:
12     from typing import Any
13     from typing import Dict
14     from typing import Tuple
15     from typing import Union
16     from sentry_sdk.integrations.wsgi import _ScopedResponse
17     from typing import Callable
18     from django.core.handlers.wsgi import WSGIRequest  # type: ignore
19     from django.http.response import HttpResponse  # type: ignore
20     from django.http.request import QueryDict  # type: ignore
21     from django.utils.datastructures import MultiValueDict  # type: ignore
22     from typing import List
23 
24 
25 try:
26     from django.urls import resolve  # type: ignore
27 except ImportError:
28     from django.core.urlresolvers import resolve  # type: ignore
29 
30 from sentry_sdk import Hub
31 from sentry_sdk.hub import _should_send_default_pii
32 from sentry_sdk.scope import add_global_event_processor
33 from sentry_sdk.utils import (
34     add_global_repr_processor,
35     capture_internal_exceptions,
36     event_from_exception,
37     safe_repr,
38     format_and_strip,
39     transaction_from_function,
40     walk_exception_chain,
41 )
42 from sentry_sdk.integrations import Integration
43 from sentry_sdk.integrations.logging import ignore_logger
44 from sentry_sdk.integrations.wsgi import SentryWsgiMiddleware
45 from sentry_sdk.integrations._wsgi_common import RequestExtractor
46 from sentry_sdk.integrations.django.transactions import LEGACY_RESOLVER
47 from sentry_sdk.integrations.django.templates import get_template_frame_from_exception
48 
49 
50 if DJANGO_VERSION < (1, 10):
51 
52     def is_authenticated(request_user):
53         # type: (Any) -> bool
54         return request_user.is_authenticated()
55 
56 
57 else:
58 
59     def is_authenticated(request_user):
60         # type: (Any) -> bool
61         return request_user.is_authenticated
62 
63 
64 class DjangoIntegration(Integration):
65     identifier = "django"
66 
67     transaction_style = None
68 
69     def __init__(self, transaction_style="url"):
70         # type: (str) -> None
71         TRANSACTION_STYLE_VALUES = ("function_name", "url")
72         if transaction_style not in TRANSACTION_STYLE_VALUES:
73             raise ValueError(
74                 "Invalid value for transaction_style: %s (must be in %s)"
75                 % (transaction_style, TRANSACTION_STYLE_VALUES)
76             )
77         self.transaction_style = transaction_style
78 
79     @staticmethod
80     def setup_once():
81         # type: () -> None
82         install_sql_hook()
83         # Patch in our custom middleware.
84 
85         # logs an error for every 500
86         ignore_logger("django.server")
87         ignore_logger("django.request")
88 
89         from django.core.handlers.wsgi import WSGIHandler
90 
91         old_app = WSGIHandler.__call__
92 
93         def sentry_patched_wsgi_handler(self, environ, start_response):
94             # type: (Any, Dict[str, str], Callable) -> _ScopedResponse
95             if Hub.current.get_integration(DjangoIntegration) is None:
96                 return old_app(self, environ, start_response)
97 
98             return SentryWsgiMiddleware(lambda *a, **kw: old_app(self, *a, **kw))(
99                 environ, start_response
100             )
101 
102         WSGIHandler.__call__ = sentry_patched_wsgi_handler
103 
104         # patch get_response, because at that point we have the Django request
105         # object
106         from django.core.handlers.base import BaseHandler  # type: ignore
107 
108         old_get_response = BaseHandler.get_response
109 
110         def sentry_patched_get_response(self, request):
111             # type: (Any, WSGIRequest) -> Union[HttpResponse, BaseException]
112             hub = Hub.current
113             integration = hub.get_integration(DjangoIntegration)
114             if integration is not None:
115                 with hub.configure_scope() as scope:
116                     scope.add_event_processor(
117                         _make_event_processor(weakref.ref(request), integration)
118                     )
119             return old_get_response(self, request)
120 
121         BaseHandler.get_response = sentry_patched_get_response
122 
123         signals.got_request_exception.connect(_got_request_exception)
124 
125         @add_global_event_processor
126         def process_django_templates(event, hint):
127             # type: (Dict[str, Any], Dict[str, Any]) -> Dict[str, Any]
128             exc_info = hint.get("exc_info", None)
129 
130             if exc_info is None:
131                 return event
132 
133             exception = event.get("exception", None)
134 
135             if exception is None:
136                 return event
137 
138             values = exception.get("values", None)
139 
140             if values is None:
141                 return event
142 
143             for exception, (_, exc_value, _) in zip(
144                 values, walk_exception_chain(exc_info)
145             ):
146                 frame = get_template_frame_from_exception(exc_value)
147                 if frame is not None:
148                     frames = exception.get("stacktrace", {}).get("frames", [])
149 
150                     for i in reversed(range(len(frames))):
151                         f = frames[i]
152                         if (
153                             f.get("function") in ("parse", "render")
154                             and f.get("module") == "django.template.base"
155                         ):
156                             i += 1
157                             break
158                     else:
159                         i = len(frames)
160 
161                     frames.insert(i, frame)
162 
163             return event
164 
165         @add_global_repr_processor
166         def _django_queryset_repr(value, hint):
167             if not isinstance(value, QuerySet) or value._result_cache:
168                 return NotImplemented
169 
170             # Do not call Hub.get_integration here. It is intentional that
171             # running under a new hub does not suddenly start executing
172             # querysets. This might be surprising to the user but it's likely
173             # less annoying.
174 
175             return u"<%s from %s at 0x%x>" % (
176                 value.__class__.__name__,
177                 value.__module__,
178                 id(value),
179             )
180 
181 
182 def _make_event_processor(weak_request, integration):
183     # type: (Callable[[], WSGIRequest], DjangoIntegration) -> Callable
184     def event_processor(event, hint):
185         # type: (Dict[str, Any], Dict[str, Any]) -> Dict[str, Any]
186         # if the request is gone we are fine not logging the data from
187         # it.  This might happen if the processor is pushed away to
188         # another thread.
189         request = weak_request()
190         if request is None:
191             return event
192 
193         try:
194             if integration.transaction_style == "function_name":
195                 event["transaction"] = transaction_from_function(
196                     resolve(request.path).func
197                 )
198             elif integration.transaction_style == "url":
199                 event["transaction"] = LEGACY_RESOLVER.resolve(request.path)
200         except Exception:
201             pass
202 
203         with capture_internal_exceptions():
204             DjangoRequestExtractor(request).extract_into_event(event)
205 
206         if _should_send_default_pii():
207             with capture_internal_exceptions():
208                 _set_user_info(request, event)
209 
210         return event
211 
212     return event_processor
213 
214 
215 def _got_request_exception(request=None, **kwargs):
216     # type: (WSGIRequest, **Any) -> None
217     hub = Hub.current
218     integration = hub.get_integration(DjangoIntegration)
219     if integration is not None:
220         event, hint = event_from_exception(
221             sys.exc_info(),
222             client_options=hub.client.options,
223             mechanism={"type": "django", "handled": False},
224         )
225         hub.capture_event(event, hint=hint)
226 
227 
228 class DjangoRequestExtractor(RequestExtractor):
229     def env(self):
230         # type: () -> Dict[str, str]
231         return self.request.META
232 
233     def cookies(self):
234         # type: () -> Dict[str, str]
235         return self.request.COOKIES
236 
237     def raw_data(self):
238         # type: () -> bytes
239         return self.request.body
240 
241     def form(self):
242         # type: () -> QueryDict
243         return self.request.POST
244 
245     def files(self):
246         # type: () -> MultiValueDict
247         return self.request.FILES
248 
249     def size_of_file(self, file):
250         return file.size
251 
252 
253 def _set_user_info(request, event):
254     # type: (WSGIRequest, Dict[str, Any]) -> None
255     user_info = event.setdefault("user", {})
256 
257     user = getattr(request, "user", None)
258 
259     if user is None or not is_authenticated(user):
260         return
261 
262     try:
263         user_info["id"] = str(user.pk)
264     except Exception:
265         pass
266 
267     try:
268         user_info["email"] = user.email
269     except Exception:
270         pass
271 
272     try:
273         user_info["username"] = user.get_username()
274     except Exception:
275         pass
276 
277 
278 class _FormatConverter(object):
279     def __init__(self, param_mapping):
280         # type: (Dict[str, int]) -> None
281 
282         self.param_mapping = param_mapping
283         self.params = []  # type: List[Any]
284 
285     def __getitem__(self, val):
286         # type: (str) -> str
287         self.params.append(self.param_mapping.get(val))
288         return "%s"
289 
290 
291 def format_sql(sql, params):
292     # type: (Any, Any) -> Tuple[str, List[str]]
293     rv = []
294 
295     if isinstance(params, dict):
296         # convert sql with named parameters to sql with unnamed parameters
297         conv = _FormatConverter(params)
298         if params:
299             sql = sql % conv
300             params = conv.params
301         else:
302             params = ()
303 
304     for param in params or ():
305         if param is None:
306             rv.append("NULL")
307         param = safe_repr(param)
308         rv.append(param)
309 
310     return sql, rv
311 
312 
313 def record_sql(sql, params, cursor=None):
314     # type: (Any, Any, Any) -> None
315     hub = Hub.current
316     if hub.get_integration(DjangoIntegration) is None:
317         return
318 
319     with capture_internal_exceptions():
320         if cursor and hasattr(cursor, "mogrify"):  # psycopg2
321             real_sql = cursor.mogrify(sql, params)
322             with capture_internal_exceptions():
323                 if isinstance(real_sql, bytes):
324                     real_sql = real_sql.decode(cursor.connection.encoding)
325         else:
326             real_sql, real_params = format_sql(sql, params)
327 
328             if real_params:
329                 try:
330                     real_sql = format_and_strip(real_sql, real_params)
331                 except Exception:
332                     pass
333         hub.add_breadcrumb(message=real_sql, category="query")
334 
335 
336 def install_sql_hook():
337     # type: () -> None
338     """If installed this causes Django's queries to be captured."""
339     try:
340         from django.db.backends.utils import CursorWrapper  # type: ignore
341     except ImportError:
342         from django.db.backends.util import CursorWrapper  # type: ignore
343 
344     try:
345         real_execute = CursorWrapper.execute
346         real_executemany = CursorWrapper.executemany
347     except AttributeError:
348         # This won't work on Django versions < 1.6
349         return
350 
351     def record_many_sql(sql, param_list, cursor):
352         for params in param_list:
353             record_sql(sql, params, cursor)
354 
355     def execute(self, sql, params=None):
356         try:
357             return real_execute(self, sql, params)
358         finally:
359             record_sql(sql, params, self.cursor)
360 
361     def executemany(self, sql, param_list):
362         try:
363             return real_executemany(self, sql, param_list)
364         finally:
365             record_many_sql(sql, param_list, self.cursor)
366 
367     CursorWrapper.execute = execute
368     CursorWrapper.executemany = executemany
369     ignore_logger("django.db.backends")
370
```
--- 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()

```

diff --git a/sentry_sdk/integrations/django/__init__.py b/sentry_sdk/integrations/django/__init__.py
--- a/sentry_sdk/integrations/django/__init__.py
+++ b/sentry_sdk/integrations/django/__init__.py
@@ -265,6 +265,12 @@
     def size_of_file(self, file):
         return file.size
 
+    def parsed_body(self):
+        try:
+            return self.request.data
+        except AttributeError:
+            return RequestExtractor.parsed_body(self)
+
 
 def _set_user_info(request, event):
     # type: (WSGIRequest, Dict[str, Any]) -> None

{"golden_diff": "diff --git a/sentry_sdk/integrations/django/__init__.py b/sentry_sdk/integrations/django/__init__.py\n--- a/sentry_sdk/integrations/django/__init__.py\n+++ b/sentry_sdk/integrations/django/__init__.py\n@@ -265,6 +265,12 @@\n     def size_of_file(self, file):\n         return file.size\n \n+    def parsed_body(self):\n+        try:\n+            return self.request.data\n+        except AttributeError:\n+            return RequestExtractor.parsed_body(self)\n+\n \n def _set_user_info(request, event):\n     # type: (WSGIRequest, Dict[str, Any]) -> None\n", "issue": "Make sure everything works with Django-Rest-Framework\nWe should django-rest-framework's `request.data` instead of trying to extract a structured body ourselves\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\nfrom __future__ import absolute_import\n\nimport sys\nimport weakref\n\nfrom django import VERSION as DJANGO_VERSION  # type: ignore\nfrom django.db.models.query import QuerySet  # type: ignore\nfrom django.core import signals  # type: ignore\n\nif False:\n    from typing import Any\n    from typing import Dict\n    from typing import Tuple\n    from typing import Union\n    from sentry_sdk.integrations.wsgi import _ScopedResponse\n    from typing import Callable\n    from django.core.handlers.wsgi import WSGIRequest  # type: ignore\n    from django.http.response import HttpResponse  # type: ignore\n    from django.http.request import QueryDict  # type: ignore\n    from django.utils.datastructures import MultiValueDict  # type: ignore\n    from typing import List\n\n\ntry:\n    from django.urls import resolve  # type: ignore\nexcept ImportError:\n    from django.core.urlresolvers import resolve  # type: ignore\n\nfrom sentry_sdk import Hub\nfrom sentry_sdk.hub import _should_send_default_pii\nfrom sentry_sdk.scope import add_global_event_processor\nfrom sentry_sdk.utils import (\n    add_global_repr_processor,\n    capture_internal_exceptions,\n    event_from_exception,\n    safe_repr,\n    format_and_strip,\n    transaction_from_function,\n    walk_exception_chain,\n)\nfrom sentry_sdk.integrations import Integration\nfrom sentry_sdk.integrations.logging import ignore_logger\nfrom sentry_sdk.integrations.wsgi import SentryWsgiMiddleware\nfrom sentry_sdk.integrations._wsgi_common import RequestExtractor\nfrom sentry_sdk.integrations.django.transactions import LEGACY_RESOLVER\nfrom sentry_sdk.integrations.django.templates import get_template_frame_from_exception\n\n\nif DJANGO_VERSION < (1, 10):\n\n    def is_authenticated(request_user):\n        # type: (Any) -> bool\n        return request_user.is_authenticated()\n\n\nelse:\n\n    def is_authenticated(request_user):\n        # type: (Any) -> bool\n        return request_user.is_authenticated\n\n\nclass DjangoIntegration(Integration):\n    identifier = \"django\"\n\n    transaction_style = None\n\n    def __init__(self, transaction_style=\"url\"):\n        # type: (str) -> None\n        TRANSACTION_STYLE_VALUES = (\"function_name\", \"url\")\n        if transaction_style not in TRANSACTION_STYLE_VALUES:\n            raise ValueError(\n                \"Invalid value for transaction_style: %s (must be in %s)\"\n                % (transaction_style, TRANSACTION_STYLE_VALUES)\n            )\n        self.transaction_style = transaction_style\n\n    @staticmethod\n    def setup_once():\n        # type: () -> None\n        install_sql_hook()\n        # Patch in our custom middleware.\n\n        # logs an error for every 500\n        ignore_logger(\"django.server\")\n        ignore_logger(\"django.request\")\n\n        from django.core.handlers.wsgi import WSGIHandler\n\n        old_app = WSGIHandler.__call__\n\n        def sentry_patched_wsgi_handler(self, environ, start_response):\n            # type: (Any, Dict[str, str], Callable) -> _ScopedResponse\n            if Hub.current.get_integration(DjangoIntegration) is None:\n                return old_app(self, environ, start_response)\n\n            return SentryWsgiMiddleware(lambda *a, **kw: old_app(self, *a, **kw))(\n                environ, start_response\n            )\n\n        WSGIHandler.__call__ = sentry_patched_wsgi_handler\n\n        # patch get_response, because at that point we have the Django request\n        # object\n        from django.core.handlers.base import BaseHandler  # type: ignore\n\n        old_get_response = BaseHandler.get_response\n\n        def sentry_patched_get_response(self, request):\n            # type: (Any, WSGIRequest) -> Union[HttpResponse, BaseException]\n            hub = Hub.current\n            integration = hub.get_integration(DjangoIntegration)\n            if integration is not None:\n                with hub.configure_scope() as scope:\n                    scope.add_event_processor(\n                        _make_event_processor(weakref.ref(request), integration)\n                    )\n            return old_get_response(self, request)\n\n        BaseHandler.get_response = sentry_patched_get_response\n\n        signals.got_request_exception.connect(_got_request_exception)\n\n        @add_global_event_processor\n        def process_django_templates(event, hint):\n            # type: (Dict[str, Any], Dict[str, Any]) -> Dict[str, Any]\n            exc_info = hint.get(\"exc_info\", None)\n\n            if exc_info is None:\n                return event\n\n            exception = event.get(\"exception\", None)\n\n            if exception is None:\n                return event\n\n            values = exception.get(\"values\", None)\n\n            if values is None:\n                return event\n\n            for exception, (_, exc_value, _) in zip(\n                values, walk_exception_chain(exc_info)\n            ):\n                frame = get_template_frame_from_exception(exc_value)\n                if frame is not None:\n                    frames = exception.get(\"stacktrace\", {}).get(\"frames\", [])\n\n                    for i in reversed(range(len(frames))):\n                        f = frames[i]\n                        if (\n                            f.get(\"function\") in (\"parse\", \"render\")\n                            and f.get(\"module\") == \"django.template.base\"\n                        ):\n                            i += 1\n                            break\n                    else:\n                        i = len(frames)\n\n                    frames.insert(i, frame)\n\n            return event\n\n        @add_global_repr_processor\n        def _django_queryset_repr(value, hint):\n            if not isinstance(value, QuerySet) or value._result_cache:\n                return NotImplemented\n\n            # Do not call Hub.get_integration here. It is intentional that\n            # running under a new hub does not suddenly start executing\n            # querysets. This might be surprising to the user but it's likely\n            # less annoying.\n\n            return u\"<%s from %s at 0x%x>\" % (\n                value.__class__.__name__,\n                value.__module__,\n                id(value),\n            )\n\n\ndef _make_event_processor(weak_request, integration):\n    # type: (Callable[[], WSGIRequest], DjangoIntegration) -> Callable\n    def event_processor(event, hint):\n        # type: (Dict[str, Any], Dict[str, Any]) -> Dict[str, Any]\n        # if the request is gone we are fine not logging the data from\n        # it.  This might happen if the processor is pushed away to\n        # another thread.\n        request = weak_request()\n        if request is None:\n            return event\n\n        try:\n            if integration.transaction_style == \"function_name\":\n                event[\"transaction\"] = transaction_from_function(\n                    resolve(request.path).func\n                )\n            elif integration.transaction_style == \"url\":\n                event[\"transaction\"] = LEGACY_RESOLVER.resolve(request.path)\n        except Exception:\n            pass\n\n        with capture_internal_exceptions():\n            DjangoRequestExtractor(request).extract_into_event(event)\n\n        if _should_send_default_pii():\n            with capture_internal_exceptions():\n                _set_user_info(request, event)\n\n        return event\n\n    return event_processor\n\n\ndef _got_request_exception(request=None, **kwargs):\n    # type: (WSGIRequest, **Any) -> None\n    hub = Hub.current\n    integration = hub.get_integration(DjangoIntegration)\n    if integration is not None:\n        event, hint = event_from_exception(\n            sys.exc_info(),\n            client_options=hub.client.options,\n            mechanism={\"type\": \"django\", \"handled\": False},\n        )\n        hub.capture_event(event, hint=hint)\n\n\nclass DjangoRequestExtractor(RequestExtractor):\n    def env(self):\n        # type: () -> Dict[str, str]\n        return self.request.META\n\n    def cookies(self):\n        # type: () -> Dict[str, str]\n        return self.request.COOKIES\n\n    def raw_data(self):\n        # type: () -> bytes\n        return self.request.body\n\n    def form(self):\n        # type: () -> QueryDict\n        return self.request.POST\n\n    def files(self):\n        # type: () -> MultiValueDict\n        return self.request.FILES\n\n    def size_of_file(self, file):\n        return file.size\n\n\ndef _set_user_info(request, event):\n    # type: (WSGIRequest, Dict[str, Any]) -> None\n    user_info = event.setdefault(\"user\", {})\n\n    user = getattr(request, \"user\", None)\n\n    if user is None or not is_authenticated(user):\n        return\n\n    try:\n        user_info[\"id\"] = str(user.pk)\n    except Exception:\n        pass\n\n    try:\n        user_info[\"email\"] = user.email\n    except Exception:\n        pass\n\n    try:\n        user_info[\"username\"] = user.get_username()\n    except Exception:\n        pass\n\n\nclass _FormatConverter(object):\n    def __init__(self, param_mapping):\n        # type: (Dict[str, int]) -> None\n\n        self.param_mapping = param_mapping\n        self.params = []  # type: List[Any]\n\n    def __getitem__(self, val):\n        # type: (str) -> str\n        self.params.append(self.param_mapping.get(val))\n        return \"%s\"\n\n\ndef format_sql(sql, params):\n    # type: (Any, Any) -> Tuple[str, List[str]]\n    rv = []\n\n    if isinstance(params, dict):\n        # convert sql with named parameters to sql with unnamed parameters\n        conv = _FormatConverter(params)\n        if params:\n            sql = sql % conv\n            params = conv.params\n        else:\n            params = ()\n\n    for param in params or ():\n        if param is None:\n            rv.append(\"NULL\")\n        param = safe_repr(param)\n        rv.append(param)\n\n    return sql, rv\n\n\ndef record_sql(sql, params, cursor=None):\n    # type: (Any, Any, Any) -> None\n    hub = Hub.current\n    if hub.get_integration(DjangoIntegration) is None:\n        return\n\n    with capture_internal_exceptions():\n        if cursor and hasattr(cursor, \"mogrify\"):  # psycopg2\n            real_sql = cursor.mogrify(sql, params)\n            with capture_internal_exceptions():\n                if isinstance(real_sql, bytes):\n                    real_sql = real_sql.decode(cursor.connection.encoding)\n        else:\n            real_sql, real_params = format_sql(sql, params)\n\n            if real_params:\n                try:\n                    real_sql = format_and_strip(real_sql, real_params)\n                except Exception:\n                    pass\n        hub.add_breadcrumb(message=real_sql, category=\"query\")\n\n\ndef install_sql_hook():\n    # type: () -> None\n    \"\"\"If installed this causes Django's queries to be captured.\"\"\"\n    try:\n        from django.db.backends.utils import CursorWrapper  # type: ignore\n    except ImportError:\n        from django.db.backends.util import CursorWrapper  # type: ignore\n\n    try:\n        real_execute = CursorWrapper.execute\n        real_executemany = CursorWrapper.executemany\n    except AttributeError:\n        # This won't work on Django versions < 1.6\n        return\n\n    def record_many_sql(sql, param_list, cursor):\n        for params in param_list:\n            record_sql(sql, params, cursor)\n\n    def execute(self, sql, params=None):\n        try:\n            return real_execute(self, sql, params)\n        finally:\n            record_sql(sql, params, self.cursor)\n\n    def executemany(self, sql, param_list):\n        try:\n            return real_executemany(self, sql, param_list)\n        finally:\n            record_many_sql(sql, param_list, self.cursor)\n\n    CursorWrapper.execute = execute\n    CursorWrapper.executemany = executemany\n    ignore_logger(\"django.db.backends\")\n", "path": "sentry_sdk/integrations/django/__init__.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\nfrom __future__ import absolute_import\n\nimport sys\nimport weakref\n\nfrom django import VERSION as DJANGO_VERSION  # type: ignore\nfrom django.db.models.query import QuerySet  # type: ignore\nfrom django.core import signals  # type: ignore\n\nif False:\n    from typing import Any\n    from typing import Dict\n    from typing import Tuple\n    from typing import Union\n    from sentry_sdk.integrations.wsgi import _ScopedResponse\n    from typing import Callable\n    from django.core.handlers.wsgi import WSGIRequest  # type: ignore\n    from django.http.response import HttpResponse  # type: ignore\n    from django.http.request import QueryDict  # type: ignore\n    from django.utils.datastructures import MultiValueDict  # type: ignore\n    from typing import List\n\ntry:\n    import psycopg2.sql  # type: ignore\n\n    def sql_to_string(sql):\n        # type: (Any) -> str\n        if isinstance(sql, psycopg2.sql.SQL):\n            return sql.string\n        return sql\n\n\nexcept ImportError:\n\n    def sql_to_string(sql):\n        # type: (Any) -> str\n        return sql\n\n\ntry:\n    from django.urls import resolve  # type: ignore\nexcept ImportError:\n    from django.core.urlresolvers import resolve  # type: ignore\n\nfrom sentry_sdk import Hub\nfrom sentry_sdk.hub import _should_send_default_pii\nfrom sentry_sdk.scope import add_global_event_processor\nfrom sentry_sdk.utils import (\n    add_global_repr_processor,\n    capture_internal_exceptions,\n    event_from_exception,\n    safe_repr,\n    format_and_strip,\n    transaction_from_function,\n    walk_exception_chain,\n)\nfrom sentry_sdk.integrations import Integration\nfrom sentry_sdk.integrations.logging import ignore_logger\nfrom sentry_sdk.integrations.wsgi import SentryWsgiMiddleware\nfrom sentry_sdk.integrations._wsgi_common import RequestExtractor\nfrom sentry_sdk.integrations.django.transactions import LEGACY_RESOLVER\nfrom sentry_sdk.integrations.django.templates import get_template_frame_from_exception\n\n\nif DJANGO_VERSION < (1, 10):\n\n    def is_authenticated(request_user):\n        # type: (Any) -> bool\n        return request_user.is_authenticated()\n\n\nelse:\n\n    def is_authenticated(request_user):\n        # type: (Any) -> bool\n        return request_user.is_authenticated\n\n\nclass DjangoIntegration(Integration):\n    identifier = \"django\"\n\n    transaction_style = None\n\n    def __init__(self, transaction_style=\"url\"):\n        # type: (str) -> None\n        TRANSACTION_STYLE_VALUES = (\"function_name\", \"url\")\n        if transaction_style not in TRANSACTION_STYLE_VALUES:\n            raise ValueError(\n                \"Invalid value for transaction_style: %s (must be in %s)\"\n                % (transaction_style, TRANSACTION_STYLE_VALUES)\n            )\n        self.transaction_style = transaction_style\n\n    @staticmethod\n    def setup_once():\n        # type: () -> None\n        install_sql_hook()\n        # Patch in our custom middleware.\n\n        # logs an error for every 500\n        ignore_logger(\"django.server\")\n        ignore_logger(\"django.request\")\n\n        from django.core.handlers.wsgi import WSGIHandler\n\n        old_app = WSGIHandler.__call__\n\n        def sentry_patched_wsgi_handler(self, environ, start_response):\n            # type: (Any, Dict[str, str], Callable) -> _ScopedResponse\n            if Hub.current.get_integration(DjangoIntegration) is None:\n                return old_app(self, environ, start_response)\n\n            return SentryWsgiMiddleware(lambda *a, **kw: old_app(self, *a, **kw))(\n                environ, start_response\n            )\n\n        WSGIHandler.__call__ = sentry_patched_wsgi_handler\n\n        # patch get_response, because at that point we have the Django request\n        # object\n        from django.core.handlers.base import BaseHandler  # type: ignore\n\n        old_get_response = BaseHandler.get_response\n\n        def sentry_patched_get_response(self, request):\n            # type: (Any, WSGIRequest) -> Union[HttpResponse, BaseException]\n            hub = Hub.current\n            integration = hub.get_integration(DjangoIntegration)\n            if integration is not None:\n                with hub.configure_scope() as scope:\n                    scope.add_event_processor(\n                        _make_event_processor(weakref.ref(request), integration)\n                    )\n            return old_get_response(self, request)\n\n        BaseHandler.get_response = sentry_patched_get_response\n\n        signals.got_request_exception.connect(_got_request_exception)\n\n        @add_global_event_processor\n        def process_django_templates(event, hint):\n            # type: (Dict[str, Any], Dict[str, Any]) -> Dict[str, Any]\n            exc_info = hint.get(\"exc_info\", None)\n\n            if exc_info is None:\n                return event\n\n            exception = event.get(\"exception\", None)\n\n            if exception is None:\n                return event\n\n            values = exception.get(\"values\", None)\n\n            if values is None:\n                return event\n\n            for exception, (_, exc_value, _) in zip(\n                values, walk_exception_chain(exc_info)\n            ):\n                frame = get_template_frame_from_exception(exc_value)\n                if frame is not None:\n                    frames = exception.get(\"stacktrace\", {}).get(\"frames\", [])\n\n                    for i in reversed(range(len(frames))):\n                        f = frames[i]\n                        if (\n                            f.get(\"function\") in (\"parse\", \"render\")\n                            and f.get(\"module\") == \"django.template.base\"\n                        ):\n                            i += 1\n                            break\n                    else:\n                        i = len(frames)\n\n                    frames.insert(i, frame)\n\n            return event\n\n        @add_global_repr_processor\n        def _django_queryset_repr(value, hint):\n            if not isinstance(value, QuerySet) or value._result_cache:\n                return NotImplemented\n\n            # Do not call Hub.get_integration here. It is intentional that\n            # running under a new hub does not suddenly start executing\n            # querysets. This might be surprising to the user but it's likely\n            # less annoying.\n\n            return u\"<%s from %s at 0x%x>\" % (\n                value.__class__.__name__,\n                value.__module__,\n                id(value),\n            )\n\n\ndef _make_event_processor(weak_request, integration):\n    # type: (Callable[[], WSGIRequest], DjangoIntegration) -> Callable\n    def event_processor(event, hint):\n        # type: (Dict[str, Any], Dict[str, Any]) -> Dict[str, Any]\n        # if the request is gone we are fine not logging the data from\n        # it.  This might happen if the processor is pushed away to\n        # another thread.\n        request = weak_request()\n        if request is None:\n            return event\n\n        try:\n            if integration.transaction_style == \"function_name\":\n                event[\"transaction\"] = transaction_from_function(\n                    resolve(request.path).func\n                )\n            elif integration.transaction_style == \"url\":\n                event[\"transaction\"] = LEGACY_RESOLVER.resolve(request.path)\n        except Exception:\n            pass\n\n        with capture_internal_exceptions():\n            DjangoRequestExtractor(request).extract_into_event(event)\n\n        if _should_send_default_pii():\n            with capture_internal_exceptions():\n                _set_user_info(request, event)\n\n        return event\n\n    return event_processor\n\n\ndef _got_request_exception(request=None, **kwargs):\n    # type: (WSGIRequest, **Any) -> None\n    hub = Hub.current\n    integration = hub.get_integration(DjangoIntegration)\n    if integration is not None:\n        event, hint = event_from_exception(\n            sys.exc_info(),\n            client_options=hub.client.options,\n            mechanism={\"type\": \"django\", \"handled\": False},\n        )\n        hub.capture_event(event, hint=hint)\n\n\nclass DjangoRequestExtractor(RequestExtractor):\n    def env(self):\n        # type: () -> Dict[str, str]\n        return self.request.META\n\n    def cookies(self):\n        # type: () -> Dict[str, str]\n        return self.request.COOKIES\n\n    def raw_data(self):\n        # type: () -> bytes\n        return self.request.body\n\n    def form(self):\n        # type: () -> QueryDict\n        return self.request.POST\n\n    def files(self):\n        # type: () -> MultiValueDict\n        return self.request.FILES\n\n    def size_of_file(self, file):\n        return file.size\n\n    def parsed_body(self):\n        try:\n            return self.request.data\n        except AttributeError:\n            return RequestExtractor.parsed_body(self)\n\n\ndef _set_user_info(request, event):\n    # type: (WSGIRequest, Dict[str, Any]) -> None\n    user_info = event.setdefault(\"user\", {})\n\n    user = getattr(request, \"user\", None)\n\n    if user is None or not is_authenticated(user):\n        return\n\n    try:\n        user_info[\"id\"] = str(user.pk)\n    except Exception:\n        pass\n\n    try:\n        user_info[\"email\"] = user.email\n    except Exception:\n        pass\n\n    try:\n        user_info[\"username\"] = user.get_username()\n    except Exception:\n        pass\n\n\nclass _FormatConverter(object):\n    def __init__(self, param_mapping):\n        # type: (Dict[str, int]) -> None\n\n        self.param_mapping = param_mapping\n        self.params = []  # type: List[Any]\n\n    def __getitem__(self, val):\n        # type: (str) -> str\n        self.params.append(self.param_mapping.get(val))\n        return \"%s\"\n\n\ndef format_sql(sql, params):\n    # type: (Any, Any) -> Tuple[str, List[str]]\n    rv = []\n\n    if isinstance(params, dict):\n        # convert sql with named parameters to sql with unnamed parameters\n        conv = _FormatConverter(params)\n        if params:\n            sql = sql % conv\n            params = conv.params\n        else:\n            params = ()\n\n    for param in params or ():\n        if param is None:\n            rv.append(\"NULL\")\n        param = safe_repr(param)\n        rv.append(param)\n\n    return sql, rv\n\n\ndef record_sql(sql, params, cursor=None):\n    # type: (Any, Any, Any) -> None\n    hub = Hub.current\n    if hub.get_integration(DjangoIntegration) is None:\n        return\n\n    with capture_internal_exceptions():\n        if cursor and hasattr(cursor, \"mogrify\"):  # psycopg2\n            real_sql = cursor.mogrify(sql, params)\n            with capture_internal_exceptions():\n                if isinstance(real_sql, bytes):\n                    real_sql = real_sql.decode(cursor.connection.encoding)\n        else:\n            real_sql, real_params = format_sql(sql, params)\n\n            if real_params:\n                try:\n                    real_sql = format_and_strip(real_sql, real_params)\n                except Exception:\n                    pass\n        hub.add_breadcrumb(message=real_sql, category=\"query\")\n\n\ndef install_sql_hook():\n    # type: () -> None\n    \"\"\"If installed this causes Django's queries to be captured.\"\"\"\n    try:\n        from django.db.backends.utils import CursorWrapper  # type: ignore\n    except ImportError:\n        from django.db.backends.util import CursorWrapper  # type: ignore\n\n    try:\n        real_execute = CursorWrapper.execute\n        real_executemany = CursorWrapper.executemany\n    except AttributeError:\n        # This won't work on Django versions < 1.6\n        return\n\n    def record_many_sql(sql, param_list, cursor):\n        for params in param_list:\n            record_sql(sql, params, cursor)\n\n    def execute(self, sql, params=None):\n        try:\n            return real_execute(self, sql, params)\n        finally:\n            record_sql(sql, params, self.cursor)\n\n    def executemany(self, sql, param_list):\n        try:\n            return real_executemany(self, sql, param_list)\n        finally:\n            record_many_sql(sql, param_list, self.cursor)\n\n    CursorWrapper.execute = execute\n    CursorWrapper.executemany = executemany\n    ignore_logger(\"django.db.backends\")\n", "path": "sentry_sdk/integrations/django/__init__.py"}]}