From 49ccfb1a00e09f6757b6e597883c95a34d612771 Mon Sep 17 00:00:00 2001
From: w0rp <devw0rp@gmail.com>
Date: Fri, 17 Nov 2017 18:11:22 +0000
Subject: Fix #516 - Add support for pyflakes for Python

---
 ale_linters/python/pyflakes.vim                    | 38 +++++++++++++++++
 .../with_virtualenv/env/Scripts/pyflakes.exe       |  0
 .../python_paths/with_virtualenv/env/bin/pyflakes  |  0
 .../test_pyflakes_command_callback.vader           | 49 ++++++++++++++++++++++
 test/handler/test_pyflakes_handler.vader           | 24 +++++++++++
 5 files changed, 111 insertions(+)
 create mode 100644 ale_linters/python/pyflakes.vim
 create mode 100755 test/command_callback/python_paths/with_virtualenv/env/Scripts/pyflakes.exe
 create mode 100755 test/command_callback/python_paths/with_virtualenv/env/bin/pyflakes
 create mode 100644 test/command_callback/test_pyflakes_command_callback.vader
 create mode 100644 test/handler/test_pyflakes_handler.vader

diff --git a/ale_linters/python/pyflakes.vim b/ale_linters/python/pyflakes.vim
new file mode 100644
index 00000000..b4a0b5f9
--- /dev/null
+++ b/ale_linters/python/pyflakes.vim
@@ -0,0 +1,38 @@
+" Author: w0rp <devw0rp@gmail.com>
+" Description: pyflakes for python files
+
+call ale#Set('python_pyflakes_executable', 'pyflakes')
+call ale#Set('python_pyflakes_use_global', 0)
+
+function! ale_linters#python#pyflakes#GetExecutable(buffer) abort
+    return ale#python#FindExecutable(a:buffer, 'python_pyflakes', ['pyflakes'])
+endfunction
+
+function! ale_linters#python#pyflakes#GetCommand(buffer) abort
+    let l:executable = ale_linters#python#pyflakes#GetExecutable(a:buffer)
+
+    return ale#Escape(l:executable) . ' %t'
+endfunction
+
+function! ale_linters#python#pyflakes#Handle(buffer, lines) abort
+    let l:pattern = '\v^[a-zA-Z]?:?[^:]+:(\d+):(\d+)?:? (.+)$'
+    let l:output = []
+
+    for l:match in ale#util#GetMatches(a:lines, l:pattern)
+        call add(l:output, {
+        \   'lnum': l:match[1] + 0,
+        \   'col': l:match[2] + 0,
+        \   'text': l:match[3],
+        \})
+    endfor
+
+    return l:output
+endfunction
+
+call ale#linter#Define('python', {
+\   'name': 'pyflakes',
+\   'executable_callback': 'ale_linters#python#pyflakes#GetExecutable',
+\   'command_callback': 'ale_linters#python#pyflakes#GetCommand',
+\   'callback': 'ale_linters#python#pyflakes#Handle',
+\   'output_stream': 'both',
+\})
diff --git a/test/command_callback/python_paths/with_virtualenv/env/Scripts/pyflakes.exe b/test/command_callback/python_paths/with_virtualenv/env/Scripts/pyflakes.exe
new file mode 100755
index 00000000..e69de29b
diff --git a/test/command_callback/python_paths/with_virtualenv/env/bin/pyflakes b/test/command_callback/python_paths/with_virtualenv/env/bin/pyflakes
new file mode 100755
index 00000000..e69de29b
diff --git a/test/command_callback/test_pyflakes_command_callback.vader b/test/command_callback/test_pyflakes_command_callback.vader
new file mode 100644
index 00000000..30a106c8
--- /dev/null
+++ b/test/command_callback/test_pyflakes_command_callback.vader
@@ -0,0 +1,49 @@
+Before:
+  Save g:ale_python_pyflakes_executable
+  Save g:ale_python_pyflakes_use_global
+
+  unlet! g:ale_python_pyflakes_executable
+  unlet!  g:ale_python_pyflakes_use_global
+
+  let b:bin_dir = has('win32') ? 'Scripts' : 'bin'
+
+  call ale#test#SetDirectory('/testplugin/test/command_callback')
+
+  runtime ale_linters/python/pyflakes.vim
+
+After:
+  Restore
+
+  unlet! b:bin_dir
+  unlet! b:executable
+
+  call ale#test#RestoreDirectory()
+  call ale#linter#Reset()
+
+Execute(The pyflakes command callback should return default string):
+  AssertEqual ale#Escape('pyflakes') . ' %t',
+  \ ale_linters#python#pyflakes#GetCommand(bufnr(''))
+
+Execute(The pyflakes executable should be configurable):
+  let g:ale_python_pyflakes_executable = '~/.local/bin/pyflakes'
+
+  AssertEqual ale#Escape('~/.local/bin/pyflakes') . ' %t',
+  \ ale_linters#python#pyflakes#GetCommand(bufnr(''))
+
+Execute(The pyflakes executable should be run from the virtualenv path):
+  call ale#test#SetFilename('python_paths/with_virtualenv/subdir/foo/bar.py')
+
+  let b:executable = ale#path#Winify(
+  \ g:dir . '/python_paths/with_virtualenv/env/' . b:bin_dir . '/pyflakes'
+  \)
+
+  AssertEqual ale#Escape(b:executable) . ' %t',
+  \ ale_linters#python#pyflakes#GetCommand(bufnr(''))
+
+Execute(You should be able to override the pyflakes virtualenv lookup):
+  call ale#test#SetFilename('python_paths/with_virtualenv/subdir/foo/bar.py')
+
+  let g:ale_python_pyflakes_use_global = 1
+
+  AssertEqual ale#Escape('pyflakes') . ' %t',
+  \ ale_linters#python#pyflakes#GetCommand(bufnr(''))
diff --git a/test/handler/test_pyflakes_handler.vader b/test/handler/test_pyflakes_handler.vader
new file mode 100644
index 00000000..ab4fab49
--- /dev/null
+++ b/test/handler/test_pyflakes_handler.vader
@@ -0,0 +1,24 @@
+Before:
+  runtime ale_linters/python/pyflakes.vim
+
+After:
+  call ale#linter#Reset()
+
+Execute(The pyflakes handler should handle basic errors):
+  AssertEqual
+  \ [
+  \   {
+  \     'lnum': 1,
+  \     'col': 0,
+  \     'text': 'undefined name ''foo''',
+  \   },
+  \   {
+  \     'lnum': 1,
+  \     'col': 7,
+  \     'text': 'invalid syntax',
+  \   },
+  \ ],
+  \ ale_linters#python#pyflakes#Handle(bufnr(''), [
+  \   'test.py:1: undefined name ''foo''',
+  \   'test.py:1:7: invalid syntax',
+  \ ])
-- 
cgit v1.2.3