diff --git a/src/pipgrip/cli.py b/src/pipgrip/cli.py index b70f192..636db95 100755 --- a/src/pipgrip/cli.py +++ b/src/pipgrip/cli.py @@ -52,7 +52,12 @@ from pipgrip.libs.mixology.package import Package from pipgrip.libs.mixology.version_solver import VersionSolver from pipgrip.package_source import PackageSource, render_pin -from pipgrip.pipper import install_packages, read_requirements +from pipgrip.pipper import ( + BUILD_FAILURE_STR, + REPORT_FAILURE_STR, + install_packages, + read_requirements, +) logging.basicConfig(format="%(levelname)s: %(message)s") logger = logging.getLogger() @@ -479,7 +484,7 @@ def main( exc = None except RuntimeError as e: # RuntimeError coming from pipgrip.pipper - if "Failed to download/build wheel" not in str(e): + if REPORT_FAILURE_STR not in str(e) and BUILD_FAILURE_STR not in str(e): # only continue handling expected RuntimeErrors raise solution = solver.solution diff --git a/src/pipgrip/pipper.py b/src/pipgrip/pipper.py index c2e291d..b503066 100644 --- a/src/pipgrip/pipper.py +++ b/src/pipgrip/pipper.py @@ -49,6 +49,10 @@ logger = logging.getLogger(__name__) +REPORT_FAILURE_STR = "Failed to get report for" +BUILD_FAILURE_STR = "Failed to download/build wheel for" +VERSIONS_FAILURE_STR = "Failed to get available versions for" + def read_requirements(path): re_comments = re.compile(r"(?:^|\s+)#") @@ -292,7 +296,7 @@ def _get_available_versions(package, index_url, extra_index_url, pre): ] _available_versions_cache[cache_key] = available_versions return available_versions - raise RuntimeError("Failed to get available versions for {}".format(package)) + raise RuntimeError("{} {}".format(VERSIONS_FAILURE_STR, package)) def _get_package_report( @@ -357,7 +361,7 @@ def _get_package_report( package, output.strip() ) ) - raise RuntimeError("Failed to get report for {}".format(package)) + raise RuntimeError("{} {}".format(REPORT_FAILURE_STR, package)) else: with io.open(report_file, "r", encoding="utf-8") as fp: return json.load(fp) @@ -397,7 +401,7 @@ def _download_wheel( package, output.strip() ) ) - raise RuntimeError("Failed to download/build wheel for {}".format(package)) + raise RuntimeError("{} {}".format(BUILD_FAILURE_STR, package)) out = out.splitlines()[::-1] abs_wheel_dir_lower = abs_wheel_dir.lower() cwd_wheel_dir_lower = cwd_wheel_dir.lower() @@ -474,7 +478,7 @@ def _download_wheel( "\n".join(out[::-1]) ) ) - raise RuntimeError("Failed to download/build wheel for {}".format(package)) + raise RuntimeError("{} {}".format(BUILD_FAILURE_STR, package)) def _extract_metadata(wheel_fname): diff --git a/tests/test_cli.py b/tests/test_cli.py index cb8fa37..294287a 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -30,6 +30,9 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # SPDX-License-Identifier: BSD-3-Clause +import logging +import subprocess + import pytest from click.testing import CliRunner @@ -141,7 +144,13 @@ def mock_stream_bash_command(*args, **kwargs): return "I passed" -def invoke_patched(func, arguments, monkeypatch, use_report=False, **kwargs): +def mock_stream_bash_command_failure(*args, **kwargs): + raise subprocess.CalledProcessError(1, args[0]) + + +def invoke_patched( + func, arguments, monkeypatch, use_report=False, mock_failure=False, **kwargs +): def default_environment(): return { "implementation_name": "cpython", @@ -157,16 +166,28 @@ def default_environment(): "sys_platform": "linux", } - monkeypatch.setattr( - pipgrip.pipper, - "_download_wheel", - mock_download_wheel, - ) - monkeypatch.setattr( - pipgrip.pipper, - "_get_package_report", - mock_get_package_report, - ) + if mock_failure: + monkeypatch.setattr( + pipgrip.pipper, + "stream_bash_command", + mock_stream_bash_command_failure, + ) + else: + monkeypatch.setattr( + pipgrip.pipper, + "stream_bash_command", + mock_stream_bash_command, + ) + monkeypatch.setattr( + pipgrip.pipper, + "_download_wheel", + mock_download_wheel, + ) + monkeypatch.setattr( + pipgrip.pipper, + "_get_package_report", + mock_get_package_report, + ) if use_report: monkeypatch.setattr( pipgrip.pipper, @@ -189,11 +210,6 @@ def default_environment(): "default_environment", default_environment, ) - monkeypatch.setattr( - pipgrip.pipper, - "stream_bash_command", - mock_stream_bash_command, - ) runner = CliRunner() return runner.invoke(main, arguments, **kwargs) @@ -426,6 +442,24 @@ def test_solutions(arguments, expected, monkeypatch): ), "Unexpected output:\n{}".format(result.output.strip()) +def test_failue_build(monkeypatch, caplog): + caplog.set_level(logging.DEBUG) + arguments = ["requests[socks]"] + result = invoke_patched(main, arguments, monkeypatch, mock_failure=True) + assert result.exit_code + assert "Best guess" in caplog.text + + +def test_failue_report(monkeypatch, caplog): + caplog.set_level(logging.DEBUG) + arguments = ["requests[socks]"] + result = invoke_patched( + main, arguments, monkeypatch, use_report=True, mock_failure=True + ) + assert result.exit_code + assert "Best guess" in caplog.text + + @pytest.mark.parametrize( "arguments", [