Skip to content

Commit b1b1231

Browse files
thorsten-kleinpdgendt
authored andcommitted
fixed RecursionError in die() method
Fixed RecursionError in die() method which has occured if config is missing. Tests are added for all log methods. Signed-off-by: Thorsten Klein <[email protected]>
1 parent 76a2ef9 commit b1b1231

File tree

2 files changed

+104
-2
lines changed

2 files changed

+104
-2
lines changed

src/west/commands.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,7 @@ def die(self, *args, exit_code: int = 1) -> NoReturn:
526526
@property
527527
def color_ui(self) -> bool:
528528
'''Should we colorize output?'''
529-
return self.config.getboolean('color.ui', default=True)
529+
return self.config.getboolean('color.ui', default=True) if self.has_config else True
530530

531531
#
532532
# Internal APIs. Not for public consumption.

tests/test_commands.py

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
import os
44

5-
from west.commands import WestCommand
5+
import pytest
6+
7+
from west.commands import Verbosity, WestCommand
68

79
assert 'TOXTEMPDIR' in os.environ, "you must run these tests using tox"
810

@@ -16,3 +18,103 @@ def test_parse_git_version():
1618
assert gv(b'git version 2.24.3 (Apple Git-128)\n') == (2, 24, 3)
1719
assert gv(b'git version 2.29.GIT\n') == (2, 29)
1820
assert gv(b'not a git version') is None
21+
22+
23+
class WestCommandImpl(WestCommand):
24+
def do_add_parser(self):
25+
pass
26+
27+
def do_run(self):
28+
pass
29+
30+
cmd = WestCommandImpl(name="x", help="y", description="z")
31+
32+
TEST_STR = "This is some test string"
33+
COL_RED = "\x1b[91m"
34+
COL_YELLOW = "\x1b[93m"
35+
COL_OFF = "\x1b[0m"
36+
37+
EXPECTED_LOG_DEFAULT = f'{TEST_STR}\n'
38+
EXPECTED_LOG_WARNING = f'{COL_YELLOW}WARNING: {TEST_STR}\n{COL_OFF}'
39+
EXPECTED_LOG_ERROR = f'{COL_RED}ERROR: {TEST_STR}\n{COL_OFF}'
40+
EXPECTED_LOG_FATAL_ERROR = f'{COL_RED}FATAL ERROR: {TEST_STR}\n{COL_OFF}'
41+
42+
TEST_CASES_LOG = [
43+
# max_log_level, log_cmd, expected_stdout, expected_stderr
44+
(Verbosity.DBG_EXTREME, cmd.dbg, EXPECTED_LOG_DEFAULT, ''),
45+
(Verbosity.DBG_EXTREME, cmd.inf, EXPECTED_LOG_DEFAULT, ''),
46+
(Verbosity.DBG_EXTREME, cmd.wrn, '', EXPECTED_LOG_WARNING),
47+
(Verbosity.DBG_EXTREME, cmd.err, '', EXPECTED_LOG_ERROR),
48+
(Verbosity.DBG_MORE, cmd.dbg, EXPECTED_LOG_DEFAULT, ''),
49+
(Verbosity.DBG_MORE, cmd.inf, EXPECTED_LOG_DEFAULT, ''),
50+
(Verbosity.DBG_MORE, cmd.wrn, '', EXPECTED_LOG_WARNING),
51+
(Verbosity.DBG_MORE, cmd.err, '', EXPECTED_LOG_ERROR),
52+
(Verbosity.DBG, cmd.dbg, EXPECTED_LOG_DEFAULT, ''),
53+
(Verbosity.DBG, cmd.inf, EXPECTED_LOG_DEFAULT, ''),
54+
(Verbosity.DBG, cmd.wrn, '', EXPECTED_LOG_WARNING),
55+
(Verbosity.DBG, cmd.err, '', EXPECTED_LOG_ERROR),
56+
(Verbosity.INF, cmd.dbg, '', ''),
57+
(Verbosity.INF, cmd.inf, EXPECTED_LOG_DEFAULT, ''),
58+
(Verbosity.INF, cmd.wrn, '', EXPECTED_LOG_WARNING),
59+
(Verbosity.INF, cmd.err, '', EXPECTED_LOG_ERROR),
60+
(Verbosity.WRN, cmd.dbg, '', ''),
61+
(Verbosity.WRN, cmd.inf, '', ''),
62+
(Verbosity.WRN, cmd.wrn, '', EXPECTED_LOG_WARNING),
63+
(Verbosity.WRN, cmd.err, '', EXPECTED_LOG_ERROR),
64+
(Verbosity.ERR, cmd.dbg, '', ''),
65+
(Verbosity.ERR, cmd.inf, '', ''),
66+
(Verbosity.ERR, cmd.wrn, '', ''),
67+
(Verbosity.ERR, cmd.err, '', EXPECTED_LOG_ERROR),
68+
(Verbosity.QUIET, cmd.dbg, '', ''),
69+
(Verbosity.QUIET, cmd.inf, '', ''),
70+
(Verbosity.QUIET, cmd.wrn, '', ''),
71+
(Verbosity.QUIET, cmd.err, '', ''),
72+
]
73+
74+
@pytest.mark.parametrize("test_case", TEST_CASES_LOG)
75+
def test_log(capsys, test_case):
76+
max_log_level, log_cmd, exp_out, exp_err = test_case
77+
cmd.verbosity = max_log_level
78+
log_cmd(TEST_STR)
79+
captured = capsys.readouterr()
80+
stdout = captured.out
81+
stderr = captured.err
82+
assert stderr == exp_err
83+
assert stdout == exp_out
84+
85+
86+
TEST_CASES_DIE = [
87+
# max_log_level, exp_out, exp_err, exp_exit, exp_exc
88+
(Verbosity.DBG_EXTREME, '', EXPECTED_LOG_FATAL_ERROR, None,
89+
RuntimeError('die with -vvv or more shows a stack trace. '
90+
'exit_code argument is ignored.'
91+
'')),
92+
(Verbosity.DBG_MORE, '', EXPECTED_LOG_FATAL_ERROR, SystemExit(1), None),
93+
(Verbosity.DBG, '', EXPECTED_LOG_FATAL_ERROR, SystemExit(1), None),
94+
(Verbosity.INF, '', EXPECTED_LOG_FATAL_ERROR, SystemExit(1), None),
95+
(Verbosity.WRN, '', EXPECTED_LOG_FATAL_ERROR, SystemExit(1), None),
96+
(Verbosity.ERR, '', EXPECTED_LOG_FATAL_ERROR, SystemExit(1), None),
97+
(Verbosity.QUIET, '', '', SystemExit(1), None),
98+
]
99+
100+
@pytest.mark.parametrize("test_case", TEST_CASES_DIE)
101+
def test_die(capsys, test_case):
102+
max_log_level, exp_out, exp_err, exp_exit, exp_exc = test_case
103+
cmd.verbosity = max_log_level
104+
105+
if exp_exit:
106+
with pytest.raises(SystemExit) as exit_info:
107+
cmd.die(TEST_STR)
108+
assert exit_info.type is type(exp_exit)
109+
assert exit_info.value.code == exp_exit.code
110+
if exp_exc:
111+
with pytest.raises(Exception) as exc_info:
112+
cmd.die(TEST_STR)
113+
assert type(exc_info.value) is type(exp_exc)
114+
assert str(exc_info.value) == str(exp_exc)
115+
116+
captured = capsys.readouterr()
117+
stdout = captured.out
118+
stderr = captured.err
119+
assert stderr == exp_err
120+
assert stdout == exp_out

0 commit comments

Comments
 (0)