-
-
Couldn't load subscription status.
- Fork 2.9k
Fix terminal reporter output not appearing with capture active #13848
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Fix terminal reporter output not appearing with capture active #13848
Conversation
Fixes pytest-dev#8973 When calling `reporter.write()` with `flush=True` during test execution, the output was not appearing in the terminal because pytest's output capture system intercepts writes to sys.stdout. This fix duplicates stdout's file descriptor early in `_prepareconfig()`, before any capture can start, and stores it in the config stash. The terminal reporter then uses this duplicated FD to write directly to the real terminal, bypassing capture. The duplicated file is opened with line buffering and write_through mode to ensure immediate visibility of output. Changes: - src/_pytest/config/__init__.py: Add stdout FD duplication and stash key - src/_pytest/terminal.py: Use duplicated FD in pytest_configure - testing/test_terminal.py: Add regression test and fix incompatible tests 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder how this compares to integrating with capture plugin e.g. using suspend_global_capture (or such)?
| # File descriptor for stdout, duplicated before capture starts. | ||
| # This allows the terminal reporter to bypass pytest's output capture (#8973). | ||
| # The FD is duplicated early in _prepareconfig before any capture can start. | ||
| stdout_fd_dup_key = StashKey[int]() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems weird to me that this is in config/ when config doesn't really care about it. It should be in terminal.py or maybe capture.py if we want to take care of it "at the source".
| plugin = config.pluginmanager.get_plugin("terminalprogress") | ||
| assert plugin is not None | ||
| # Use a mock file with isatty returning True | ||
| from io import StringIO |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to have the imports at the beginning of the file if they don't need to be "lazy". Also below.
| def test_plugin_registration(self, pytester: pytest.Pytester) -> None: | ||
| """Test that the plugin is registered correctly on TTY output.""" | ||
| # The plugin module should be registered as a default plugin. | ||
| with patch.object(sys.stdout, "isatty", return_value=True): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain why need to change this test?
| assert "\x1b]9;4;0;\x1b\\" in mock_file.getvalue() | ||
|
|
||
|
|
||
| def test_terminal_reporter_write_with_capture(pytester: Pytester) -> None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test seems to pass also in main, so needs some refinement if we want to prevent regression.
Fixes #8973
When calling
reporter.write()withflush=Trueduring test execution,the output was not appearing in the terminal because pytest's output
capture system intercepts writes to sys.stdout.
This fix duplicates stdout's file descriptor early in
_prepareconfig(),before any capture can start, and stores it in the config stash. The
terminal reporter then uses this duplicated FD to write directly to the
real terminal, bypassing capture.
The duplicated file is opened with line buffering and write_through mode
to ensure immediate visibility of output.
Changes:
🤖 Generated with Claude Code
Co-Authored-By: Claude noreply@anthropic.com