diff --git a/src/_pytest/_io/saferepr.py b/src/_pytest/_io/saferepr.py index 8518290ef..4d1d18d3b 100644 --- a/src/_pytest/_io/saferepr.py +++ b/src/_pytest/_io/saferepr.py @@ -1,14 +1,13 @@ -import py import sys -builtin_repr = repr +from six.moves import reprlib -reprlib = py.builtin._tryimport('repr', 'reprlib') class SafeRepr(reprlib.Repr): - """ subclass of repr.Repr that limits the resulting size of repr() - and includes information on exceptions raised during the call. + """subclass of repr.Repr that limits the resulting size of repr() + and includes information on exceptions raised during the call. """ + def repr(self, x): return self._callhelper(reprlib.Repr.repr, self, x) @@ -16,48 +15,50 @@ class SafeRepr(reprlib.Repr): # Strictly speaking wrong on narrow builds def repr(u): if "'" not in u: - return py.builtin._totext("'%s'") % u + return u"'%s'" % u elif '"' not in u: - return py.builtin._totext('"%s"') % u + return u'"%s"' % u else: - return py.builtin._totext("'%s'") % u.replace("'", r"\'") - s = repr(x[:self.maxstring]) + return u"'%s'" % u.replace("'", r"\'") + + s = repr(x[: self.maxstring]) if len(s) > self.maxstring: - i = max(0, (self.maxstring-3)//2) - j = max(0, self.maxstring-3-i) - s = repr(x[:i] + x[len(x)-j:]) - s = s[:i] + '...' + s[len(s)-j:] + i = max(0, (self.maxstring - 3) // 2) + j = max(0, self.maxstring - 3 - i) + s = repr(x[:i] + x[len(x) - j :]) + s = s[:i] + "..." + s[len(s) - j :] return s def repr_instance(self, x, level): - return self._callhelper(builtin_repr, x) + return self._callhelper(repr, x) def _callhelper(self, call, x, *args): try: # Try the vanilla repr and make sure that the result is a string s = call(x, *args) - except py.builtin._sysex: - raise - except: + except Exception: cls, e, tb = sys.exc_info() - exc_name = getattr(cls, '__name__', 'unknown') + exc_name = getattr(cls, "__name__", "unknown") try: exc_info = str(e) - except py.builtin._sysex: - raise - except: - exc_info = 'unknown' + except Exception: + exc_info = "unknown" return '<[%s("%s") raised in repr()] %s object at 0x%x>' % ( - exc_name, exc_info, x.__class__.__name__, id(x)) + exc_name, + exc_info, + x.__class__.__name__, + id(x), + ) else: if len(s) > self.maxsize: - i = max(0, (self.maxsize-3)//2) - j = max(0, self.maxsize-3-i) - s = s[:i] + '...' + s[len(s)-j:] + i = max(0, (self.maxsize - 3) // 2) + j = max(0, self.maxsize - 3 - i) + s = s[:i] + "..." + s[len(s) - j :] return s + def saferepr(obj, maxsize=240): - """ return a size-limited safe repr-string for the given object. + """return a size-limited safe repr-string for the given object. Failing __repr__ functions of user instances will be represented with a short exception info and 'saferepr' generally takes care to never raise exceptions itself. This function is a wrapper diff --git a/testing/io/test_saferepr.py b/testing/io/test_saferepr.py index 97be1416f..901203088 100644 --- a/testing/io/test_saferepr.py +++ b/testing/io/test_saferepr.py @@ -1,75 +1,66 @@ # -*- coding: utf-8 -*- +from _pytest._io.saferepr import saferepr -from __future__ import generators -import py -import sys -saferepr = py.io.saferepr +def test_simple_repr(): + assert saferepr(1) == "1" + assert saferepr(None) == "None" -class TestSafeRepr: - def test_simple_repr(self): - assert saferepr(1) == '1' - assert saferepr(None) == 'None' - def test_maxsize(self): - s = saferepr('x'*50, maxsize=25) - assert len(s) == 25 - expected = repr('x'*10 + '...' + 'x'*10) - assert s == expected +def test_maxsize(): + s = saferepr("x" * 50, maxsize=25) + assert len(s) == 25 + expected = repr("x" * 10 + "..." + "x" * 10) + assert s == expected - def test_maxsize_error_on_instance(self): - class A: - def __repr__(self): - raise ValueError('...') - s = saferepr(('*'*50, A()), maxsize=25) - assert len(s) == 25 - assert s[0] == '(' and s[-1] == ')' +def test_maxsize_error_on_instance(): + class A: + def __repr__(): + raise ValueError("...") - def test_exceptions(self): - class BrokenRepr: - def __init__(self, ex): - self.ex = ex - foo = 0 - def __repr__(self): - raise self.ex - class BrokenReprException(Exception): - __str__ = None - __repr__ = None - assert 'Exception' in saferepr(BrokenRepr(Exception("broken"))) - s = saferepr(BrokenReprException("really broken")) - assert 'TypeError' in s - assert 'TypeError' in saferepr(BrokenRepr("string")) + s = saferepr(("*" * 50, A()), maxsize=25) + assert len(s) == 25 + assert s[0] == "(" and s[-1] == ")" - s2 = saferepr(BrokenRepr(BrokenReprException('omg even worse'))) - assert 'NameError' not in s2 - assert 'unknown' in s2 - def test_big_repr(self): - from py._io.saferepr import SafeRepr - assert len(saferepr(range(1000))) <= \ - len('[' + SafeRepr().maxlist * "1000" + ']') +def test_exceptions(): + class BrokenRepr: + def __init__(self, ex): + self.ex = ex - def test_repr_on_newstyle(self): - class Function(object): - def __repr__(self): - return "<%s>" %(self.name) - try: - s = saferepr(Function()) - except Exception: - py.test.fail("saferepr failed for newstyle class") + def __repr__(self): + raise self.ex - def test_unicode(self): - val = py.builtin._totext('£€', 'utf-8') - reprval = py.builtin._totext("'£€'", 'utf-8') - assert saferepr(val) == reprval + class BrokenReprException(Exception): + __str__ = None + __repr__ = None -def test_unicode_handling(): - value = py.builtin._totext('\xc4\x85\xc4\x87\n', 'utf-8').encode('utf8') - def f(): - raise Exception(value) - excinfo = py.test.raises(Exception, f) - s = str(excinfo) - if sys.version_info[0] < 3: - u = unicode(excinfo) + assert "Exception" in saferepr(BrokenRepr(Exception("broken"))) + s = saferepr(BrokenReprException("really broken")) + assert "TypeError" in s + assert "TypeError" in saferepr(BrokenRepr("string")) + s2 = saferepr(BrokenRepr(BrokenReprException("omg even worse"))) + assert "NameError" not in s2 + assert "unknown" in s2 + + +def test_big_repr(): + from _pytest._io.saferepr import SafeRepr + + assert len(saferepr(range(1000))) <= len("[" + SafeRepr().maxlist * "1000" + "]") + + +def test_repr_on_newstyle(): + class Function(object): + def __repr__(self): + return "<%s>" % (self.name) + + assert saferepr(Function()) + + +def test_unicode(): + val = u"£€" + reprval = u"'£€'" + assert saferepr(val) == reprval