From c3ea2fd0c7213a3951c6ae23eacadd33a9864ea3 Mon Sep 17 00:00:00 2001 From: mcarton Date: Sun, 15 Nov 2015 16:55:07 +0100 Subject: [PATCH 1/3] Fix cache problem when going from Python 2 to 3 --- thefuck/utils.py | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/thefuck/utils.py b/thefuck/utils.py index b840b2a0..392f63fa 100644 --- a/thefuck/utils.py +++ b/thefuck/utils.py @@ -1,18 +1,17 @@ -from difflib import get_close_matches -from functools import wraps -import shelve -from warnings import warn -from decorator import decorator -from contextlib import closing - +import dbm import os import pickle -import re -from inspect import getargspec - -from pathlib import Path import pkg_resources +import re +import shelve from .conf import settings +from contextlib import closing +from decorator import decorator +from difflib import get_close_matches +from functools import wraps +from inspect import getargspec +from pathlib import Path +from warnings import warn DEVNULL = open(os.devnull, 'w') @@ -210,13 +209,24 @@ def cache(*depends_on): etag = '.'.join(_get_mtime(name) for name in depends_on) cache_path = _get_cache_path() - with closing(shelve.open(cache_path)) as db: - if db.get(key, {}).get('etag') == etag: - return db[key]['value'] - else: + try: + with closing(shelve.open(cache_path)) as db: + if db.get(key, {}).get('etag') == etag: + return db[key]['value'] + else: + value = fn(*args, **kwargs) + db[key] = {'etag': etag, 'value': value} + return value + except dbm.error: + # Caused when going from Python 2 to Python 3 + warn("Removing possibly out-dated cache") + os.remove(cache_path) + + with closing(shelve.open(cache_path)) as db: value = fn(*args, **kwargs) db[key] = {'etag': etag, 'value': value} return value + return _cache cache.disabled = False From 8feb722ed0b56d1eb973f06c3b60d5f9cd6ca3ef Mon Sep 17 00:00:00 2001 From: mcarton Date: Sun, 15 Nov 2015 18:02:37 +0100 Subject: [PATCH 2/3] Fix some pep8 warnings --- tests/rules/test_dirty_untar.py | 1 + tests/rules/test_mkdir_p.py | 9 ++-- tests/rules/test_mvn_no_command.py | 2 +- .../rules/test_mvn_unknown_lifecycle_phase.py | 2 +- tests/rules/test_no_such_file.py | 6 +-- tests/rules/test_rm_dir.py | 16 +++--- tests/rules/test_unknown_command.py | 5 +- tests/rules/test_vagrant_up.py | 5 +- tests/test_types.py | 1 - thefuck/rules/fix_file.py | 50 +++++++++---------- thefuck/rules/unknown_command.py | 2 +- thefuck/rules/vagrant_up.py | 2 +- thefuck/types.py | 2 +- 13 files changed, 51 insertions(+), 52 deletions(-) diff --git a/tests/rules/test_dirty_untar.py b/tests/rules/test_dirty_untar.py index 21579c8e..b33a8900 100644 --- a/tests/rules/test_dirty_untar.py +++ b/tests/rules/test_dirty_untar.py @@ -63,6 +63,7 @@ def test_side_effect(ext, tar_error, filename, unquoted, quoted, script, fixed): side_effect(Command(script=script.format(filename.format(ext))), None) assert set(os.listdir('.')) == {unquoted.format(ext), 'd'} + @parametrize_extensions @parametrize_filename @parametrize_script diff --git a/tests/rules/test_mkdir_p.py b/tests/rules/test_mkdir_p.py index 8d8a3bfe..39111b2c 100644 --- a/tests/rules/test_mkdir_p.py +++ b/tests/rules/test_mkdir_p.py @@ -7,7 +7,7 @@ from tests.utils import Command Command('mkdir foo/bar/baz', stderr='mkdir: foo/bar: No such file or directory'), Command('./bin/hdfs dfs -mkdir foo/bar/baz', stderr='mkdir: `foo/bar/baz\': No such file or directory'), Command('hdfs dfs -mkdir foo/bar/baz', stderr='mkdir: `foo/bar/baz\': No such file or directory') - ]) +]) def test_match(command): assert match(command) @@ -17,7 +17,8 @@ def test_match(command): Command('mkdir foo/bar/baz', stderr='foo bar baz'), Command('hdfs dfs -mkdir foo/bar/baz'), Command('./bin/hdfs dfs -mkdir foo/bar/baz'), - Command()]) + Command(), +]) def test_not_match(command): assert not match(command) @@ -25,7 +26,7 @@ def test_not_match(command): @pytest.mark.parametrize('command, new_command', [ (Command('mkdir foo/bar/baz'), 'mkdir -p foo/bar/baz'), (Command('hdfs dfs -mkdir foo/bar/baz'), 'hdfs dfs -mkdir -p foo/bar/baz'), - (Command('./bin/hdfs dfs -mkdir foo/bar/baz'), './bin/hdfs dfs -mkdir -p foo/bar/baz')]) + (Command('./bin/hdfs dfs -mkdir foo/bar/baz'), './bin/hdfs dfs -mkdir -p foo/bar/baz'), +]) def test_get_new_command(command, new_command): assert get_new_command(command) == new_command - diff --git a/tests/rules/test_mvn_no_command.py b/tests/rules/test_mvn_no_command.py index 1bb57d87..1871716c 100644 --- a/tests/rules/test_mvn_no_command.py +++ b/tests/rules/test_mvn_no_command.py @@ -32,9 +32,9 @@ def test_match(command): def test_not_match(command): assert not match(command) + @pytest.mark.parametrize('command, new_command', [ (Command(script='mvn', stdout='[ERROR] No goals have been specified for this build. You must specify a valid lifecycle phase or a goal in the format : or :[:]:. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]'), ['mvn clean package', 'mvn clean install']), (Command(script='mvn -N', stdout='[ERROR] No goals have been specified for this build. You must specify a valid lifecycle phase or a goal in the format : or :[:]:. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]'), ['mvn -N clean package', 'mvn -N clean install'])]) def test_get_new_command(command, new_command): assert get_new_command(command) == new_command - diff --git a/tests/rules/test_mvn_unknown_lifecycle_phase.py b/tests/rules/test_mvn_unknown_lifecycle_phase.py index 0c2b1a17..c4b4b7a5 100644 --- a/tests/rules/test_mvn_unknown_lifecycle_phase.py +++ b/tests/rules/test_mvn_unknown_lifecycle_phase.py @@ -32,9 +32,9 @@ def test_match(command): def test_not_match(command): assert not match(command) + @pytest.mark.parametrize('command, new_command', [ (Command(script='mvn cle', stdout='[ERROR] Unknown lifecycle phase "cle". You must specify a valid lifecycle phase or a goal in the format : or :[:]:. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]'), ['mvn clean', 'mvn compile']), (Command(script='mvn claen package', stdout='[ERROR] Unknown lifecycle phase "claen". You must specify a valid lifecycle phase or a goal in the format : or :[:]:. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]'), ['mvn clean package'])]) def test_get_new_command(command, new_command): assert get_new_command(command) == new_command - diff --git a/tests/rules/test_no_such_file.py b/tests/rules/test_no_such_file.py index 0735cd6b..169882e5 100644 --- a/tests/rules/test_no_such_file.py +++ b/tests/rules/test_no_such_file.py @@ -6,7 +6,7 @@ from tests.utils import Command @pytest.mark.parametrize('command', [ Command(script='mv foo bar/foo', stderr="mv: cannot move 'foo' to 'bar/foo': No such file or directory"), Command(script='mv foo bar/', stderr="mv: cannot move 'foo' to 'bar/': No such file or directory"), - ]) +]) def test_match(command): assert match(command) @@ -14,7 +14,7 @@ def test_match(command): @pytest.mark.parametrize('command', [ Command(script='mv foo bar/', stderr=""), Command(script='mv foo bar/foo', stderr="mv: permission denied"), - ]) +]) def test_not_match(command): assert not match(command) @@ -22,6 +22,6 @@ def test_not_match(command): @pytest.mark.parametrize('command, new_command', [ (Command(script='mv foo bar/foo', stderr="mv: cannot move 'foo' to 'bar/foo': No such file or directory"), 'mkdir -p bar && mv foo bar/foo'), (Command(script='mv foo bar/', stderr="mv: cannot move 'foo' to 'bar/': No such file or directory"), 'mkdir -p bar && mv foo bar/'), - ]) +]) def test_get_new_command(command, new_command): assert get_new_command(command) == new_command diff --git a/tests/rules/test_rm_dir.py b/tests/rules/test_rm_dir.py index 65b41bd6..69ec42a3 100644 --- a/tests/rules/test_rm_dir.py +++ b/tests/rules/test_rm_dir.py @@ -7,25 +7,25 @@ from tests.utils import Command Command('rm foo', stderr='rm: foo: is a directory'), Command('rm foo', stderr='rm: foo: Is a directory'), Command('hdfs dfs -rm foo', stderr='rm: `foo`: Is a directory'), - Command('./bin/hdfs dfs -rm foo', stderr='rm: `foo`: Is a directory') - ]) + Command('./bin/hdfs dfs -rm foo', stderr='rm: `foo`: Is a directory'), +]) def test_match(command): assert match(command) @pytest.mark.parametrize('command', [ - Command('rm foo'), + Command('rm foo'), Command('hdfs dfs -rm foo'), - Command('./bin/hdfs dfs -rm foo'), - Command()]) + Command('./bin/hdfs dfs -rm foo'), + Command(), +]) def test_not_match(command): assert not match(command) @pytest.mark.parametrize('command, new_command', [ (Command('rm foo'), 'rm -rf foo'), - (Command('hdfs dfs -rm foo'), 'hdfs dfs -rm -r foo')]) + (Command('hdfs dfs -rm foo'), 'hdfs dfs -rm -r foo'), +]) def test_get_new_command(command, new_command): assert get_new_command(command) == new_command - - diff --git a/tests/rules/test_unknown_command.py b/tests/rules/test_unknown_command.py index 3416b33a..9a2d37e7 100644 --- a/tests/rules/test_unknown_command.py +++ b/tests/rules/test_unknown_command.py @@ -14,8 +14,8 @@ def test_match(command): @pytest.mark.parametrize('command', [ Command(script='./bin/hdfs dfs -ls', stderr=''), - Command(script='./bin/hdfs dfs -ls /foo/bar', stderr=''), - Command(script='hdfs dfs -ls -R /foo/bar', stderr=''), + Command(script='./bin/hdfs dfs -ls /foo/bar', stderr=''), + Command(script='hdfs dfs -ls -R /foo/bar', stderr=''), Command()]) def test_not_match(command): assert not match(command) @@ -32,4 +32,3 @@ def test_not_match(command): stderr='ls: Unknown command\nDid you mean -ls? This command begins with a dash.'), ['./bin/hdfs dfs -Dtest=fred -ls -R /foo/bar'])]) def test_get_new_command(command, new_command): assert get_new_command(command) == new_command - diff --git a/tests/rules/test_vagrant_up.py b/tests/rules/test_vagrant_up.py index 66f2ebfa..19d7b335 100644 --- a/tests/rules/test_vagrant_up.py +++ b/tests/rules/test_vagrant_up.py @@ -16,8 +16,8 @@ def test_match(command): @pytest.mark.parametrize('command', [ Command(script='vagrant ssh', stderr=''), - Command(script='vagrant ssh jeff', stderr='The machine with the name \'jeff\' was not found configured for this Vagrant environment.'), - Command(script='vagrant ssh', stderr='A Vagrant environment or target machine is required to run this command. Run `vagrant init` to create a new Vagrant environment. Or, get an ID of a target machine from `vagrant global-status` to run this command on. A final option is to change to a directory with a Vagrantfile and to try again.'), + Command(script='vagrant ssh jeff', stderr='The machine with the name \'jeff\' was not found configured for this Vagrant environment.'), + Command(script='vagrant ssh', stderr='A Vagrant environment or target machine is required to run this command. Run `vagrant init` to create a new Vagrant environment. Or, get an ID of a target machine from `vagrant global-status` to run this command on. A final option is to change to a directory with a Vagrantfile and to try again.'), Command()]) def test_not_match(command): assert not match(command) @@ -32,4 +32,3 @@ def test_not_match(command): stderr='VM must be created before running this command. Run `vagrant up` first.'), ['vagrant up devbox && vagrant rdp devbox', 'vagrant up && vagrant rdp devbox'])]) def test_get_new_command(command, new_command): assert get_new_command(command) == new_command - diff --git a/tests/test_types.py b/tests/test_types.py index 5fb28dea..54452a0a 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -122,4 +122,3 @@ class TestCommand(object): else: with pytest.raises(EmptyCommand): Command.from_raw_script(script) - diff --git a/thefuck/rules/fix_file.py b/thefuck/rules/fix_file.py index 7177c270..13a46b3b 100644 --- a/thefuck/rules/fix_file.py +++ b/thefuck/rules/fix_file.py @@ -7,31 +7,31 @@ from thefuck import shells # order is important: only the first match is considered patterns = ( - # js, node: - '^ at {file}:{line}:{col}', - # cargo: - '^ {file}:{line}:{col}', - # python, thefuck: - '^ File "{file}", line {line}', - # awk: - '^awk: {file}:{line}:', - # git - '^fatal: bad config file line {line} in {file}', - # llc: - '^llc: {file}:{line}:{col}:', - # lua: - '^lua: {file}:{line}:', - # fish: - '^{file} \\(line {line}\\):', - # bash, sh, ssh: - '^{file}: line {line}: ', - # cargo, clang, gcc, go, pep8, rustc: - '^{file}:{line}:{col}', - # ghc, make, ruby, zsh: - '^{file}:{line}:', - # perl: - 'at {file} line {line}', - ) + # js, node: + '^ at {file}:{line}:{col}', + # cargo: + '^ {file}:{line}:{col}', + # python, thefuck: + '^ File "{file}", line {line}', + # awk: + '^awk: {file}:{line}:', + # git + '^fatal: bad config file line {line} in {file}', + # llc: + '^llc: {file}:{line}:{col}:', + # lua: + '^lua: {file}:{line}:', + # fish: + '^{file} \\(line {line}\\):', + # bash, sh, ssh: + '^{file}: line {line}: ', + # cargo, clang, gcc, go, pep8, rustc: + '^{file}:{line}:{col}', + # ghc, make, ruby, zsh: + '^{file}:{line}:', + # perl: + 'at {file} line {line}', +) # for the sake of readability do not use named groups above diff --git a/thefuck/rules/unknown_command.py b/thefuck/rules/unknown_command.py index c0048cc1..ee7139e2 100644 --- a/thefuck/rules/unknown_command.py +++ b/thefuck/rules/unknown_command.py @@ -1,6 +1,7 @@ import re from thefuck.utils import replace_command + def match(command): return (re.search(r"([^:]*): Unknown command.*", command.stderr) != None and re.search(r"Did you mean ([^?]*)?", command.stderr) != None) @@ -10,4 +11,3 @@ def get_new_command(command): broken_cmd = re.findall(r"([^:]*): Unknown command.*", command.stderr)[0] matched = re.findall(r"Did you mean ([^?]*)?", command.stderr) return replace_command(command, broken_cmd, matched) - diff --git a/thefuck/rules/vagrant_up.py b/thefuck/rules/vagrant_up.py index 04610a0e..d166bec1 100644 --- a/thefuck/rules/vagrant_up.py +++ b/thefuck/rules/vagrant_up.py @@ -17,4 +17,4 @@ def get_new_command(command): if machine is None: return startAllInstances else: - return [ shells.and_("vagrant up " + machine, command.script), startAllInstances] + return [shells.and_("vagrant up " + machine, command.script), startAllInstances] diff --git a/thefuck/types.py b/thefuck/types.py index 7abd1a6f..a2cd9623 100644 --- a/thefuck/types.py +++ b/thefuck/types.py @@ -269,7 +269,7 @@ class CorrectedCommand(object): def __repr__(self): return 'CorrectedCommand(script={}, side_effect={}, priority={})'.format( self.script, self.side_effect, self.priority) - + def run(self, old_cmd): """Runs command from rule for passed command. From 7c5676491a01c4608c09118a7d3bb706cc5498e5 Mon Sep 17 00:00:00 2001 From: mcarton Date: Sun, 15 Nov 2015 18:08:59 +0100 Subject: [PATCH 3/3] Fix some more warnings from flake8 --- tests/rules/test_ssh_known_host.py | 1 - tests/rules/test_systemctl.py | 1 - tests/specific/test_sudo.py | 1 - tests/test_logs.py | 1 - thefuck/specific/sudo.py | 1 - 5 files changed, 5 deletions(-) diff --git a/tests/rules/test_ssh_known_host.py b/tests/rules/test_ssh_known_host.py index d713acc5..f2828a37 100644 --- a/tests/rules/test_ssh_known_host.py +++ b/tests/rules/test_ssh_known_host.py @@ -1,6 +1,5 @@ import os import pytest -from mock import Mock from thefuck.rules.ssh_known_hosts import match, get_new_command,\ side_effect from tests.utils import Command diff --git a/tests/rules/test_systemctl.py b/tests/rules/test_systemctl.py index c16b1eb4..eb9a270b 100644 --- a/tests/rules/test_systemctl.py +++ b/tests/rules/test_systemctl.py @@ -1,4 +1,3 @@ -import pytest from thefuck.rules.systemctl import match, get_new_command from tests.utils import Command diff --git a/tests/specific/test_sudo.py b/tests/specific/test_sudo.py index bbc3d360..2b99eb72 100644 --- a/tests/specific/test_sudo.py +++ b/tests/specific/test_sudo.py @@ -1,5 +1,4 @@ import pytest -from mock import Mock from thefuck.specific.sudo import sudo_support from tests.utils import Command diff --git a/tests/test_logs.py b/tests/test_logs.py index 4b585ee4..59aefd22 100644 --- a/tests/test_logs.py +++ b/tests/test_logs.py @@ -1,5 +1,4 @@ import pytest -from mock import Mock from thefuck import logs diff --git a/thefuck/specific/sudo.py b/thefuck/specific/sudo.py index 9941183c..ddc6d409 100644 --- a/thefuck/specific/sudo.py +++ b/thefuck/specific/sudo.py @@ -1,6 +1,5 @@ import six from decorator import decorator -from ..types import Command @decorator