Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #430 from nvbn/429-apt-invalid-operation
#429: Add `apt_invalid_operation` rule
- Loading branch information
Showing
3 changed files
with
176 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
from io import BytesIO | ||
import pytest | ||
from tests.utils import Command | ||
from thefuck.rules.apt_invalid_operation import match, get_new_command, \ | ||
_get_operations | ||
|
||
invalid_operation = 'E: Invalid operation {}'.format | ||
apt_help = b'''apt 1.0.10.2ubuntu1 for amd64 compiled on Oct 5 2015 15:55:05 | ||
Usage: apt [options] command | ||
CLI for apt. | ||
Basic commands: | ||
list - list packages based on package names | ||
search - search in package descriptions | ||
show - show package details | ||
update - update list of available packages | ||
install - install packages | ||
remove - remove packages | ||
upgrade - upgrade the system by installing/upgrading packages | ||
full-upgrade - upgrade the system by removing/installing/upgrading packages | ||
edit-sources - edit the source information file | ||
''' | ||
apt_operations = ['list', 'search', 'show', 'update', 'install', 'remove', | ||
'upgrade', 'full-upgrade', 'edit-sources'] | ||
|
||
apt_get_help = b'''apt 1.0.10.2ubuntu1 for amd64 compiled on Oct 5 2015 15:55:05 | ||
Usage: apt-get [options] command | ||
apt-get [options] install|remove pkg1 [pkg2 ...] | ||
apt-get [options] source pkg1 [pkg2 ...] | ||
apt-get is a simple command line interface for downloading and | ||
installing packages. The most frequently used commands are update | ||
and install. | ||
Commands: | ||
update - Retrieve new lists of packages | ||
upgrade - Perform an upgrade | ||
install - Install new packages (pkg is libc6 not libc6.deb) | ||
remove - Remove packages | ||
autoremove - Remove automatically all unused packages | ||
purge - Remove packages and config files | ||
source - Download source archives | ||
build-dep - Configure build-dependencies for source packages | ||
dist-upgrade - Distribution upgrade, see apt-get(8) | ||
dselect-upgrade - Follow dselect selections | ||
clean - Erase downloaded archive files | ||
autoclean - Erase old downloaded archive files | ||
check - Verify that there are no broken dependencies | ||
changelog - Download and display the changelog for the given package | ||
download - Download the binary package into the current directory | ||
Options: | ||
-h This help text. | ||
-q Loggable output - no progress indicator | ||
-qq No output except for errors | ||
-d Download only - do NOT install or unpack archives | ||
-s No-act. Perform ordering simulation | ||
-y Assume Yes to all queries and do not prompt | ||
-f Attempt to correct a system with broken dependencies in place | ||
-m Attempt to continue if archives are unlocatable | ||
-u Show a list of upgraded packages as well | ||
-b Build the source package after fetching it | ||
-V Show verbose version numbers | ||
-c=? Read this configuration file | ||
-o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp | ||
See the apt-get(8), sources.list(5) and apt.conf(5) manual | ||
pages for more information and options. | ||
This APT has Super Cow Powers. | ||
''' | ||
apt_get_operations = ['update', 'upgrade', 'install', 'remove', 'autoremove', | ||
'purge', 'source', 'build-dep', 'dist-upgrade', | ||
'dselect-upgrade', 'clean', 'autoclean', 'check', | ||
'changelog', 'download'] | ||
|
||
|
||
@pytest.mark.parametrize('script, stderr', [ | ||
('apt', invalid_operation('saerch')), | ||
('apt-get', invalid_operation('isntall')), | ||
('apt-cache', invalid_operation('rumove'))]) | ||
def test_match(script, stderr): | ||
assert match(Command(script, stderr=stderr)) | ||
|
||
|
||
@pytest.mark.parametrize('script, stderr', [ | ||
('vim', invalid_operation('vim')), | ||
('apt-get', "")]) | ||
def test_not_match(script, stderr): | ||
assert not match(Command(script, stderr=stderr)) | ||
|
||
|
||
@pytest.fixture | ||
def set_help(mocker): | ||
mock = mocker.patch('subprocess.Popen') | ||
|
||
def _set_text(text): | ||
mock.return_value.stdout = BytesIO(text) | ||
|
||
return _set_text | ||
|
||
|
||
@pytest.mark.parametrize('app, help_text, operations', [ | ||
('apt', apt_help, apt_operations), | ||
('apt-get', apt_get_help, apt_get_operations) | ||
]) | ||
def test_get_operations(set_help, app, help_text, operations): | ||
set_help(help_text) | ||
assert _get_operations(app) == operations | ||
|
||
|
||
@pytest.mark.parametrize('script, stderr, help_text, result', [ | ||
('apt-get isntall vim', invalid_operation('isntall'), | ||
apt_get_help, 'apt-get install vim'), | ||
('apt saerch vim', invalid_operation('saerch'), | ||
apt_help, 'apt search vim'), | ||
]) | ||
def test_get_new_command(set_help, stderr, script, help_text, result): | ||
set_help(help_text) | ||
assert get_new_command(Command(script, stderr=stderr))[0] == result |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import subprocess | ||
from thefuck.specific.sudo import sudo_support | ||
from thefuck.utils import for_app, eager, replace_command | ||
|
||
|
||
@for_app('apt', 'apt-get', 'apt-cache') | ||
@sudo_support | ||
def match(command): | ||
return 'E: Invalid operation' in command.stderr | ||
|
||
|
||
@eager | ||
def _parse_apt_operations(help_text_lines): | ||
is_commands_list = False | ||
for line in help_text_lines: | ||
line = line.decode().strip() | ||
if is_commands_list and line: | ||
yield line.split()[0] | ||
elif line.startswith('Basic commands:'): | ||
is_commands_list = True | ||
|
||
|
||
@eager | ||
def _parse_apt_get_and_cache_operations(help_text_lines): | ||
is_commands_list = False | ||
for line in help_text_lines: | ||
line = line.decode().strip() | ||
if is_commands_list: | ||
if not line: | ||
return | ||
|
||
yield line.split()[0] | ||
elif line.startswith('Commands:'): | ||
is_commands_list = True | ||
|
||
|
||
def _get_operations(app): | ||
proc = subprocess.Popen([app, '--help'], | ||
stdout=subprocess.PIPE, | ||
stderr=subprocess.PIPE) | ||
lines = proc.stdout.readlines() | ||
|
||
if app == 'apt': | ||
return _parse_apt_operations(lines) | ||
else: | ||
return _parse_apt_get_and_cache_operations(lines) | ||
|
||
|
||
@sudo_support | ||
def get_new_command(command): | ||
invalid_operation = command.stderr.split()[-1] | ||
operations = _get_operations(command.script_parts[0]) | ||
return replace_command(command, invalid_operation, operations) |