diff --git a/README.md b/README.md index bb1d8df2..55ef2b32 100644 --- a/README.md +++ b/README.md @@ -266,6 +266,7 @@ following rules are enabled by default: * `no_command` – fixes wrong console commands, for example `vom/vim`; * `no_such_file` – creates missing directories with `mv` and `cp` commands; * `open` – either prepends `http://` to address passed to `open` or create a new file or directory and passes it to `open`; +* `pip_install` – fixes permission issues with `pip install` commands by adding `--user` or prepending `sudo` if necessary; * `pip_unknown_command` – fixes wrong `pip` commands, for example `pip instatl/pip install`; * `php_s` – replaces `-s` by `-S` when trying to run a local php server; * `port_already_in_use` – kills process that bound port; diff --git a/tests/rules/test_pip_install.py b/tests/rules/test_pip_install.py new file mode 100644 index 00000000..c920b7cc --- /dev/null +++ b/tests/rules/test_pip_install.py @@ -0,0 +1,27 @@ +# -*- coding: UTF-8 -*- +from thefuck.rules.pip_install import match, get_new_command +from thefuck.types import Command + + +def test_match(): + response1 = """ + Could not install packages due to an EnvironmentError: [Errno 13] Permission denied: '/Library/Python/2.7/site-packages/entrypoints.pyc' +Consider using the `--user` option or check the permissions. +""" + assert match(Command('pip install -r requirements.txt', response1)) + + response2 = """ +Collecting bacon + Downloading https://files.pythonhosted.org/packages/b2/81/19fb79139ee71c8bc4e5a444546f318e2b87253b8939ec8a7e10d63b7341/bacon-0.3.1.zip (11.0MB) + 100% |████████████████████████████████| 11.0MB 3.0MB/s +Installing collected packages: bacon + Running setup.py install for bacon ... done +Successfully installed bacon-0.3.1 +""" + assert not match(Command('pip install bacon', response2)) + + +def test_get_new_command(): + assert get_new_command(Command('pip install -r requirements.txt', '')) == 'pip install --user -r requirements.txt' + assert get_new_command(Command('pip install bacon', '')) == 'pip install --user bacon' + assert get_new_command(Command('pip install --user -r requirements.txt', '')) == 'sudo pip install -r requirements.txt' diff --git a/thefuck/rules/pip_install.py b/thefuck/rules/pip_install.py new file mode 100644 index 00000000..8ee013c0 --- /dev/null +++ b/thefuck/rules/pip_install.py @@ -0,0 +1,15 @@ +from thefuck.utils import for_app +from thefuck.specific.sudo import sudo_support + + +@sudo_support +@for_app('pip') +def match(command): + return ('pip install' in command.script and 'Permission denied' in command.output) + + +def get_new_command(command): + if '--user' not in command.script: # add --user (attempt 1) + return command.script.replace(' install ', ' install --user ') + + return 'sudo {}'.format(command.script.replace(' --user', '')) # since --user didn't fix things, let's try sudo (attempt 2)