saferepr.py 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. # -*- coding: utf-8 -*-
  2. import pprint
  3. from six.moves import reprlib
  4. def _call_and_format_exception(call, x, *args):
  5. try:
  6. # Try the vanilla repr and make sure that the result is a string
  7. return call(x, *args)
  8. except Exception as exc:
  9. exc_name = type(exc).__name__
  10. try:
  11. exc_info = str(exc)
  12. except Exception:
  13. exc_info = "unknown"
  14. return '<[%s("%s") raised in repr()] %s object at 0x%x>' % (
  15. exc_name,
  16. exc_info,
  17. x.__class__.__name__,
  18. id(x),
  19. )
  20. class SafeRepr(reprlib.Repr):
  21. """subclass of repr.Repr that limits the resulting size of repr()
  22. and includes information on exceptions raised during the call.
  23. """
  24. def repr(self, x):
  25. return self._callhelper(reprlib.Repr.repr, self, x)
  26. def repr_unicode(self, x, level):
  27. # Strictly speaking wrong on narrow builds
  28. def repr(u):
  29. if "'" not in u:
  30. return u"'%s'" % u
  31. elif '"' not in u:
  32. return u'"%s"' % u
  33. else:
  34. return u"'%s'" % u.replace("'", r"\'")
  35. s = repr(x[: self.maxstring])
  36. if len(s) > self.maxstring:
  37. i = max(0, (self.maxstring - 3) // 2)
  38. j = max(0, self.maxstring - 3 - i)
  39. s = repr(x[:i] + x[len(x) - j :])
  40. s = s[:i] + "..." + s[len(s) - j :]
  41. return s
  42. def repr_instance(self, x, level):
  43. return self._callhelper(repr, x)
  44. def _callhelper(self, call, x, *args):
  45. s = _call_and_format_exception(call, x, *args)
  46. if len(s) > self.maxsize:
  47. i = max(0, (self.maxsize - 3) // 2)
  48. j = max(0, self.maxsize - 3 - i)
  49. s = s[:i] + "..." + s[len(s) - j :]
  50. return s
  51. def safeformat(obj):
  52. """return a pretty printed string for the given object.
  53. Failing __repr__ functions of user instances will be represented
  54. with a short exception info.
  55. """
  56. return _call_and_format_exception(pprint.pformat, obj)
  57. def saferepr(obj, maxsize=240):
  58. """return a size-limited safe repr-string for the given object.
  59. Failing __repr__ functions of user instances will be represented
  60. with a short exception info and 'saferepr' generally takes
  61. care to never raise exceptions itself. This function is a wrapper
  62. around the Repr/reprlib functionality of the standard 2.6 lib.
  63. """
  64. # review exception handling
  65. srepr = SafeRepr()
  66. srepr.maxstring = maxsize
  67. srepr.maxsize = maxsize
  68. srepr.maxother = 160
  69. return srepr.repr(obj)