From 58ac4faf0c6338439f9b8335709a6bc216d7cd1c Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 29 Mar 2017 14:38:14 -0300 Subject: [PATCH] Fix exception formatting while importing test modules Fix #2336 --- CHANGELOG.rst | 7 ++++++- _pytest/compat.py | 2 ++ _pytest/python.py | 4 ++-- testing/python/collect.py | 17 +++++++++++++++++ 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c2e4e9ce70d..78d7501fbb5 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,7 +5,10 @@ than ValueErrors in the ``fileno`` method (`#2276`_). Thanks `@metasyn`_ for the PR. -* +* Fix exception formatting while importing modules when the exception message + contains non-ascii characters (`#2336`_). + Thanks `@fabioz`_ for the report and `@nicoddemus`_ for the PR. + * @@ -14,10 +17,12 @@ * +.. _@fabioz: https://github.com/fabioz .. _@metasyn: https://github.com/metasyn .. _#2276: https://github.com/pytest-dev/pytest/issues/2276 +.. _#2336: https://github.com/pytest-dev/pytest/issues/2336 3.0.7 (2017-03-14) diff --git a/_pytest/compat.py b/_pytest/compat.py index d278b89cd44..cc2954bff6c 100644 --- a/_pytest/compat.py +++ b/_pytest/compat.py @@ -237,5 +237,7 @@ def safe_str(v): try: return str(v) except UnicodeError: + if not isinstance(v, unicode): + v = unicode(v) errors = 'replace' return v.encode('ascii', errors) diff --git a/_pytest/python.py b/_pytest/python.py index 3e865e9df6b..59492bc4192 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -19,7 +19,7 @@ isclass, isfunction, is_generator, _escape_strings, REGEX_TYPE, STRING_TYPES, NoneType, NOTSET, get_real_func, getfslineno, safe_getattr, - getlocation, enum, + safe_str, getlocation, enum, ) cutdir1 = py.path.local(pluggy.__file__.rstrip("oc")) @@ -437,7 +437,7 @@ def _importtestmodule(self): if self.config.getoption('verbose') < 2: exc_info.traceback = exc_info.traceback.filter(filter_traceback) exc_repr = exc_info.getrepr(style='short') if exc_info.traceback else exc_info.exconly() - formatted_tb = py._builtin._totext(exc_repr) + formatted_tb = safe_str(exc_repr) raise self.CollectError( "ImportError while importing test module '{fspath}'.\n" "Hint: make sure your test modules/packages have valid Python names.\n" diff --git a/testing/python/collect.py b/testing/python/collect.py index cce934ddc8d..d0e49083224 100644 --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -105,6 +105,23 @@ def test_show_traceback_import_error(self, testdir, verbose): assert name not in stdout + def test_show_traceback_import_error_unicode(self, testdir): + """Check test modules collected which raise ImportError with unicode messages + are handled properly (#2336). + """ + testdir.makepyfile(u""" + # -*- coding: utf-8 -*- + raise ImportError(u'Something bad happened ☺') + """) + result = testdir.runpytest() + result.stdout.fnmatch_lines([ + "ImportError while importing test module*", + "Traceback:", + "*raise ImportError*Something bad happened*", + ]) + assert result.ret == 2 + + class TestClass: def test_class_with_init_warning(self, testdir): testdir.makepyfile("""