Skip to content

Commit

Permalink
pipx install: emit a warning when --force and --python were pas…
Browse files Browse the repository at this point in the history
…sed at the same time (#899)

Co-authored-by: Bernát Gábor <[email protected]>
  • Loading branch information
dukecat0 and gaborbernat authored Nov 30, 2023
1 parent dd441b9 commit 51f78b7
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## dev

- `pipx install`: emit a warning when `--force` and `--python` were passed at the same time
- Drop support for Python 3.7
- Make usage message in `pipx run` show `package_or_url`, so extra will be printed out as well
- Add `--force-reinstall` to pip arguments when `--force` was passed
Expand Down
17 changes: 16 additions & 1 deletion src/pipx/commands/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from pipx import constants
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.interpreter import DEFAULT_PYTHON
from pipx.util import pipx_wrap
from pipx.venv import Venv, VenvContainer

Expand All @@ -13,19 +14,23 @@ def install(
package_name: Optional[str],
package_spec: str,
local_bin_dir: Path,
python: str,
python: Optional[str],
pip_args: List[str],
venv_args: List[str],
verbose: bool,
*,
force: bool,
reinstall: bool,
include_dependencies: bool,
preinstall_packages: Optional[List[str]],
suffix: str = "",
) -> ExitCode:
"""Returns pipx exit code."""
# package_spec is anything pip-installable, including package_name, vcs spec,
# zip file, or tar.gz file.
python_flag_was_passed = python is not None

python = python or DEFAULT_PYTHON

if package_name is None:
package_name = package_name_from_spec(
Expand All @@ -42,6 +47,16 @@ def install(

venv = Venv(venv_dir, python=python, verbose=verbose)
if exists:
if not reinstall and force and python_flag_was_passed:
print(
pipx_wrap(
f"""
--python is ignored when --force is passed.
If you want to reinstall {package_name} with {python},
run `pipx reinstall {package_spec} --python {python}` instead.
"""
)
)
if force:
print(f"Installing to existing venv {venv.name!r}")
pip_args += ["--force-reinstall"]
Expand Down
1 change: 1 addition & 0 deletions src/pipx/commands/reinstall.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ def reinstall(
venv.pipx_metadata.venv_args,
verbose,
force=True,
reinstall=True,
include_dependencies=venv.pipx_metadata.main_package.include_dependencies,
preinstall_packages=[],
suffix=venv.pipx_metadata.main_package.suffix,
Expand Down
3 changes: 2 additions & 1 deletion src/pipx/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ def run_pipx_command(args: argparse.Namespace) -> ExitCode: # noqa: C901
venv_args,
verbose,
force=args.force,
reinstall=False,
include_dependencies=args.include_deps,
preinstall_packages=args.preinstall,
suffix=args.suffix,
Expand Down Expand Up @@ -344,7 +345,7 @@ def _add_install(subparsers: argparse._SubParsersAction) -> None:
)
p.add_argument(
"--python",
default=DEFAULT_PYTHON,
# Don't pass a default Python here so we know whether --python flag was passed
help=(
"Python to install with. Possible values can be the executable name (python3.11), "
"the version to pass to py launcher (3.11), or the full path to the executable."
Expand Down
11 changes: 11 additions & 0 deletions tests/test_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,3 +284,14 @@ def test_preinstall(pipx_temp_env, caplog):
def test_do_not_wait_for_input(pipx_temp_env, pipx_session_shared_dir, monkeypatch):
monkeypatch.setenv("PIP_INDEX_URL", "http://127.0.0.1:8080/simple")
run_pipx_cli(["install", "pycowsay"])


def test_passed_python_and_force_flag_warning(pipx_temp_env, capsys):
assert not run_pipx_cli(["install", "black"])
assert not run_pipx_cli(["install", "--python", sys.executable, "--force", "black"])
captured = capsys.readouterr()
assert "--python is ignored when --force is passed." in captured.out

assert not run_pipx_cli(["install", "pycowsay", "--force"])
captured = capsys.readouterr()
assert "--python is ignored when --force is passed." not in captured.out

0 comments on commit 51f78b7

Please sign in to comment.