pytest
pytest copied to clipboard
calling capture.resume_global_capture() changes the used terminal width
I have to suspend the global capture, because I ask the user for some user input in my pytest plugin. But this leads to a changed terminal width.
conftest.py
import pytest
import shutil
@pytest.hookimpl(trylast=True)
def pytest_sessionfinish(session):
capture = session.config.pluginmanager.getplugin("capturemanager")
capture.suspend_global_capture(in_=True)
# some code to read user input
print(shutil.get_terminal_size())
capture.resume_global_capture()
print(shutil.get_terminal_size())
The === in the no tests ran line are shorter than above and the result of get_terminal_size changed.
pytest: 8.3.5 os: Debian
I performed this test in a directory that only contained the specified file conftest.py.
Hey @15r10nk ,
Thanks for reporting this! It looks like suspending global capture is affecting how pytest handles terminal settings, which in turn changes the reported terminal width. This is likely due to how pytest manages stdout and stderr during capture.
Potential Workarounds: ✅ Store and restore the terminal size manually before and after suspending capture: `` `import pytest import shutil import os
@pytest.hookimpl(trylast=True) def pytest_sessionfinish(session): capture = session.config.pluginmanager.getplugin("capturemanager") terminal_size_before = shutil.get_terminal_size()
capture.suspend_global_capture(in_=True)
print("Terminal size after suspend:", shutil.get_terminal_size())
capture.resume_global_capture()
os.environ["COLUMNS"] = str(terminal_size_before.columns)
os.environ["LINES"] = str(terminal_size_before.lines)
print("Terminal size after resume:", shutil.get_terminal_size())
✅ Write directly to sys.__stdout__ instead of using print(), since pytest captures stdout:
import sys sys.stdout.write(f"Terminal size after suspend: {shutil.get_terminal_size()}\n")
✅ Try flushing stdout before and after suspending capture to maintain expected behavior:
import sys sys.stdout.flush()
Would love to hear if any of these solutions work for you! Let me know how it goes. 🚀
@sanyamk23 if you post random Ai output, at least verify its not completely wrong on the technical side
It's simply mean to anyone else as is
I debugged a bit deeper and the problem seems to be that only in_ is captured.
import pytest
@pytest.hookimpl(trylast=True)
def pytest_sessionfinish(session):
capture = session.config.pluginmanager.getplugin("capturemanager")
print(capture._global_capturing)
========================================= test session starts ==========================================
platform linux -- Python 3.13.1, pytest-8.5.0.dev57+gcfc66062c, pluggy-1.6.0
rootdir: /home/frank/projects/tmp/pytest_bug
collected 1 item
test_a.py . [100%]<
MultiCapture out=<FDCapture 1 oldfd=7 _state='suspended' tmpfile=<EncodedFile name="<_io.FileIO name=8 m
ode='rb+' closefd=True>" mode='r+' encoding='utf-8'>> err=<FDCapture 2 oldfd=9 _state='suspended' tmpfil
e=<EncodedFile name="<_io.FileIO name=10 mode='rb+' closefd=True>" mode='r+' encoding='utf-8'>> in_=<FDC
apture 0 oldfd=5 _state='started' tmpfile=<_io.TextIOWrapper name='/dev/null' mode='r' encoding='utf-8'>
> _state='suspended' _in_suspended=False>
========================================== 1 passed in 0.00s ===========================================
The output shows that out and err are in suspended state and in_ is in started state
I find this a bit confusing and see no reason for it.
This is my current work around:
if (
capture._global_capturing is not None
and capture._global_capturing.in_ is not None
):
capture._global_capturing.in_.suspend()
try:
...
finally:
if (
capture._global_capturing is not None
and capture._global_capturing.in_ is not None
):
capture._global_capturing.in_.resume()
This is definitely not the best solution (because it uses internal API) but the only one I could find.
Please let me know if there is a better way to fix this.