From e1791a9503470b3d3a62738c3389ef2548866f08 Mon Sep 17 00:00:00 2001 From: Vadim Markovtsev Date: Wed, 12 Jan 2022 15:50:02 +0100 Subject: [PATCH] Do not serialize mappings with custom __repr__ as dict-s Fixes #1296 --- sentry_sdk/serializer.py | 5 ++++- tests/test_client.py | 15 +++++++++++---- tests/test_serializer.py | 9 +++++++++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/sentry_sdk/serializer.py b/sentry_sdk/serializer.py index 4dc4bb5177..63ecb8a3bc 100644 --- a/sentry_sdk/serializer.py +++ b/sentry_sdk/serializer.py @@ -288,7 +288,10 @@ def _serialize_node_impl( else safe_repr(obj) ) - elif isinstance(obj, Mapping): + elif isinstance(obj, Mapping) and type(obj).__repr__ in ( + object.__repr__, + dict.__repr__, + ): # Create temporary copy here to avoid calling too much code that # might mutate our dictionary while we're still iterating over it. obj = dict(iteritems(obj)) diff --git a/tests/test_client.py b/tests/test_client.py index 9137f4115a..c5a990dd65 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -646,7 +646,8 @@ def test_chained_exceptions(sentry_init, capture_events): @pytest.mark.tests_internal_exceptions -def test_broken_mapping(sentry_init, capture_events): +@pytest.mark.parametrize("with_custom_repr", [False, True]) +def test_broken_mapping(sentry_init, capture_events, with_custom_repr): sentry_init() events = capture_events() @@ -660,8 +661,10 @@ def broken(self, *args, **kwargs): __iter__ = broken __len__ = broken - def __repr__(self): - return "broken" + if with_custom_repr: + + def __repr__(self): + return "still works" try: a = C() # noqa @@ -670,9 +673,13 @@ def __repr__(self): capture_exception() (event,) = events + if with_custom_repr: + valid_repr = "still works" + else: + valid_repr = "" assert ( event["exception"]["values"][0]["stacktrace"]["frames"][0]["vars"]["a"] - == "" + == valid_repr ) diff --git a/tests/test_serializer.py b/tests/test_serializer.py index 35cbdfb96b..a46b0df029 100644 --- a/tests/test_serializer.py +++ b/tests/test_serializer.py @@ -64,3 +64,12 @@ def test_bytes_serialization_repr(message_normalizer): def test_serialize_sets(extra_normalizer): result = extra_normalizer({1, 2, 3}) assert result == [1, 2, 3] + + +def test_serialize_custom_mapping(extra_normalizer): + class CustomReprDict(dict): + def __repr__(self): + return "custom!" + + result = extra_normalizer(CustomReprDict(one=1, two=2)) + assert result == "custom!"