Skip to content

Support custom repr() defined in classes inheriting from Mapping #1296

Closed
@vmarkovtsev

Description

@vmarkovtsev

I noticed that if I define a class like this:

from typing import Mapping

class Foo(Mapping):
    def __repr__(self) -> str:
        return "custom repr() to save space in the stack trace parameters list"

then Sentry does not call my custom repr() and serializes the object like a regular dict. That's because how _serialize_node_impl in serializer.py branches:

if obj is None or isinstance(obj, (bool, number_types)):
    ...
elif isinstance(obj, datetime):
    ...
elif isinstance(obj, Mapping):  # <- this is where all classes inherited from Mapping land
    ...
elif not isinstance(obj, serializable_str_types) and isinstance(obj, (Set, Sequence)):
    ...
obj = safe_repr(obj)  # <- I want to flow here

I need this feature much because I deal with huge dict-likes (custom dataclasses with tens of key-values), they don't fully fit in the stack trace parameters list and thus clobber the rest of the values standing after them. My handcrafted __repr__ summarizes them instead of printing all the contents and significantly reduces the envelope size. My current workaround is:

class OverriddenReprMeta(abc.ABCMeta):
    """Metaclass for OverriddenReprMapping to make isinstance() return False on custom repr()-s."""

    def __instancecheck__(self, instance):
        """Override for isinstance(instance, cls)."""
        if type(instance).__repr__ not in (object.__repr__, dict.__repr__):
            return False
        return super().__instancecheck__(instance)


class OverriddenReprMapping(Mapping, metaclass=OverriddenReprMeta):
    """Mapping that fails isinstance() check if the object contains a custom repr()."""


sentry_sdk.serializer.serialize.__globals__["Mapping"] = OverriddenReprMapping

It's a broken ugly hack, of course, but it works really well for my project.

Would you please add custom __repr__ support for classes that inherit from Mapping?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions