mirror of
				https://github.com/nvbn/thefuck.git
				synced 2025-10-30 06:34:09 +00: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:
		| @@ -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])) | ||||||
|   | |||||||
| @@ -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) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user