Skip to content

Instantly share code, notes, and snippets.

@wshayes
Last active December 2, 2021 18:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save wshayes/ca20d1b4c26a80eadb300c91358a55fe to your computer and use it in GitHub Desktop.
Save wshayes/ca20d1b4c26a80eadb300c91358a55fe to your computer and use it in GitHub Desktop.
[Safe repr] safe recursive repr function #python
# https://blog.ionelmc.ro/2020/01/20/is-there-anything-safe-in-python/
def safe_repr(obj, maxdepth=5):
if not maxdepth:
return '...'
obj_type = type(obj)
obj_type_type = type(obj_type)
newdepth = maxdepth - 1
# only represent exact builtins
# (subclasses can have side-effects due to __class__ being
# a property, __instancecheck__, __subclasscheck__ etc)
if obj_type is dict:
return '{%s}' % ', '.join('%s: %s' % (
safe_repr(k, maxdepth),
safe_repr(v, newdepth)
) for k, v in obj.items())
elif obj_type is list:
return '[%s]' % ', '.join(
safe_repr(i, newdepth) for i in obj
)
elif obj_type is tuple:
return '(%s%s)' % (
', '.join(safe_repr(i, newdepth) for i in obj),
',' if len(obj) == 1 else ''
)
elif obj_type is set:
return '{%s}' % ', '.join(
safe_repr(i, newdepth) for i in obj
)
elif obj_type is frozenset:
return '%s({%s})' % (
obj_type.__name__,
', '.join(safe_repr(i, newdepth) for i in obj)
)
elif obj_type is deque:
return '%s([%s])' % (
obj_type.__name__, ', '.join(safe_repr(i, newdepth) for i in obj)
)
elif obj_type in (Counter, OrderedDict, defaultdict):
return '%s({%s})' % (
obj_type.__name__,
', '.join('%s: %s' % (
safe_repr(k, maxdepth),
safe_repr(v, newdepth)
) for k, v in obj.items())
)
elif obj_type is types.MethodType: # noqa
self = obj.__self__
name = getattr(obj, '__qualname__', None)
if name is None:
name = obj.__name__
return '<%sbound method %s of %s>' % (
'un' if self is None else '',
name,
safe_repr(self, newdepth)
)
elif obj_type_type is type and BaseException in obj_type.__mro__:
return '%s(%s)' % (
obj_type.__name__,
', '.join(safe_repr(i, newdepth) for i in obj.args)
)
elif obj_type_type is type and \
obj_type is not InstanceType and \
obj_type.__module__ in (builtins.__name__, 'io', 'socket', '_socket'):
# hardcoded list of safe things. note that isinstance ain't used
# (and we don't trust subclasses to do the right thing in __repr__)
return repr(obj)
else:
return object.__repr__(obj)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment