Skip to content

Commit 7882d75

Browse files
authored
fix: print stdout and stderr when there is error (#142)
1 parent 96fbc91 commit 7882d75

File tree

2 files changed

+35
-20
lines changed

2 files changed

+35
-20
lines changed

cpp_linter_hooks/util.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
import logging
66
from typing import Optional, List
77

8-
try:
8+
if sys.version_info >= (3, 11):
99
import tomllib
10-
except ModuleNotFoundError:
10+
else:
1111
import tomli as tomllib
1212

1313
from cpp_linter_hooks.versions import CLANG_FORMAT_VERSIONS, CLANG_TIDY_VERSIONS
@@ -60,16 +60,18 @@ def parse_version(v: str):
6060

6161

6262
def _install_tool(tool: str, version: str) -> Optional[Path]:
63-
"""Install a tool using pip, suppressing output."""
64-
try:
65-
subprocess.check_call(
66-
[sys.executable, "-m", "pip", "install", f"{tool}=={version}"],
67-
stdout=subprocess.DEVNULL,
68-
stderr=subprocess.DEVNULL,
69-
)
63+
"""Install a tool using pip, logging output on failure."""
64+
result = subprocess.run(
65+
[sys.executable, "-m", "pip", "install", f"{tool}=={version}"],
66+
capture_output=True,
67+
text=True,
68+
)
69+
if result.returncode == 0:
7070
return shutil.which(tool)
71-
except subprocess.CalledProcessError:
72-
return None
71+
LOG.error("pip failed to install %s %s", tool, version)
72+
LOG.error(result.stdout)
73+
LOG.error(result.stderr)
74+
return None
7375

7476

7577
def resolve_install(tool: str, version: Optional[str]) -> Optional[Path]:

tests/test_util.py

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -123,28 +123,34 @@ def test_install_tool_success():
123123
"""Test _install_tool successful installation."""
124124
mock_path = "/usr/bin/clang-format"
125125

126+
def patched_run(*args, **kwargs):
127+
return subprocess.CompletedProcess(args, returncode=0)
128+
126129
with (
127-
patch("subprocess.check_call") as mock_check_call,
130+
patch("subprocess.run", side_effect=patched_run) as mock_run,
128131
patch("shutil.which", return_value=mock_path),
129132
):
130133
result = _install_tool("clang-format", "20.1.7")
131134
assert result == mock_path
132135

133-
mock_check_call.assert_called_once_with(
136+
mock_run.assert_called_once_with(
134137
[sys.executable, "-m", "pip", "install", "clang-format==20.1.7"],
135-
stdout=subprocess.DEVNULL,
136-
stderr=subprocess.DEVNULL,
138+
capture_output=True,
139+
text=True,
137140
)
138141

139142

140143
@pytest.mark.benchmark
141144
def test_install_tool_failure():
142145
"""Test _install_tool when pip install fails."""
146+
147+
def patched_run(*args, **kwargs):
148+
return subprocess.CompletedProcess(
149+
args, returncode=1, stderr="Error", stdout="Installation failed"
150+
)
151+
143152
with (
144-
patch(
145-
"subprocess.check_call",
146-
side_effect=subprocess.CalledProcessError(1, ["pip"]),
147-
),
153+
patch("subprocess.run", side_effect=patched_run),
148154
patch("cpp_linter_hooks.util.LOG"),
149155
):
150156
result = _install_tool("clang-format", "20.1.7")
@@ -154,7 +160,14 @@ def test_install_tool_failure():
154160
@pytest.mark.benchmark
155161
def test_install_tool_success_but_not_found():
156162
"""Test _install_tool when install succeeds but tool not found in PATH."""
157-
with patch("subprocess.check_call"), patch("shutil.which", return_value=None):
163+
164+
def patched_run(*args, **kwargs):
165+
return subprocess.CompletedProcess(args, returncode=0)
166+
167+
with (
168+
patch("subprocess.run", side_effect=patched_run),
169+
patch("shutil.which", return_value=None),
170+
):
158171
result = _install_tool("clang-format", "20.1.7")
159172
assert result is None
160173

0 commit comments

Comments
 (0)