Skip to content

Commit 73b44db

Browse files
committed
main: refactor color detection
Signed-off-by: Filipe Laíns <lains@riseup.net>
1 parent 672d9dc commit 73b44db

File tree

2 files changed

+48
-4
lines changed

2 files changed

+48
-4
lines changed

src/build/__main__.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import traceback
1414
import warnings
1515

16-
from typing import Iterable, Iterator, List, Optional, Sequence, TextIO, Type, Union
16+
from typing import Dict, Iterable, Iterator, List, Optional, Sequence, TextIO, Type, Union
1717

1818
import build
1919

@@ -24,7 +24,7 @@
2424
__all__ = ['build', 'main', 'main_parser']
2525

2626

27-
_STYLES = {
27+
_COLORS = {
2828
'red': '\33[91m',
2929
'green': '\33[92m',
3030
'yellow': '\33[93m',
@@ -33,8 +33,20 @@
3333
'underline': '\33[4m',
3434
'reset': '\33[0m',
3535
}
36-
if 'FORCE_COLOR' not in os.environ and not sys.stdout.isatty() or 'NO_COLOR' in os.environ:
37-
_STYLES = {color: '' for color in _STYLES}
36+
_NO_COLORS = {color: '' for color in _COLORS}
37+
38+
39+
def _init_colors() -> Dict[str, str]:
40+
if 'NO_COLOR' in os.environ:
41+
if 'FORCE_COLOR' in os.environ:
42+
warnings.warn('Both NO_COLOR and FORCE_COLOR environment variables are set, disabling color')
43+
return _NO_COLORS
44+
elif 'FORCE_COLOR' in os.environ or sys.stdout.isatty():
45+
return _COLORS
46+
return _NO_COLORS
47+
48+
49+
_STYLES = _init_colors()
3850

3951

4052
def _showwarning(

tests/test_main.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ def test_output_env_subprocess_error(
338338
stdout_body,
339339
stdout_error,
340340
):
341+
monkeypatch.delenv('NO_COLOR')
341342
monkeypatch.setenv('FORCE_COLOR' if color else 'NO_COLOR', '')
342343

343344
importlib.reload(build.__main__) # reload module to set _STYLES
@@ -352,3 +353,34 @@ def test_output_env_subprocess_error(
352353

353354
assert len(stderr) == 1
354355
assert stderr[0].startswith('ERROR: Invalid requirement: ')
356+
357+
358+
@pytest.mark.parametrize(
359+
('tty', 'env', 'colors'),
360+
[
361+
(False, {}, build.__main__._NO_COLORS),
362+
(True, {}, build.__main__._COLORS),
363+
(False, {'NO_COLOR': ''}, build.__main__._NO_COLORS),
364+
(True, {'NO_COLOR': ''}, build.__main__._NO_COLORS),
365+
(False, {'FORCE_COLOR': ''}, build.__main__._COLORS),
366+
(True, {'FORCE_COLOR': ''}, build.__main__._COLORS),
367+
],
368+
)
369+
def test_colors(mocker, monkeypatch, main_reload_styles, tty, env, colors):
370+
mocker.patch('sys.stdout.isatty', return_value=tty)
371+
for key, value in env.items():
372+
monkeypatch.setenv(key, value)
373+
374+
importlib.reload(build.__main__) # reload module to set _STYLES
375+
376+
assert build.__main__._STYLES == colors
377+
378+
379+
def test_colors_conflict(monkeypatch, main_reload_styles):
380+
monkeypatch.setenv('NO_COLOR', '')
381+
monkeypatch.setenv('FORCE_COLOR', '')
382+
383+
with pytest.warns(Warning, match='Both NO_COLOR and FORCE_COLOR environment variables are set, disabling color'):
384+
importlib.reload(build.__main__)
385+
386+
assert build.__main__._STYLES == build.__main__._NO_COLORS

0 commit comments

Comments
 (0)