diff --git a/CHANGELOG.md b/CHANGELOG.md index 82c84c4bbc..21a8ff2d1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## 1.4.1 - Set default logging level to WARNING, so debug log messages won't be shown without passing additional flags such as `--verbose` +- Raise more user friendly error when provided `--python` version is not found. ## 1.4.0 diff --git a/src/pipx/commands/install.py b/src/pipx/commands/install.py index 8e84bd309f..6b34f53862 100644 --- a/src/pipx/commands/install.py +++ b/src/pipx/commands/install.py @@ -1,9 +1,14 @@ from pathlib import Path from typing import List, Optional -from pipx import constants +from pipx import constants, emojis from pipx.commands.common import package_name_from_spec, run_post_install_actions -from pipx.constants import EXIT_CODE_INSTALL_VENV_EXISTS, EXIT_CODE_OK, ExitCode +from pipx.constants import ( + EXIT_CODE_INSTALL_VENV_EXISTS, + EXIT_CODE_OK, + EXIT_CODE_SPECIFIED_PYTHON_EXECUTABLE_NOT_FOUND, + ExitCode, +) from pipx.interpreter import DEFAULT_PYTHON from pipx.util import pipx_wrap from pipx.venv import Venv, VenvContainer @@ -102,6 +107,23 @@ def install( include_dependencies, force=force, ) + except FileNotFoundError as e: + venv.remove_venv() + if python in str(e) or "The system cannot find the file specified" in str(e): + print( + pipx_wrap( + f""" + {emojis.hazard} No executable for the provided Python version '{python}' found. + Please make sure the executable name is on your PATH / + the path to the executable is correct. + """, + subsequent_indent=" " * 4, + ) + ) + return EXIT_CODE_SPECIFIED_PYTHON_EXECUTABLE_NOT_FOUND + else: + print() + raise except (Exception, KeyboardInterrupt): print() venv.remove_venv() diff --git a/src/pipx/constants.py b/src/pipx/constants.py index dbe3a707cc..8aba427efd 100644 --- a/src/pipx/constants.py +++ b/src/pipx/constants.py @@ -46,6 +46,7 @@ EXIT_CODE_UNINSTALL_ERROR = ExitCode(1) EXIT_CODE_REINSTALL_VENV_NONEXISTENT = ExitCode(1) EXIT_CODE_REINSTALL_INVALID_PYTHON = ExitCode(1) +EXIT_CODE_SPECIFIED_PYTHON_EXECUTABLE_NOT_FOUND = ExitCode(1) pipx_log_file: Optional[Path] = None diff --git a/tests/test_install.py b/tests/test_install.py index b814b736a0..a1a43f5c2f 100644 --- a/tests/test_install.py +++ b/tests/test_install.py @@ -337,3 +337,9 @@ def test_passed_python_and_force_flag_warning(pipx_temp_env, capsys): assert not run_pipx_cli(["install", "pycowsay", "--force"]) captured = capsys.readouterr() assert "--python is ignored when --force is passed." not in captured.out + + +def test_passed_python_not_executable(pipx_temp_env, capsys): + assert run_pipx_cli(["install", "--python", "py_not_real", "pycowsay"]) + captured = capsys.readouterr() + assert "No executable for the provided Python version" in captured.out