VimでNeomake + Pylavaを使用したPython3の自動静的コード解析

はじめに

Python3のコーディングをVimで行う際にPEP8規約違反などを自動的に検出する方法をまとめます。

静的検証ツール Pylava の導入

Pythonの静的解析ツール Pylava を使用します。

github.com

Pylava では pycodestylePyFlakes などのツール群が利用可能であるため強力なコードチェックが可能です。
同様のツールとして Pylama がありますが、現状Python3.7に未対応です。
そこで Pylama からフォークした Pylava を選択しました。

github.com

github.com

Pylava では例えば次のような検証ができます。

  • pycodestyle : コードのPEP8規約準拠
  • pydocstyle : docstring のPEP257規約準拠
  • pyflakes : 論理的なエラー検知(未使用のモジュールや未定義の名前など)
  • Maccabe : McCabeの複雑度

インストール

$ pip install pylava

Pylavaの設定

pylava は実行時にカレントディレクトリから設定ファイルを探します。
pylava.ini を作成することで使用するlinterや無視する規約などを指定することができます。 pydocstyle はデフォルトだと無効なので明示的に記述する必要があります。

pylava.ini

[pylava]
skip = */settings.py
linters = pycodestyle,pydocstyle,pyflakes,mccabe
ignore = D203,D213,D401,D406

個人設定では ignore には以下のエラーコードを指定しています。
PEP257では規約内で矛盾が生じている箇所があるため個人の好みやプロジェクト内のルールに従い選択が必要です。

エラーコード エラーメッセージ
D203 1 blank line required before class docstring
D213 Multi-line docstring summary should start at the second line
D401 First line should be in imperative mood
D406 Section name should end with a newline

Pylavaの動作確認

例として次のサンプルプログラムを用意します。
使用していない sys のimportが行われている等の不備に気付くかと思います。

sample.py

import sys

def plus(a, b):
    print(a + b)

plus(1,2)

sample.py は1と2を足して3を出力するだけの単純なプログラムです。

$ python sample.py 
3

このままでも実行可能ですが、 pylava を実行することで改善点が多々あることが検知できます。

$ pylava
sample.py:1:1: D100 Missing docstring in public module [pydocstyle]
sample.py:1:1: W0611 'sys' imported but unused [pyflakes]
sample.py:3:1: E302 expected 2 blank lines, found 1 [pycodestyle]
sample.py:3:1: D103 Missing docstring in public function [pydocstyle]
sample.py:6:1: E305 expected 2 blank lines after class or function definition, found 1 [pycodestyle]
sample.py:6:7: E231 missing whitespace after ',' [pycodestyle]

VimでPylavaを自動実行

Neomakeの導入

コーディング後に都度 pylava を実行するのは手間なのでVim上で自動的にエラー検知を可能にします。 pylavaの自動実行にはVimプラグイン neomake を使用します。

github.com

dein.toml

[[plugins]]
repo = 'neomake/neomake'

Neomakeの設定

Neovimの場合は .init.vimVimの場合は .vimrcNeomake から Pylava を使用するための設定を記述します。

.init.vim(.vimrc)

call neomake#config#set('ft.python.pylama.exe', 'pylava')
call neomake#configure#automake('nrwi', 100)
let g:neomake_open_list = 2
let g:neomake_python_enabled_makers = ['pylama']
let g:neomake_python_pylama_maker = {
        \ 'args': ['--format', 'parsable', '-o', '~/pylava.ini'],
        \ 'errorformat': '%f:%l:%c: [%t] %m',
        \ 'postprocess': function('neomake#makers#ft#python#PylamaEntryProcess'),
        \ 'output_stream': 'stdout',
        \ 'exe': '/usr/local/bin/pylava'
        \ }

特に注意が必要な点として、 pylava を 使用するためには次の設定が必要です。

.init.vim(.vimrc)

call neomake#config#set('ft.python.pylama.exe', 'pylava')

github.com

また前述の pylava.iniVimからも共有したいので、 args には pylava -o ~/pylava.ini を指定しています(設定ファイルのパスは適宜変更してください)。

.init.vim(.vimrc)

let g:neomake_python_pylama_maker = {
        \ 'args': ['--format', 'parsable', '-o', '~/pylava.ini'],
        ...

exe には pylava のパスを指定します。
conda などで導入してある pylava を使用したい場合にもこちらで指定が可能です。

.init.vim(.vimrc)

let g:neomake_python_pylama_maker = {
        ...
        \ 'exe': '/usr/local/bin/pylava'
        \ }

エラーの一覧はロケーションリストに出力されるため、 エラー箇所への移動を簡単にするためにマッピングを設定します。

.init.vim(.vimrc)

map <C-n> :lnext<CR>
map <C-p> :lprev<CR>

動作確認

このようにしてVimから離れることなくコードの質を高めることができます。

f:id:hiroki-sawano:20181111145649g:plain