saferepr.py 2.4 KB

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