Open ResidentMario opened 7 years ago
I am seeing this also when using __import__('pdb').set_trace()
somewhere inside of the runner
.
This is likely related to pytest turning IO-capturing off / changing it.
Reminded me of an old stash I had: https://github.com/pallets/click/pull/951.
As for pytest itself I've created https://github.com/pytest-dev/pytest/issues/3344.
See also https://github.com/pallets/click/issues/654 (duplicate?!).
I hit a similar error when writing a CLI of my own & thought I'd share my fix in the hope it helps isolate where there might be a fix (and this is the top hit in Google for me).
In one of my commands I was opening stdout using click.get_text_stream
- something like
with click.open_file(input) as src, click.get_text_stream('stdout') as sink:
data = parse_input()
sink.write(json.dumps(data) + '\n')
...and I think the closing of the sink stream at the end of the context was killing the mocked version of stdout in the test?
Anyway, the workaround was to shift to click.echo
which is much better behaved (and doesn't require the context manager). Hopefully this helps someone else (I certainly wasted a fair bit of time working it out!).
I got the issue recently as well. It was due to the use of a logger within the function.
Using click.echo
can as well solve the issue if the logging was to only display some info to the user.
The workaround I found is to write my pytest function with the caplog
fixture and making sure no logger will produce any message.
def test_xxxx(caplog):
caplog.set_level(100000)
...
I recently ran into this and created a repo which reproduces the issue standalone: https://github.com/cdleonard/click-pytest-issue
The problem seems to be that the stdio capturing of pytest and click does not mix well. My workaround is to just avoid CliRunner and call main() directly because pytest caplog/capsys already covers everything.
Maybe there could be an option to disable the stdio isolation feature of CliRunner?
See #2156 for a simple example that reproduces the error on Windows. The example only fails if pytest live logs is enabled.
Doing the following seems to work well for me:
def test_no_args(capsys: CaptureFixture):
with capsys.disabled() as disabled:
result = CliRunner.invoke(...)
FYI, building on previous answers in this thread, we ended up creating the following fixture to disable capsys on all invoke calls (truncated to simplify)
@pytest.fixture
def click_runner(capsys: CaptureFixture[str]) -> Iterator[CliRunner]:
"""
Convenience fixture to return a click.CliRunner for cli testing
"""
class MyCliRunner(CliRunner):
"""Override CliRunner to disable capsys"""
def invoke(self, *args, **kwargs) -> Result:
# Way to fix https://github.com/pallets/click/issues/824
with capsys.disabled():
result = super().invoke(*args, **kwargs)
return result
yield MyCliRunner()
See #2156 for a simple example that reproduces the error on Windows. The example only fails if pytest live logs is enabled.
I had the issue as well for pytest live logs. I actually wanted to see logs for passed tests though (not necessarily "live"). So running pytest -rP
instead worked for me.
I was running into this with the --cli-log-level
option, solved by adding -s
.
I am getting a
ValueError
when usingCliRunner
to test my CLI tool. Unfortunately I can't isolate, but I can give a reproduction:Which raises the following traceback:
This is on Ubuntu 16.04.