Skip to content

Commit 69d65db

Browse files
authored
Treat django.template.context.BasicContext as sequence in serializer (#4621)
closes #4606
1 parent c1c6e0b commit 69d65db

File tree

3 files changed

+44
-2
lines changed

3 files changed

+44
-2
lines changed

sentry_sdk/integrations/django/__init__.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import sentry_sdk
88
from sentry_sdk.consts import OP, SPANDATA
99
from sentry_sdk.scope import add_global_event_processor, should_send_default_pii
10-
from sentry_sdk.serializer import add_global_repr_processor
10+
from sentry_sdk.serializer import add_global_repr_processor, add_repr_sequence_type
1111
from sentry_sdk.tracing import SOURCE_FOR_STYLE, TransactionSource
1212
from sentry_sdk.tracing_utils import add_query_source, record_sql_queries
1313
from sentry_sdk.utils import (
@@ -269,6 +269,7 @@ def _django_queryset_repr(value, hint):
269269
patch_views()
270270
patch_templates()
271271
patch_signals()
272+
add_template_context_repr_sequence()
272273

273274
if patch_caching is not None:
274275
patch_caching()
@@ -745,3 +746,13 @@ def _set_db_data(span, cursor_or_db):
745746
server_socket_address = connection_params.get("unix_socket")
746747
if server_socket_address is not None:
747748
span.set_data(SPANDATA.SERVER_SOCKET_ADDRESS, server_socket_address)
749+
750+
751+
def add_template_context_repr_sequence():
752+
# type: () -> None
753+
try:
754+
from django.template.context import BaseContext
755+
756+
add_repr_sequence_type(BaseContext)
757+
except Exception:
758+
pass

sentry_sdk/serializer.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,14 @@ def add_global_repr_processor(processor):
6363
global_repr_processors.append(processor)
6464

6565

66+
sequence_types = [Sequence, Set] # type: List[type]
67+
68+
69+
def add_repr_sequence_type(ty):
70+
# type: (type) -> None
71+
sequence_types.append(ty)
72+
73+
6674
class Memo:
6775
__slots__ = ("_ids", "_objs")
6876

@@ -332,7 +340,7 @@ def _serialize_node_impl(
332340
return rv_dict
333341

334342
elif not isinstance(obj, serializable_str_types) and isinstance(
335-
obj, (Set, Sequence)
343+
obj, tuple(sequence_types)
336344
):
337345
rv_list = []
338346

tests/integrations/django/test_basic.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@
1010
from werkzeug.test import Client
1111

1212
from django import VERSION as DJANGO_VERSION
13+
1314
from django.contrib.auth.models import User
1415
from django.core.management import execute_from_command_line
1516
from django.db.utils import OperationalError, ProgrammingError, DataError
1617
from django.http.request import RawPostDataException
1718
from django.utils.functional import SimpleLazyObject
19+
from django.template.context import make_context
1820

1921
try:
2022
from django.urls import reverse
@@ -310,6 +312,27 @@ def test_queryset_repr(sentry_init, capture_events):
310312
)
311313

312314

315+
@pytest.mark.forked
316+
@pytest_mark_django_db_decorator()
317+
def test_context_nested_queryset_repr(sentry_init, capture_events):
318+
sentry_init(integrations=[DjangoIntegration()])
319+
events = capture_events()
320+
User.objects.create_user("john", "[email protected]", "johnpassword")
321+
322+
try:
323+
context = make_context({"entries": User.objects.all()}) # noqa
324+
1 / 0
325+
except Exception:
326+
capture_exception()
327+
328+
(event,) = events
329+
330+
(exception,) = event["exception"]["values"]
331+
assert exception["type"] == "ZeroDivisionError"
332+
(frame,) = exception["stacktrace"]["frames"]
333+
assert "<User: " not in frame["vars"]["context"]
334+
335+
313336
def test_custom_error_handler_request_context(sentry_init, client, capture_events):
314337
sentry_init(integrations=[DjangoIntegration()])
315338
events = capture_events()

0 commit comments

Comments
 (0)