diff --git a/CHANGELOG b/CHANGELOG index 3aa1df466..ce1009166 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -26,6 +26,10 @@ NEXT (2.6) - fix issue412: messing with stdout/stderr FD-level streams is now captured without crashes. +- simplified internal capturing mechanism and made it more robust + against tests or setups changing FD1/FD2, also better integrated + now with pytest.pdb() in single tests. + 2.5.2 ----------------------------------- diff --git a/_pytest/capture.py b/_pytest/capture.py index 121221cd9..be4f5bbbe 100644 --- a/_pytest/capture.py +++ b/_pytest/capture.py @@ -7,7 +7,6 @@ from __future__ import with_statement import sys import os from tempfile import TemporaryFile -import contextlib import py import pytest @@ -34,13 +33,9 @@ def pytest_addoption(parser): def pytest_load_initial_conftests(early_config, parser, args, __multicall__): ns = parser.parse_known_args(args) pluginmanager = early_config.pluginmanager - method = ns.capture - if method != "no": - dupped_stdout = safe_text_dupfile(sys.stdout, "wb") - pluginmanager.register(dupped_stdout, "dupped_stdout") - #pluginmanager.add_shutdown(dupped_stdout.close) - - capman = CaptureManager(method) + if ns.capture == "no": + return + capman = CaptureManager(ns.capture) pluginmanager.register(capman, "capturemanager") # make sure that capturemanager is properly reset at final shutdown @@ -129,20 +124,23 @@ class CaptureManager: @pytest.mark.hookwrapper def pytest_runtest_setup(self, item): - with self.item_capture_wrapper(item, "setup"): - yield + self.resumecapture() + yield + self.suspendcapture_item(item, "setup") @pytest.mark.hookwrapper def pytest_runtest_call(self, item): - with self.item_capture_wrapper(item, "call"): - self.activate_funcargs(item) - yield - #self.deactivate_funcargs() called from ctx's suspendcapture() + self.resumecapture() + self.activate_funcargs(item) + yield + #self.deactivate_funcargs() called from suspendcapture() + self.suspendcapture_item(item, "call") @pytest.mark.hookwrapper def pytest_runtest_teardown(self, item): - with self.item_capture_wrapper(item, "teardown"): - yield + self.resumecapture() + yield + self.suspendcapture_item(item, "teardown") @pytest.mark.tryfirst def pytest_keyboard_interrupt(self, excinfo): @@ -152,10 +150,7 @@ class CaptureManager: def pytest_internalerror(self, excinfo): self.reset_capturings() - @contextlib.contextmanager - def item_capture_wrapper(self, item, when): - self.resumecapture() - yield + def suspendcapture_item(self, item, when): out, err = self.suspendcapture() item.add_report_section(when, "out", out) item.add_report_section(when, "err", err) diff --git a/_pytest/genscript.py b/_pytest/genscript.py index b58798aec..25e8e6a0f 100755 --- a/_pytest/genscript.py +++ b/_pytest/genscript.py @@ -60,7 +60,6 @@ def pytest_addoption(parser): def pytest_cmdline_main(config): genscript = config.getvalue("genscript") if genscript: - #tw = config.get_terminal_writer() tw = py.io.TerminalWriter() deps = ['py', '_pytest', 'pytest'] if sys.version_info < (2,7): diff --git a/_pytest/helpconfig.py b/_pytest/helpconfig.py index f3cb10fe7..9e31c21e7 100644 --- a/_pytest/helpconfig.py +++ b/_pytest/helpconfig.py @@ -47,8 +47,6 @@ def pytest_unconfigure(config): def pytest_cmdline_main(config): if config.option.version: - capman = config.pluginmanager.getplugin("capturemanager") - capman.reset_capturings() p = py.path.local(pytest.__file__) sys.stderr.write("This is pytest version %s, imported from %s\n" % (pytest.__version__, p)) @@ -64,7 +62,7 @@ def pytest_cmdline_main(config): return 0 def showhelp(config): - tw = config.get_terminal_writer() + tw = py.io.TerminalWriter() tw.write(config._parser.optparser.format_help()) tw.line() tw.line() diff --git a/_pytest/mark.py b/_pytest/mark.py index 0d241625e..6b66b1876 100644 --- a/_pytest/mark.py +++ b/_pytest/mark.py @@ -40,7 +40,7 @@ def pytest_addoption(parser): def pytest_cmdline_main(config): if config.option.markers: config.do_configure() - tw = config.get_terminal_writer() + tw = py.io.TerminalWriter() for line in config.getini("markers"): name, rest = line.split(":", 1) tw.write("@pytest.mark.%s:" % name, bold=True) diff --git a/_pytest/python.py b/_pytest/python.py index 23a45f30d..544055ec9 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -885,7 +885,7 @@ def _showfixtures_main(config, session): nodeid = "::".join(map(str, [curdir.bestrelpath(part[0])] + part[1:])) nodeid.replace(session.fspath.sep, "/") - tw = config.get_terminal_writer() + tw = py.io.TerminalWriter() verbose = config.getvalue("verbose") fm = session._fixturemanager diff --git a/_pytest/terminal.py b/_pytest/terminal.py index 3647fa7f9..29e4e8c9f 100644 --- a/_pytest/terminal.py +++ b/_pytest/terminal.py @@ -36,10 +36,7 @@ def pytest_addoption(parser): def pytest_configure(config): config.option.verbose -= config.option.quiet - out = config.pluginmanager.getplugin("dupped_stdout") - #if out is None: - # out = sys.stdout - reporter = TerminalReporter(config, out) + reporter = TerminalReporter(config, sys.stdout) config.pluginmanager.register(reporter, 'terminalreporter') if config.option.debug or config.option.traceconfig: def mywriter(tags, args): @@ -47,11 +44,6 @@ def pytest_configure(config): reporter.write_line("[traceconfig] " + msg) config.trace.root.setprocessor("pytest:config", mywriter) -def get_terminal_writer(config): - tr = config.pluginmanager.getplugin("terminalreporter") - return tr._tw - - def getreportopt(config): reportopts = "" optvalue = config.option.report @@ -104,7 +96,6 @@ class TerminalReporter: self.startdir = self.curdir = py.path.local() if file is None: file = py.std.sys.stdout - #assert file.encoding self._tw = self.writer = py.io.TerminalWriter(file) if self.config.option.color == 'yes': self._tw.hasmarkup = True