Skip to content

Commit e4d4f3c

Browse files
Tyl13AndreasBackx
authored andcommitted
Fixes issue #2606, and makes color=True agnostic of Operating System.
1 parent 26aa7bf commit e4d4f3c

File tree

2 files changed

+153
-14
lines changed

2 files changed

+153
-14
lines changed

CHANGES.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ Unreleased
1616
:issue:`2632`
1717
- Fix ``click.echo(color=...)`` passing ``color`` to coloroma so it can be
1818
forced on Windows. :issue:`2606`.
19-
19+
- Fix/Changed the way ``color=True`` is applied when the OS is windows,
20+
additionally changed ``test_utils.py`` by removing the old version of
21+
``test_echo_color_flag`` with three different versions to test multiple
22+
cases of ``click.echo()``. :issue:`2606` :pr:`2731`
2023

2124
Version 8.1.7
2225
-------------

tests/test_utils.py

Lines changed: 149 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -207,34 +207,170 @@ def test_echo_via_pager(monkeypatch, capfd, cat, test):
207207
assert out == expected_output
208208

209209

210-
def test_echo_color_flag(monkeypatch, capfd):
210+
"""
211+
These variables are used for the next three tests.
212+
213+
_text_str is guranteeing that each color test is using the same
214+
string.
215+
216+
_styled_text_str is running _text_str through click.style with fg
217+
set to red. This gurantees that each test is getting the same styled text.
218+
219+
expected_stripped_text is using an fstring on _text_str to add a newline chracter
220+
to the end of it.
221+
222+
expected_unstripped_text is using an fstring on_styled_text_str to add a newline
223+
character to the end of it.
224+
225+
Each expected variable is what is being used in the asserts to gurantee the output
226+
is correct.
227+
228+
The unstripped version is for when an the ANSI style should stay applied.
229+
The stripped version is for when the ANSI style should be removed from the text.
230+
231+
These can be removed if you would rather have the parametrize values be explict
232+
in the following tests. The variables could also be extended and the tests truncated
233+
by adding isatty and jupyter_kernel variables here. Expanding the parametrize
234+
matrix to use those within the test instead of it being explict based on tests.
235+
"""
236+
_text_str = "test"
237+
_styled_text_str = click.style(_text_str, fg="red")
238+
expected_stripped_text = f"{_text_str}\n"
239+
expected_unstripped_text = f"{_styled_text_str}\n"
240+
241+
242+
@pytest.mark.parametrize(
243+
"color, text, stylized_text, expected",
244+
[
245+
(False, _text_str, _styled_text_str, expected_stripped_text),
246+
(True, _text_str, _styled_text_str, expected_unstripped_text),
247+
(None, _text_str, _styled_text_str, expected_unstripped_text),
248+
],
249+
)
250+
def test_echo_color_flag_atty_and_not_jupyter_kernel(
251+
monkeypatch, capfd, color, text, stylized_text, expected
252+
):
253+
"""
254+
This is the test for echo color when the stream is a tty and
255+
not a jupyter kernel output.
256+
257+
If color is set to False, then the text should strip the ANSI values regardless
258+
of operating system.
259+
260+
If color is set to True, then we are forcing click to not care about
261+
the type of stream or operating system. This means ANSI style codes will be applied
262+
even if the output would not support them. Instances of this would be piping an
263+
echo to a file.
264+
265+
If color is set to None / not set, then click will check if the stream is a tty.
266+
This test is forcing that to always be true, and will then mean that the output
267+
should keep the ANSI style.
268+
269+
The mocking of _is_jupyter_kernel_output is not needed, but was added to keep it
270+
consistent with the other tests.
271+
"""
211272
isatty = True
212273
monkeypatch.setattr(click._compat, "isatty", lambda x: isatty)
213274

214-
text = "foo"
275+
jupyter_kernel = False
276+
monkeypatch.setattr(
277+
click._compat, "_is_jupyter_kernel_output", lambda x: jupyter_kernel
278+
)
279+
215280
styled_text = click.style(text, fg="red")
216-
assert styled_text == "\x1b[31mfoo\x1b[0m"
281+
assert styled_text == stylized_text
217282

