1 new commit in py: https://bitbucket.org/hpk42/py/commits/a890a2fd1e8b/ Changeset: a890a2fd1e8b User: hpk42 Date: 2014-01-22 17:37:22 Summary: fix unicode related issues -- but this changing two things currently. Affected #: 7 files
diff -r 509aef38de37c70f12d1b706f8b69b0e712bbfe2 -r a890a2fd1e8b3004cec17fce5c363241ca1161f7 CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,12 @@ - ignore unicode decode errors in xmlescape. Thanks Anatoly Bubenkoff. +- on python2 modify traceback.format_exception_only to match python3 + behaviour, namely trying to print unicode for Exception instances + +- use a safer way for serializing exception reports (helps to fix + pytest issue413) + Changes between 1.4.18 and 1.4.19 ================================================== diff -r 509aef38de37c70f12d1b706f8b69b0e712bbfe2 -r a890a2fd1e8b3004cec17fce5c363241ca1161f7 py/__init__.py --- a/py/__init__.py +++ b/py/__init__.py @@ -8,7 +8,7 @@ (c) Holger Krekel and others, 2004-2013 """ -__version__ = '1.4.20' +__version__ = '1.4.20.dev2' from py import _apipkg diff -r 509aef38de37c70f12d1b706f8b69b0e712bbfe2 -r a890a2fd1e8b3004cec17fce5c363241ca1161f7 py/_code/code.py --- a/py/_code/code.py +++ b/py/_code/code.py @@ -6,6 +6,35 @@ reprlib = py.builtin._tryimport('repr', 'reprlib') +if sys.version_info[0] >= 3: + from traceback import format_exception_only +else: + import traceback + def format_exception_only(etype, evalue): + """ return list of unicode strings if possible (otherwise bytestrings) + """ + # we patch traceback._some_str to try return unicode to have nicer + # printing of exceptions with unicode attributes in tracebacks. + # Alternative to monkeypatching we would need to copy + # python-2.7's format_exception_only and its induced functions + # -- which seems like overkill. + def somestr(value): + try: + return unicode(value) + except Exception: + try: + return str(value) + except Exception: + pass + return '<unprintable %s object>' % type(value).__name__ + + old = traceback._some_str + traceback._some_str = somestr + try: + return traceback.format_exception_only(etype, evalue) + finally: + traceback._some_str = old + class Code(object): """ wrapper around Python code objects """ def __init__(self, rawcode): @@ -374,7 +403,7 @@ if isinstance(value, AssertionError) and hasattr(value, 'msg'): return ['AssertionError: ' + value.msg] else: - return py.std.traceback.format_exception_only(etype, value) + return format_exception_only(etype, value) def errisinstance(self, exc): """ return True if the exception is an instance of exc """ @@ -594,22 +623,16 @@ return s def __unicode__(self): - l = [] - tw = py.io.TerminalWriter(l.append) + # FYI this is called from pytest-xdist's serialization of exception + # information. + io = py.io.TextIO() + tw = py.io.TerminalWriter(file=io) self.toterminal(tw) - l = map(unicode_or_repr, l) - return "".join(l).strip() + return io.getvalue().strip() def __repr__(self): return "<%s instance at %0x>" %(self.__class__, id(self)) -def unicode_or_repr(obj): - try: - return py.builtin._totext(obj) - except KeyboardInterrupt: - raise - except Exception: - return "<print-error: %r>" % py.io.saferepr(obj) class ReprExceptionInfo(TerminalRepr): def __init__(self, reprtraceback, reprcrash): diff -r 509aef38de37c70f12d1b706f8b69b0e712bbfe2 -r a890a2fd1e8b3004cec17fce5c363241ca1161f7 setup.py --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ name='py', description='library with cross-python path, ini-parsing, io, code, log facilities', long_description = open('README.txt').read(), - version='1.4.20', + version='1.4.20.dev2', url='http://pylib.readthedocs.org/', license='MIT license', platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'], diff -r 509aef38de37c70f12d1b706f8b69b0e712bbfe2 -r a890a2fd1e8b3004cec17fce5c363241ca1161f7 testing/code/test_code.py --- a/testing/code/test_code.py +++ b/testing/code/test_code.py @@ -89,23 +89,6 @@ if sys.version_info[0] < 3: u = unicode(excinfo) -def test_unicode_or_repr(): - from py._code.code import unicode_or_repr - assert unicode_or_repr('hello') == "hello" - if sys.version_info[0] < 3: - s = unicode_or_repr('\xf6\xc4\x85') - else: - s = eval("unicode_or_repr(b'\\f6\\xc4\\x85')") - assert 'print-error' in s - assert 'c4' in s - class A: - def __repr__(self): - raise ValueError() - s = unicode_or_repr(A()) - assert 'print-error' in s - assert 'ValueError' in s - - def test_code_getargs(): def f1(x): pass diff -r 509aef38de37c70f12d1b706f8b69b0e712bbfe2 -r a890a2fd1e8b3004cec17fce5c363241ca1161f7 testing/code/test_excinfo.py --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -727,6 +727,14 @@ assert isinstance(repr, ReprExceptionInfo) assert repr.reprtraceback.style == style + def test_reprexcinfo_unicode(self): + from py._code.code import TerminalRepr + class MyRepr(TerminalRepr): + def toterminal(self, tw): + tw.line(py.builtin._totext("я", "utf-8")) + x = py.builtin._totext(MyRepr()) + assert x == py.builtin._totext("я", "utf-8") + def test_toterminal_long(self, importasmod): mod = importasmod(""" def g(x): diff -r 509aef38de37c70f12d1b706f8b69b0e712bbfe2 -r a890a2fd1e8b3004cec17fce5c363241ca1161f7 testing/io_/test_saferepr.py --- a/testing/io_/test_saferepr.py +++ b/testing/io_/test_saferepr.py @@ -76,18 +76,3 @@ if sys.version_info[0] < 3: u = unicode(excinfo) -def test_unicode_or_repr(): - from py._code.code import unicode_or_repr - assert unicode_or_repr('hello') == "hello" - if sys.version_info[0] < 3: - s = unicode_or_repr('\xf6\xc4\x85') - else: - s = eval("unicode_or_repr(b'\\f6\\xc4\\x85')") - assert 'print-error' in s - assert 'c4' in s - class A: - def __repr__(self): - raise ValueError() - s = unicode_or_repr(A()) - assert 'print-error' in s - assert 'ValueError' in s Repository URL: https://bitbucket.org/hpk42/py/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. _______________________________________________ pytest-commit mailing list pytest-commit@python.org https://mail.python.org/mailman/listinfo/pytest-commit