summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorw0rp <w0rp@users.noreply.github.com>2019-01-26 21:41:40 +0000
committerGitHub <noreply@github.com>2019-01-26 21:41:40 +0000
commita47deeae40d7deda5f237145b7496943bde913ef (patch)
tree08d30dccc53673430507fcd99385f3f550e2b729
parent452460b8cdff8b2809d0226b60183dbda5ae605d (diff)
parent0a5de2b42b3b8774b7aa12f028544ac3f81b8830 (diff)
downloadale-a47deeae40d7deda5f237145b7496943bde913ef.zip
Merge pull request #2250 from m-pilia/bandit
Add bandit linter for Python
-rw-r--r--README.md2
-rw-r--r--ale_linters/python/bandit.vim58
-rw-r--r--doc/ale-python.txt39
-rw-r--r--doc/ale.txt3
-rw-r--r--test/command_callback/test_bandit_command_callback.vader49
-rw-r--r--test/handler/test_bandit_handler.vader42
6 files changed, 191 insertions, 2 deletions
diff --git a/README.md b/README.md
index 9eebf5d1..17b243d0 100644
--- a/README.md
+++ b/README.md
@@ -175,7 +175,7 @@ formatting.
| proto | [protoc-gen-lint](https://github.com/ckaznocha/protoc-gen-lint) |
| Pug | [pug-lint](https://github.com/pugjs/pug-lint) |
| Puppet | [languageserver](https://github.com/lingua-pupuli/puppet-editor-services), [puppet](https://puppet.com), [puppet-lint](https://puppet-lint.com) |
-| Python | [autopep8](https://github.com/hhatto/autopep8), [black](https://github.com/ambv/black), [flake8](http://flake8.pycqa.org/en/latest/), [isort](https://github.com/timothycrosley/isort), [mypy](http://mypy-lang.org/), [prospector](https://github.com/PyCQA/prospector), [pycodestyle](https://github.com/PyCQA/pycodestyle), [pydocstyle](https://www.pydocstyle.org/), [pyls](https://github.com/palantir/python-language-server), [pyre](https://github.com/facebook/pyre-check), [pylint](https://www.pylint.org/) !!, [vulture](https://github.com/jendrikseipp/vulture) !!, [yapf](https://github.com/google/yapf) |
+| Python | [autopep8](https://github.com/hhatto/autopep8), [bandit](https://github.com/PyCQA/bandit), [black](https://github.com/ambv/black), [flake8](http://flake8.pycqa.org/en/latest/), [isort](https://github.com/timothycrosley/isort), [mypy](http://mypy-lang.org/), [prospector](https://github.com/PyCQA/prospector), [pycodestyle](https://github.com/PyCQA/pycodestyle), [pydocstyle](https://www.pydocstyle.org/), [pyls](https://github.com/palantir/python-language-server), [pyre](https://github.com/facebook/pyre-check), [pylint](https://www.pylint.org/) !!, [vulture](https://github.com/jendrikseipp/vulture) !!, [yapf](https://github.com/google/yapf) |
| QML | [qmlfmt](https://github.com/jesperhh/qmlfmt), [qmllint](https://github.com/qt/qtdeclarative/tree/5.11/tools/qmllint) |
| R | [lintr](https://github.com/jimhester/lintr) |
| Racket | [raco](https://docs.racket-lang.org/raco/) |
diff --git a/ale_linters/python/bandit.vim b/ale_linters/python/bandit.vim
new file mode 100644
index 00000000..1b5a84a4
--- /dev/null
+++ b/ale_linters/python/bandit.vim
@@ -0,0 +1,58 @@
+" Author: Martino Pilia <martino.pilia@gmail.com>
+" Description: bandit linting for python files
+
+call ale#Set('python_bandit_executable', 'bandit')
+call ale#Set('python_bandit_options', '')
+call ale#Set('python_bandit_use_global', get(g:, 'ale_use_global_executables', 0))
+call ale#Set('python_bandit_auto_pipenv', 0)
+
+function! ale_linters#python#bandit#GetExecutable(buffer) abort
+ if (ale#Var(a:buffer, 'python_auto_pipenv') ||
+ \ ale#Var(a:buffer, 'python_bandit_auto_pipenv'))
+ \ && ale#python#PipenvPresent(a:buffer)
+ return 'pipenv'
+ endif
+
+ return ale#python#FindExecutable(a:buffer, 'python_bandit', ['bandit'])
+endfunction
+
+function! ale_linters#python#bandit#GetCommand(buffer) abort
+ let l:executable = ale_linters#python#bandit#GetExecutable(a:buffer)
+ let l:flags = ' --format custom'
+ \ . ' --msg-template "{line}:{test_id}:{severity}:{msg}" '
+
+ let l:exec_args = l:executable =~? 'pipenv$'
+ \ ? ' run bandit'
+ \ : ''
+
+ return ale#Escape(l:executable) . l:exec_args
+ \ . l:flags
+ \ . ale#Pad(ale#Var(a:buffer, 'python_bandit_options'))
+ \ . ' -'
+endfunction
+
+function! ale_linters#python#bandit#Handle(buffer, lines) abort
+ " Custom format defined in GetCommand via --msg-template
+ let l:pattern = '\v^([0-9]+):(B[0-9]+):([A-Z]+):(.*)$'
+ let l:severity = {'LOW': 'I', 'MEDIUM': 'W', 'HIGH': 'E'}
+ let l:output = []
+
+ for l:match in ale#util#GetMatches(a:lines, l:pattern)
+ call add(l:output, {
+ \ 'bufnr': a:buffer,
+ \ 'lnum': str2nr(l:match[1]),
+ \ 'code': l:match[2],
+ \ 'type': l:severity[l:match[3]],
+ \ 'text': l:match[4],
+ \})
+ endfor
+
+ return l:output
+endfunction
+
+call ale#linter#Define('python', {
+\ 'name': 'bandit',
+\ 'executable_callback': 'ale_linters#python#bandit#GetExecutable',
+\ 'command_callback': 'ale_linters#python#bandit#GetCommand',
+\ 'callback': 'ale_linters#python#bandit#Handle',
+\})
diff --git a/doc/ale-python.txt b/doc/ale-python.txt
index 3d355bc6..175216f6 100644
--- a/doc/ale-python.txt
+++ b/doc/ale-python.txt
@@ -66,6 +66,45 @@ g:ale_python_autopep8_use_global *g:ale_python_autopep8_use_global*
===============================================================================
+bandit *ale-python-bandit*
+
+g:ale_python_bandit_executable *g:ale_python_bandit_executable*
+ *b:ale_python_bandit_executable*
+ Type: |String|
+ Default: `'bandit'`
+
+ See |ale-integrations-local-executables|
+
+ Set this to `'pipenv'` to invoke `'pipenv` `run` `bandit'`.
+
+
+g:ale_python_bandit_options *g:ale_python_bandit_options*
+ *b:ale_python_bandit_options*
+ Type: |String|
+ Default: `''`
+
+ This variable can be changed to add command-line arguments to the
+ bandit invocation.
+
+
+g:ale_python_bandit_use_global *g:ale_python_bandit_use_global*
+ *b:ale_python_bandit_use_global*
+ Type: |Number|
+ Default: `get(g:, 'ale_use_global_executables', 0)`
+
+ See |ale-integrations-local-executables|
+
+
+g:ale_python_bandit_auto_pipenv *g:ale_python_bandit_auto_pipenv*
+ *b:ale_python_bandit_auto_pipenv*
+ Type: |Number|
+ Default: `0`
+
+ Detect whether the file is inside a pipenv, and set the executable to `pipenv`
+ if true. This is overridden by a manually-set executable.
+
+
+===============================================================================
black *ale-python-black*
g:ale_python_black_executable *g:ale_python_black_executable*
diff --git a/doc/ale.txt b/doc/ale.txt
index e0de8d1e..580effc7 100644
--- a/doc/ale.txt
+++ b/doc/ale.txt
@@ -257,6 +257,7 @@ CONTENTS *ale-contents*
cython..............................|ale-pyrex-cython|
python................................|ale-python-options|
autopep8............................|ale-python-autopep8|
+ bandit..............................|ale-python-bandit|
black...............................|ale-python-black|
flake8..............................|ale-python-flake8|
isort...............................|ale-python-isort|
@@ -484,7 +485,7 @@ Notes:
* proto: `protoc-gen-lint`
* Pug: `pug-lint`
* Puppet: `languageserver`, `puppet`, `puppet-lint`
-* Python: `autopep8`, `black`, `flake8`, `isort`, `mypy`, `prospector`, `pycodestyle`, `pydocstyle`, `pyls`, `pyre`, `pylint`!!, `vulture`!!, `yapf`
+* Python: `autopep8`, `bandit`, `black`, `flake8`, `isort`, `mypy`, `prospector`, `pycodestyle`, `pydocstyle`, `pyls`, `pyre`, `pylint`!!, `vulture`!!, `yapf`
* QML: `qmlfmt`, `qmllint`
* R: `lintr`
* Racket: `raco`
diff --git a/test/command_callback/test_bandit_command_callback.vader b/test/command_callback/test_bandit_command_callback.vader
new file mode 100644
index 00000000..5d1e6fd3
--- /dev/null
+++ b/test/command_callback/test_bandit_command_callback.vader
@@ -0,0 +1,49 @@
+Before:
+ call ale#assert#SetUpLinterTest('python', 'bandit')
+ let b:bandit_flags = ' --format custom '
+ \ . '--msg-template "{line}:{test_id}:{severity}:{msg}" '
+
+After:
+ call ale#assert#TearDownLinterTest()
+ unlet! b:bandit_flags
+
+Execute(The bandit command callback should return default string):
+ AssertLinter 'bandit',
+ \ ale#Escape('bandit')
+ \ . b:bandit_flags
+ \ . ' -'
+
+Execute(The bandit command callback should allow options):
+ let g:ale_python_bandit_options = '--configfile bandit.yaml'
+
+ AssertLinter 'bandit',
+ \ ale#Escape('bandit')
+ \ . b:bandit_flags
+ \ . ' --configfile bandit.yaml -'
+
+Execute(The bandit executable should be configurable):
+ let g:ale_python_bandit_executable = '~/.local/bin/bandit'
+
+ AssertLinter '~/.local/bin/bandit',
+ \ ale#Escape('~/.local/bin/bandit')
+ \ . b:bandit_flags
+ \ . ' -'
+
+Execute(Setting executable to 'pipenv' appends 'run bandit'):
+ let g:ale_python_bandit_executable = 'path/to/pipenv'
+
+ AssertLinter 'path/to/pipenv',
+ \ ale#Escape('path/to/pipenv')
+ \ . ' run bandit'
+ \ . b:bandit_flags
+ \ . ' -'
+
+Execute(Pipenv is detected when python_bandit_auto_pipenv is set):
+ let g:ale_python_bandit_auto_pipenv = 1
+ call ale#test#SetFilename('/testplugin/test/python_fixtures/pipenv/whatever.py')
+
+ AssertLinter 'pipenv',
+ \ ale#Escape('pipenv')
+ \ . ' run bandit'
+ \ . b:bandit_flags
+ \ . ' -'
diff --git a/test/handler/test_bandit_handler.vader b/test/handler/test_bandit_handler.vader
new file mode 100644
index 00000000..a2793a46
--- /dev/null
+++ b/test/handler/test_bandit_handler.vader
@@ -0,0 +1,42 @@
+Before:
+ runtime ale_linters/python/bandit.vim
+
+After:
+ call ale#linter#Reset()
+
+Execute(The bandit handler for Python should parse input correctly):
+ AssertEqual
+ \ [
+ \ {
+ \ 'bufnr': 0,
+ \ 'lnum': 2,
+ \ 'code': 'B404',
+ \ 'type': 'I',
+ \ 'text': 'Consider possible security implications associated with subprocess module.',
+ \ },
+ \ {
+ \ 'bufnr': 0,
+ \ 'lnum': 4,
+ \ 'code': 'B305',
+ \ 'type': 'W',
+ \ 'text': 'Use of insecure cipher mode cryptography.hazmat.primitives.ciphers.modes.ECB.',
+ \ },
+ \ {
+ \ 'bufnr': 0,
+ \ 'lnum': 6,
+ \ 'code': 'B609',
+ \ 'type': 'E',
+ \ 'text': 'Possible wildcard injection in call: subprocess.Popen',
+ \ },
+ \ ],
+ \ ale_linters#python#bandit#Handle(0, [
+ \ '[main] INFO profile include tests: None',
+ \ '[main] INFO profile exclude tests: None',
+ \ '[main] INFO cli include tests: None',
+ \ '[main] INFO cli exclude tests: None',
+ \ '[main] INFO running on Python 3.7.2',
+ \ '[node_visitor] INFO Unable to find qualified name for module: <stdin>',
+ \ '2:B404:LOW:Consider possible security implications associated with subprocess module.',
+ \ '4:B305:MEDIUM:Use of insecure cipher mode cryptography.hazmat.primitives.ciphers.modes.ECB.',
+ \ '6:B609:HIGH:Possible wildcard injection in call: subprocess.Popen',
+ \ ])