From 7c6e47f715e4956573191ad98bfa8f44087cf1a9 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Tue, 5 Oct 2010 17:21:50 +0200 Subject: [PATCH] fix issue124 - make test reporting more resilient against tests changing FD 1 --HG-- branch : trunk --- CHANGELOG | 2 ++ py/_plugin/pytest_terminal.py | 12 ++++++++++-- testing/plugin/test_pytest_capture.py | 1 - testing/plugin/test_pytest_terminal.py | 18 ++++++++++++++++++ 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 2e5499610..38124fc31 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,8 @@ Changes between 1.3.4 and 1.4.0.dev0 ================================================== +- fix issue124 - make reporting more resilient against tests opening + files on filedescriptor 1 (stdout). - fix issue109 - sibling conftest.py files will not be loaded. (and Directory collectors cannot be customized anymore from a Directory's conftest.py - this needs to happen at least one level up). diff --git a/py/_plugin/pytest_terminal.py b/py/_plugin/pytest_terminal.py index 7be7e1be8..1ed32a4f7 100644 --- a/py/_plugin/pytest_terminal.py +++ b/py/_plugin/pytest_terminal.py @@ -5,6 +5,7 @@ This is a good source for looking at the various reporting hooks. """ import py import sys +import os def pytest_addoption(parser): group = parser.getgroup("terminal reporting", "reporting", after="general") @@ -29,8 +30,6 @@ def pytest_addoption(parser): help="don't cut any tracebacks (default is to cut).") def pytest_configure(config): - if config.option.showfuncargs: - return if config.option.collectonly: reporter = CollectonlyReporter(config) else: @@ -75,6 +74,15 @@ class TerminalReporter: self.curdir = py.path.local() if file is None: file = py.std.sys.stdout + # we try hard to make printing resilient against + # later changes on FD level. + if hasattr(os, 'dup') and hasattr(file, 'fileno'): + try: + newfd = os.dup(file.fileno()) + except ValueError: + pass + else: + file = os.fdopen(newfd, file.mode, 1) self._tw = py.io.TerminalWriter(file) self.currentfspath = None self.reportchars = getreportopt(config) diff --git a/testing/plugin/test_pytest_capture.py b/testing/plugin/test_pytest_capture.py index a583bd873..1e596aa0e 100644 --- a/testing/plugin/test_pytest_capture.py +++ b/testing/plugin/test_pytest_capture.py @@ -377,4 +377,3 @@ def test_fdfuncarg_skips_on_no_osdup(testdir): result.stdout.fnmatch_lines([ "*1 skipped*" ]) - diff --git a/testing/plugin/test_pytest_terminal.py b/testing/plugin/test_pytest_terminal.py index 1a0fbea46..bbb2a0ab7 100644 --- a/testing/plugin/test_pytest_terminal.py +++ b/testing/plugin/test_pytest_terminal.py @@ -609,3 +609,21 @@ def pytest_report_header(config): "line2", "*hello: info*", ]) + +needsosdup = py.test.mark.xfail("not hasattr(os, 'dup')") +def test_fdopen_kept_alive_issue124(testdir): + testdir.makepyfile(""" + import os, sys + k = [] + def test_open_file_and_keep_alive(capfd): + stdout = os.fdopen(1, 'w', 1) + k.append(stdout) + + def test_close_kept_alive_file(): + stdout = k.pop() + stdout.close() + """) + result = testdir.runpytest("-s") + result.stdout.fnmatch_lines([ + "*2 passed*" + ])