配置yapf和isort的Vim与Pytest插件

VimPython,曾是一件流行的事,而今已经变得小众。 实际上,Vim仍然是Python开发的最佳利器之一,在很多方面,甚至优于PyCharm这样的IDE。

本文会基于Vim,介绍Python的风格统一与格式化方法。 并且,还会集成它们到pytest中去。

yapf简介

Golang的出现,改变了很多事。 它从Python中学走了编程风格、代码规范的固化,毕竟这关乎优雅。 Python的固化,跟多还停留在规范层面,如PEP8Golang从一开始就更进一步,用gofmt把这种固化做成了源文件格式化。

这固然带来了很多争议,但也带来了很多便利。 这些便利可以总结为一句话——结束了关于风格与规范的圣战。

yapf就是在gofmt的思路下,反馈给Python社区的礼物。 可以在YAPF Online Demo中,试用yapf并查看效果。

isort简介

yapf只专注于格式化,而不会去修改内容和顺序。 这在大部分区域都没问题,但在import区域,却显得不足。 在Pylint下,Pythonimport,也需要像Java那样有确定的顺序和分组,而yapf无能为力。 这就是isort的领域。

Isort demo

isort会把import分成标准库、第三方库、本地库三种,分别按字母排序。 格式化的结果,能自动满足Pylint的需要。 实际上,它本身就是Pylint的一个依赖。

更难得的是,isort自己提供了一个Wiki——isort Plugins · timothycrosley/isort Wiki——介绍了如何给几种流行的编辑环境配置插件。

安装与配置插件

pip install yapf isort

安装很简单,命令行使用也很方便,可以自行查看--help。 这里谈谈两种配置到Vim的两种方法。

vim-autoformat与vim-isort

以下为基于Vundle.vim的插件配置。

Plugin 'Chiel92/vim-autoformat'
let g:formatter_yapf_style = 'pep8'
Plugin 'fisadev/vim-isort'
noremap <F2> :Autoformat<CR>:Isort<CR>

vim-autoformat是一个通用的Vim格式化插件,它通过yapfPython提供支持。 vim-isort则是一个简单的,专为isort而生的插件。

最后,这里配置了作为格式化快捷键。

ale

以上的两个插件,无疑是能用的,孤也用了很长时间。 但比起ale来,在通用性上,还是略显不足。

Plugin 'w0rp/ale'
let g:ale_fixers = {
            \ 'python': ['yapf', 'isort'],
            \ }
noremap <F2> :ALEFix<CR>

以上配置为真实ale配置的一个简化版。 它比上一个插件方案看上去清晰多了,并且很容易兼容更多fixer、更多语言。

ale本身是一个很大的话题,这里不多介绍。)

配置

yapf配置与优先级:

  1. Specified on the command line
  2. In the [style] section of a .style.yapf file in either the current directory or one of its parent directories.
  3. In the [yapf] section of a setup.cfg file in either the current directory or one of its parent directories.
  4. In the ~/.config/yapf/style file in your home directory.

isort配置:

yapfisort,虽然都有还不错的默认配置,但也不能完全不调整。 尤其是,它们会格式化同一区域,会有一些冲突情况,比如最后一个import的comma(,)。 虽然它俩都有各自的配置文件与优先顺序,但本地配置中都支持setup.cfg。 所以,推荐在项目的setup.cfg中进行配置,固化在项目中。

[isort]
line_length = 79
multi_line_output = 3
include_trailing_comma = true

[yapf]
based_on_style = facebook
coalesce_brackets = true
dedent_closing_brackets = true

以上为孤的个人配置,至少解决了已知的comma冲突问题。

集成到pytest

既然谈到固化,就要有检查。 如果两个人开发同一个文件,一个人有做文件格式化,另一个没有,那么前者就经常会自动修改后者的代码,带来不必要的冲突; 如果两个人的格式化配置不一样,那么故事就更精彩了。

用相同的配置建立同一的标准,并且在每一次commit都去检查它,这才是完整的方案。 而pytest能实现这个方案。

setup.pytests_require中,或者requirements.txt中,添加pytest-isortpytest-yapf(推荐使用pytest-yapf3),并且安装它们。 然后,配置setup.cfg

[tool:pytest]
addopts = --verbose
          --isort
          --yapf
          ...
isort_ignore = setup.py

[isort]
...

[yapf]
...

这里,主要是添加--isort--yapf到已有的pytest配置中。 pytest-isort还支持isort_ignore,忽略不需要检查的文件; pytest-yapf还不支持这个功能。

配置完成后,一切尽在pytest

pytest-yapf3

现在推荐pytest-yapf3,这是孤写的插件。 由于pytest-yapf完成度不高,也不再维护,因此孤fork出来重写了一份。 3的意思,除了区分外,也是只支持Python 3的意思。 除原先的基本功能外,增加了以下改进:

结语

终于可以像写Golang那样去写Python了。

咦?那为什么……


相关笔记