1
0
mirror of https://github.com/nvbn/thefuck.git synced 2025-04-19 01:00:42 +01:00

Add support for stdout in the fix_file rule

At least `pep8` and `py.test` consider errors as normal and print them
on stdout.
This commit is contained in:
mcarton 2015-08-17 14:11:06 +02:00
parent 7f0f9a966f
commit 4a2f869c6d
2 changed files with 62 additions and 34 deletions

View File

@ -4,9 +4,9 @@ from thefuck.rules.fix_file import match, get_new_command
from tests.utils import Command from tests.utils import Command
# (script, file, line, col (or None), stderr) # (script, file, line, col (or None), stdout, stderr)
tests = ( tests = (
('gcc a.c', 'a.c', 3, 1, ('gcc a.c', 'a.c', 3, 1, '',
""" """
a.c: In function 'main': a.c: In function 'main':
a.c:3:1: error: expected expression before '}' token a.c:3:1: error: expected expression before '}' token
@ -14,47 +14,47 @@ a.c:3:1: error: expected expression before '}' token
^ ^
"""), """),
('clang a.c', 'a.c', 3, 1, ('clang a.c', 'a.c', 3, 1, '',
""" """
a.c:3:1: error: expected expression a.c:3:1: error: expected expression
} }
^ ^
"""), """),
('perl a.pl', 'a.pl', 3, None, ('perl a.pl', 'a.pl', 3, None, '',
""" """
syntax error at a.pl line 3, at EOF syntax error at a.pl line 3, at EOF
Execution of a.pl aborted due to compilation errors. Execution of a.pl aborted due to compilation errors.
"""), """),
('perl a.pl', 'a.pl', 2, None, ('perl a.pl', 'a.pl', 2, None, '',
""" """
Search pattern not terminated at a.pl line 2. Search pattern not terminated at a.pl line 2.
"""), """),
('sh a.sh', 'a.sh', 2, None, ('sh a.sh', 'a.sh', 2, None, '',
""" """
a.sh: line 2: foo: command not found a.sh: line 2: foo: command not found
"""), """),
('zsh a.sh', 'a.sh', 2, None, ('zsh a.sh', 'a.sh', 2, None, '',
""" """
a.sh:2: command not found: foo a.sh:2: command not found: foo
"""), """),
('bash a.sh', 'a.sh', 2, None, ('bash a.sh', 'a.sh', 2, None, '',
""" """
a.sh: line 2: foo: command not found a.sh: line 2: foo: command not found
"""), """),
('rustc a.rs', 'a.rs', 2, 5, ('rustc a.rs', 'a.rs', 2, 5, '',
""" """
a.rs:2:5: 2:6 error: unexpected token: `+` a.rs:2:5: 2:6 error: unexpected token: `+`
a.rs:2 + a.rs:2 +
^ ^
"""), """),
('cargo build', 'src/lib.rs', 3, 5, ('cargo build', 'src/lib.rs', 3, 5, '',
""" """
Compiling test v0.1.0 (file:///tmp/fix-error/test) Compiling test v0.1.0 (file:///tmp/fix-error/test)
src/lib.rs:3:5: 3:6 error: unexpected token: `+` src/lib.rs:3:5: 3:6 error: unexpected token: `+`
@ -65,7 +65,7 @@ Could not compile `test`.
To learn more, run the command again with --verbose. To learn more, run the command again with --verbose.
"""), """),
('python a.py', 'a.py', 2, None, ('python a.py', 'a.py', 2, None, '',
""" """
File "a.py", line 2 File "a.py", line 2
+ +
@ -73,7 +73,7 @@ To learn more, run the command again with --verbose.
SyntaxError: invalid syntax SyntaxError: invalid syntax
"""), """),
('python a.py', 'a.py', 8, None, ('python a.py', 'a.py', 8, None, '',
""" """
Traceback (most recent call last): Traceback (most recent call last):
File "a.py", line 8, in <module> File "a.py", line 8, in <module>
@ -87,43 +87,43 @@ Traceback (most recent call last):
TypeError: first argument must be string or compiled pattern TypeError: first argument must be string or compiled pattern
"""), """),
('ruby a.rb', 'a.rb', 3, None, ('ruby a.rb', 'a.rb', 3, None, '',
""" """
a.rb:3: syntax error, unexpected keyword_end a.rb:3: syntax error, unexpected keyword_end
"""), """),
('lua a.lua', 'a.lua', 2, None, ('lua a.lua', 'a.lua', 2, None, '',
""" """
lua: a.lua:2: unexpected symbol near '+' lua: a.lua:2: unexpected symbol near '+'
"""), """),
('fish a.sh', '/tmp/fix-error/a.sh', 2, None, ('fish a.sh', '/tmp/fix-error/a.sh', 2, None, '',
""" """
fish: Unknown command 'foo' fish: Unknown command 'foo'
/tmp/fix-error/a.sh (line 2): foo /tmp/fix-error/a.sh (line 2): foo
^ ^
"""), """),
('./a', './a', 2, None, ('./a', './a', 2, None, '',
""" """
awk: ./a:2: BEGIN { print "Hello, world!" + } awk: ./a:2: BEGIN { print "Hello, world!" + }
awk: ./a:2: ^ syntax error awk: ./a:2: ^ syntax error
"""), """),
('llc a.ll', 'a.ll', 1, None, ('llc a.ll', 'a.ll', 1, None, '',
""" """
llc: a.ll:1:1: error: expected top-level entity llc: a.ll:1:1: error: expected top-level entity
+ +
^ ^
"""), """),
('go build a.go', 'a.go', 1, None, ('go build a.go', 'a.go', 1, None, '',
""" """
can't load package: can't load package:
a.go:1:1: expected 'package', found '+' a.go:1:1: expected 'package', found '+'
"""), """),
('make', 'Makefile', 2, None, ('make', 'Makefile', 2, None, '',
""" """
bidule bidule
make: bidule: Command not found make: bidule: Command not found
@ -131,12 +131,12 @@ Makefile:2: recipe for target 'target' failed
make: *** [target] Error 127 make: *** [target] Error 127
"""), """),
('git st', '/home/martin/.config/git/config', 1, None, ('git st', '/home/martin/.config/git/config', 1, None, '',
""" """
fatal: bad config file line 1 in /home/martin/.config/git/config fatal: bad config file line 1 in /home/martin/.config/git/config
"""), """),
('node fuck.js asdf qwer', '/Users/pablo/Workspace/barebones/fuck.js', '2', 5, ('node fuck.js asdf qwer', '/Users/pablo/Workspace/barebones/fuck.js', '2', 5, '',
""" """
/Users/pablo/Workspace/barebones/fuck.js:2 /Users/pablo/Workspace/barebones/fuck.js:2
conole.log(arg); // this should read console.log(arg); conole.log(arg); // this should read console.log(arg);
@ -153,35 +153,63 @@ ReferenceError: conole is not defined
at startup (node.js:129:16) at startup (node.js:129:16)
at node.js:814:3 at node.js:814:3
"""), """),
('pep8', './tests/rules/test_systemctl.py', 17, 80,
"""
./tests/rules/test_systemctl.py:17:80: E501 line too long (93 > 79 characters)
./tests/rules/test_systemctl.py:18:80: E501 line too long (103 > 79 characters)
./tests/rules/test_whois.py:20:80: E501 line too long (89 > 79 characters)
./tests/rules/test_whois.py:22:80: E501 line too long (83 > 79 characters)
""", ''),
('py.test', '/home/thefuck/tests/rules/test_fix_file.py', 218, None,
"""
monkeypatch = <_pytest.monkeypatch.monkeypatch object at 0x7fdb76a25b38>
test = ('fish a.sh', '/tmp/fix-error/a.sh', 2, None, '', "\\nfish: Unknown command 'foo'\\n/tmp/fix-error/a.sh (line 2): foo\\n ^\\n")
@pytest.mark.parametrize('test', tests)
@pytest.mark.usefixtures('no_memoize')
def test_get_new_command(monkeypatch, test):
> mocker.patch('os.path.isfile', return_value=True)
E NameError: name 'mocker' is not defined
/home/thefuck/tests/rules/test_fix_file.py:218: NameError
""", ''),
) )
@pytest.mark.parametrize('test', tests) @pytest.mark.parametrize('test', tests)
@pytest.mark.usefixtures('no_memoize')
def test_match(mocker, monkeypatch, test): def test_match(mocker, monkeypatch, test):
mocker.patch('os.path.isfile', return_value=True) mocker.patch('os.path.isfile', return_value=True)
monkeypatch.setenv('EDITOR', 'dummy_editor') monkeypatch.setenv('EDITOR', 'dummy_editor')
assert match(Command(stderr=test[4]), None) assert match(Command(stdout=test[4], stderr=test[5]), None)
@pytest.mark.parametrize('test', tests) @pytest.mark.parametrize('test', tests)
@pytest.mark.usefixtures('no_memoize')
def test_no_editor(mocker, monkeypatch, test): def test_no_editor(mocker, monkeypatch, test):
mocker.patch('os.path.isfile', return_value=True) mocker.patch('os.path.isfile', return_value=True)
if 'EDITOR' in os.environ: if 'EDITOR' in os.environ:
monkeypatch.delenv('EDITOR') monkeypatch.delenv('EDITOR')
assert not match(Command(stderr=test[4]), None) assert not match(Command(stdout=test[4], stderr=test[5]), None)
@pytest.mark.parametrize('test', tests) @pytest.mark.parametrize('test', tests)
@pytest.mark.usefixtures('no_memoize')
def test_not_file(mocker, monkeypatch, test): def test_not_file(mocker, monkeypatch, test):
mocker.patch('os.path.isfile', return_value=False) mocker.patch('os.path.isfile', return_value=False)
monkeypatch.setenv('EDITOR', 'dummy_editor') monkeypatch.setenv('EDITOR', 'dummy_editor')
assert not match(Command(stderr=test[4]), None) assert not match(Command(stdout=test[4], stderr=test[5]), None)
@pytest.mark.parametrize('test', tests) @pytest.mark.parametrize('test', tests)
def test_get_new_command(monkeypatch, test): @pytest.mark.usefixtures('no_memoize')
def test_get_new_command(mocker, monkeypatch, test):
mocker.patch('os.path.isfile', return_value=True)
monkeypatch.setenv('EDITOR', 'dummy_editor') monkeypatch.setenv('EDITOR', 'dummy_editor')
assert (get_new_command(Command(script=test[0], stderr=test[4]), None) == cmd = Command(script=test[0], stdout=test[4], stderr=test[5])
assert (get_new_command(cmd, None) ==
'dummy_editor {} +{} && {}'.format(test[1], test[2], test[0])) 'dummy_editor {} +{} && {}'.format(test[1], test[2], test[0]))

View File

@ -25,7 +25,7 @@ patterns = (
'^{file}: line {line}: ', '^{file}: line {line}: ',
# ghc, make, ruby, zsh: # ghc, make, ruby, zsh:
'^{file}:{line}:', '^{file}:{line}:',
# cargo, clang, gcc, go, rustc: # cargo, clang, gcc, go, pep8, rustc:
'^{file}:{line}:{col}', '^{file}:{line}:{col}',
# perl: # perl:
'at {file} line {line}', 'at {file} line {line}',
@ -45,7 +45,7 @@ patterns = [_make_pattern(p) for p in patterns]
def _search(stderr): def _search(stderr):
for pattern in patterns: for pattern in patterns:
m = re.search(pattern, stderr) m = re.search(pattern, stderr)
if m: if m and os.path.isfile(m.group('file')):
return m return m
@ -53,15 +53,15 @@ def match(command, settings):
if 'EDITOR' not in os.environ: if 'EDITOR' not in os.environ:
return False return False
m = _search(command.stderr) return _search(command.stderr) or _search(command.stdout)
return m and os.path.isfile(m.group('file'))
def get_new_command(command, settings): def get_new_command(command, settings):
m = _search(command.stderr) m = _search(command.stderr) or _search(command.stdout)
# Note: there does not seem to be a standard for columns, so they are just # Note: there does not seem to be a standard for columns, so they are just
# ignored for now # ignored for now
return shells.and_('{} {} +{}'.format(os.environ['EDITOR'], m.group('file'), m.group('line')), editor_call = '{} {} +{}'.format(os.environ['EDITOR'],
command.script) m.group('file'),
m.group('line'))
return shells.and_(editor_call, command.script)