Skip to content

Commit 8e34c62

Browse files
committed
Fixes issue #2606, and makes color=True agnostic of Operating System.
1 parent 5b1624b commit 8e34c62

File tree

3 files changed

+154
-16
lines changed

3 files changed

+154
-16
lines changed

CHANGES.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ Unreleased
1212
the help for an option. :issue:`2500`
1313
- The test runner handles stripping color consistently on Windows.
1414
:issue:`2705`
15-
15+
- Fix/Changed the way ``color=True`` is applied when the OS is windows,
16+
additionally changed ``test_utils.py`` by removing the old version of
17+
``test_echo_color_flag`` with three different versions to test multiple
18+
cases of ``click.echo()``. :issue:`2606`
1619

1720
Version 8.1.7
1821
-------------

src/click/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ def echo(
311311
out = strip_ansi(out)
312312
elif WIN:
313313
if auto_wrap_for_ansi is not None:
314-
file = auto_wrap_for_ansi(file) # type: ignore
314+
file = auto_wrap_for_ansi(file, color) # type: ignore
315315
elif not color:
316316
out = strip_ansi(out)
317317

tests/test_utils.py

Lines changed: 149 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -209,32 +209,167 @@ def test_echo_via_pager(monkeypatch, capfd, cat, test):
209209
assert out == expected_output
210210

211211

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

217-
text = "foo"
277+
jupyter_kernel = False
278+
monkeypatch.setattr(
279+
click._compat, "_is_jupyter_kernel_output", lambda x: jupyter_kernel
280+
)
281+
218282
styled_text = click.style(text, fg="red")
219-
assert styled_text == "\x1b[31mfoo\x1b[0m"
283+
assert styled_text == stylized_text
220284

221-
click.echo(styled_text, color=False)
285+
click.echo(styled_text, color=color)
222286
out, err = capfd.readouterr()
223-
assert out == f"{text}\n"
287+
assert out == expected
224288

225-
click.echo(styled_text, color=True)
226-
out, err = capfd.readouterr()
227-
assert out == f"{styled_text}\n"
228289

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

333+
@pytest.mark.parametrize(
334+
"color, text, stylized_text, expected",
335+
[
336+
(False, _text_str, _styled_text_str, expected_stripped_text),
337+
(True, _text_str, _styled_text_str, expected_unstripped_text),
338+
(None, _text_str, _styled_text_str, expected_stripped_text),
339+
],
340+
)
341+
def test_echo_color_flag_not_atty_and_not_jupyter_kernel(
342+
monkeypatch, capfd, color, text, stylized_text, expected
343+
):
344+
"""
345+
This is the test for echo color when the stream is not a tty nor a jupyter kernel
346+
output.
347+
348+
If color is set to False, then the text should strip the ANSI values regardless
349+
of operating system.
350+
351+
If color is set to True, then we are forcing click to not care about
352+
the type of stream or operating system. This means ANSI style codes will be applied
353+
even if the output would not support them. Instances of this would be piping an
354+
echo to a file.
355+
356+
If color is set to None / not set, then click will check that the stream is neither
357+
a tty nor a jupyter notebook. This means the styling should be stripped regardless
358+
of the operating system.
359+
"""
234360
isatty = False
235-
click.echo(styled_text)
361+
monkeypatch.setattr(click._compat, "isatty", lambda x: isatty)
362+
jupyter_kernel = False
363+
monkeypatch.setattr(
364+
click._compat, "_is_jupyter_kernel_output", lambda x: jupyter_kernel
365+
)
366+
367+
styled_text = click.style(text, fg="red")
368+
assert styled_text == stylized_text
369+
370+
click.echo(styled_text, color=color)
236371
out, err = capfd.readouterr()
237-
assert out == f"{text}\n"
372+
assert out == expected
238373

239374

240375
def test_prompt_cast_default(capfd, monkeypatch):

0 commit comments

Comments
 (0)