From 227d847216a5c05cd5fd909574435985794ffb8e Mon Sep 17 00:00:00 2001 From: holger krekel Date: Sun, 24 Jun 2012 16:42:31 +0200 Subject: [PATCH] fix problem with unicode in writing failure representations to terminal, thanks ThomasWaldmann --- CHANGELOG | 4 +++- _pytest/runner.py | 7 +++++-- _pytest/terminal.py | 9 +++++---- testing/test_runner.py | 18 ++++++++++++++++++ 4 files changed, 31 insertions(+), 7 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 31ba3a0a1..6701d7478 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,12 +1,14 @@ Changes between 2.2.4 and 2.2.5.dev ----------------------------------- +- catch unicode-issues when writing failure representations + to terminal to prevent the whole session from crashing - fix xfail/skip confusion: a skip-mark or an imperative pytest.skip will now take precedence before xfail-markers because we can't determine xfail/xpass status in case of a skip. see also: http://stackoverflow.com/questions/11105828/in-py-test-when-i-explicitly-skip-a-test-that-is-marked-as-xfail-how-can-i-get -- always report installed 3rd party plugins +- always report installed 3rd party plugins in the header of a test run - fix issue160: a failing setup of an xfail-marked tests should be reported as xfail (not xpass) diff --git a/_pytest/runner.py b/_pytest/runner.py index cac63f252..1bf62762c 100644 --- a/_pytest/runner.py +++ b/_pytest/runner.py @@ -154,7 +154,10 @@ class BaseReport(object): if hasattr(longrepr, 'toterminal'): longrepr.toterminal(out) else: - out.line(str(longrepr)) + try: + out.line(longrepr) + except UnicodeEncodeError: + out.line("") passed = property(lambda x: x.outcome == "passed") failed = property(lambda x: x.outcome == "failed") @@ -279,7 +282,7 @@ class CollectErrorRepr(TerminalRepr): def __init__(self, msg): self.longrepr = msg def toterminal(self, out): - out.line(str(self.longrepr), red=True) + out.line(self.longrepr, red=True) class SetupState(object): """ shared state for setting up/tearing down test items or collectors. """ diff --git a/_pytest/terminal.py b/_pytest/terminal.py index b825cc8bf..526337169 100644 --- a/_pytest/terminal.py +++ b/_pytest/terminal.py @@ -38,13 +38,14 @@ def pytest_configure(config): stdout = py.std.sys.stdout if hasattr(os, 'dup') and hasattr(stdout, 'fileno'): try: - newfd = os.dup(stdout.fileno()) - #print "got newfd", newfd + newstdout = py.io.dupfile(stdout, buffering=1, + encoding=stdout.encoding) except ValueError: pass else: - stdout = os.fdopen(newfd, stdout.mode, 1) - config._cleanup.append(lambda: stdout.close()) + config._cleanup.append(lambda: newstdout.close()) + assert stdout.encoding == newstdout.encoding + stdout = newstdout reporter = TerminalReporter(config, stdout) config.pluginmanager.register(reporter, 'terminalreporter') diff --git a/testing/test_runner.py b/testing/test_runner.py index 10a8c9610..e02434b8d 100644 --- a/testing/test_runner.py +++ b/testing/test_runner.py @@ -456,3 +456,21 @@ def test_pytest_cmdline_main(testdir): ret = popen.wait() assert ret == 0 + +def test_unicode_in_longrepr(testdir): + testdir.makeconftest(""" + import py + def pytest_runtest_makereport(__multicall__): + rep = __multicall__.execute() + if rep.when == "call": + rep.longrepr = py.builtin._totext("\\xc3\\xa4", "utf8") + return rep + """) + testdir.makepyfile(""" + def test_out(): + assert 0 + """) + result = testdir.runpytest() + assert result.ret == 1 + assert "UnicodeEncodeError" not in result.stderr.str() +