diff --git a/sentry_sdk/serializer.py b/sentry_sdk/serializer.py index df6a9053c1..134528cd9a 100644 --- a/sentry_sdk/serializer.py +++ b/sentry_sdk/serializer.py @@ -273,6 +273,8 @@ def _serialize_node_impl( if result is not NotImplemented: return _flatten_annotated(result) + sentry_repr = getattr(type(obj), "__sentry_repr__", None) + if obj is None or isinstance(obj, (bool, number_types)): if should_repr_strings or ( isinstance(obj, float) and (math.isinf(obj) or math.isnan(obj)) @@ -281,8 +283,8 @@ def _serialize_node_impl( else: return obj - elif callable(getattr(obj, "sentry_repr", None)): - return obj.sentry_repr() + elif callable(sentry_repr): + return sentry_repr(obj) elif isinstance(obj, datetime): return ( diff --git a/tests/test_serializer.py b/tests/test_serializer.py index 503bc14fb2..1cc20c4b4a 100644 --- a/tests/test_serializer.py +++ b/tests/test_serializer.py @@ -1,5 +1,4 @@ import sys - import pytest from sentry_sdk.serializer import serialize @@ -68,8 +67,20 @@ def test_serialize_sets(extra_normalizer): def test_serialize_custom_mapping(extra_normalizer): class CustomReprDict(dict): - def sentry_repr(self): + def __sentry_repr__(self): return "custom!" result = extra_normalizer(CustomReprDict(one=1, two=2)) assert result == "custom!" + + +def test_custom_mapping_doesnt_mess_with_mock(extra_normalizer): + """ + Adding the __sentry_repr__ magic method check in the serializer + shouldn't mess with how mock works. This broke some stuff when we added + sentry_repr without the dunders. + """ + mock = pytest.importorskip("unittest.mock") + m = mock.Mock() + extra_normalizer(m) + assert len(m.mock_calls) == 0