218-
click.echo(styled_text, color=False)
283+
click.echo(styled_text, color=color)
219284
out, err = capfd.readouterr()
220-
assert out == f"{text}\n"
285+
assert out == expected
221286

222-
click.echo(styled_text, color=True)
223-
out, err = capfd.readouterr()
224-
assert out == f"{styled_text}\n"
225287

226-
isatty = True
227-
click.echo(styled_text)
288+
@pytest.mark.parametrize(
289+
"color, text, stylized_text, expected",
290+
[
291+
(False, _text_str, _styled_text_str, expected_stripped_text),
292+
(True, _text_str, _styled_text_str, expected_unstripped_text),
293+
(None, _text_str, _styled_text_str, expected_unstripped_text),
294+
],
295+
)
296+
def test_echo_color_flag_jupyter_kernel_and_not_atty(
297+
monkeypatch, capfd, color, text, stylized_text, expected
298+
):
299+
"""
300+
This is the test for echo color when the stream is not a tty and
301+
is a jupyter kernel output.
302+
303+
If color is set to False, then the text should strip the ANSI values regardless
304+
of operating system.
305+
306+
If color is set to True, then we are forcing click to not care about
307+
the type of stream or operating system. This means ANSI style codes will be applied
308+
even if the output would not support them. Instances of this would be piping an
309+
echo to a file.
310+
311+
If color is set to None / not set, then click will check if the stream is a tty.
312+
Which is being forced to be False so, the strip function will next check if
313+
the stream is a jupyter kernel output which is being set as True. This means
314+
that the ANSI style should not be stripped.
315+
"""
316+
jupyter_kernel = True
317+
monkeypatch.setattr(
318+
click._compat, "_is_jupyter_kernel_output", lambda x: jupyter_kernel
319+
)
320+
isatty = False
321+
monkeypatch.setattr(click._compat, "isatty", lambda x: isatty)
322+
323+
styled_text = click.style(text, fg="red")
324+
assert styled_text == stylized_text
325+
326+
click.echo(styled_text, color=color)
228327
out, err = capfd.readouterr()
229-
assert out == f"{styled_text}\n"
328+
assert out == expected
329+
230330

331+
@pytest.mark.parametrize(
332+
"color, text, stylized_text, expected",
333+
[
334+
(False, _text_str, _styled_text_str, expected_stripped_text),
335+
(True, _text_str, _styled_text_str, expected_unstripped_text),
336+
(None, _text_str, _styled_text_str, expected_stripped_text),
337+
],
338+
)
339+
def test_echo_color_flag_not_atty_and_not_jupyter_kernel(
340+
monkeypatch, capfd, color, text, stylized_text, expected
341+
):
342+
"""
343+
This is the test for echo color when the stream is not a tty nor a jupyter kernel
344+
output.
345+
346+
If color is set to False, then the text should strip the ANSI values regardless
347+
of operating system.
348+
349+
If color is set to True, then we are forcing click to not care about
350+
the type of stream or operating system. This means ANSI style codes will be applied
351+
even if the output would not support them. Instances of this would be piping an
352+
echo to a file.
353+
354+
If color is set to None / not set, then click will check that the stream is neither
355+
a tty nor a jupyter notebook. This means the styling should be stripped regardless
356+
of the operating system.
357+
"""
231358
isatty = False
232359
# Faking isatty() is not enough on Windows;
233360
# the implementation caches the colorama wrapped stream
234361
# so we have to use a new stream for each test
235362
stream = StringIO()
236-
click.echo(styled_text, file=stream)
237-
assert stream.getvalue() == f"{text}\n"
363+
monkeypatch.setattr(click._compat, "isatty", lambda x: isatty)
364+
jupyter_kernel = False
365+
monkeypatch.setattr(
366+
click._compat, "_is_jupyter_kernel_output", lambda x: jupyter_kernel
367+
)
368+
369+
styled_text = click.style(text, fg="red")
370+
assert styled_text == stylized_text
371+
372+
click.echo(styled_text, color=color, file=stream)
373+
assert stream.getvalue() == expected
238374

239375
stream = StringIO()
240376
click.echo(styled_text, file=stream, color=True)

0 commit comments

Comments
 (0)