github: https://github.com/pfnet/pysen
はじめに
pysenはpreferred networksが公開するpython用のlinter/formatterの管理用アプリです。
複数人でコードを作成するとき、ある程度の可読性を確保するためにコーディングの約束を決めるものですが、それを自動的に判定/整形しようというのがlinter/formatterです。しかし、python用のlinter/formatterは複数あり、プロジェクトごとに様々で、linter/formatterの整備自体が形骸化するのが問題でした。そこで、preferred networksではlinter/formatterの管理用アプリを作って統合しようと作ったのがpysenです。
ただ、preferred networksのgithubのREADME.mdには英語のドキュメントしかなかったので、和訳したのが以下です。(執筆時 2021/03/29)
pysen って何?
「pysenは日々の開発用のツールを統合すること」を目標に提供されるツールです。
次のように使うことを想定しています。
-
pysen run lint
,pysen run format
を実行することで、プロジェクト内のすべてのコードをチェックして、フォーマットする -
pyproject.toml
内での数行書くことで標準化用のコードスタイルを定義する
pysenは各々のチームが蓄積した知見やコード、特にpythonのlinterについて中央集権的に共有します。実行はsetup.pyと私たちのコマンドラインツールのどちらからでも実行可能です。現在、以下のツールの設定ファイルを管理可能です。
- linter
- flake8
- isort
- mypy
- black
- utility
- (2021/03/29現在:予定)protoc
pysenで「できない」こと
- pysen自体はlinterではありません。
pysen run lint
は複数のpythonのlinterをpysenのより抽象的な設定ファイルに則って自動的に各々のlinterの設定を構築します。 - pysenはあなたの環境の依存性やパッケージを管理するものではありません。パッケージマネージャには
pipenv
やpoetry
を使い、pysenが使うツール(isort, mypy, flake8, blackなど)のバージョンを固定することを推奨します。pysenが対応するバージョンはsetup.py
内のextra_requires/lintを確認してください。pip install pysen[lint]
によるlinterのバージョン管理は非推奨です。 - pysenはlintだけに限って作られたものではありません。是非、「プラグイン」を見て詳細を確認してみてください。
インストール方法
[訳注]以下のいずれかを使用してください。ただし、pipは非推奨です。
# pip
pip install "pysen[lint]"
# pipenv
pipenv install --dev "pysen[lint]==0.9.1"
# poetry
poetry add -D pysen==0.9.1 -E lint
クイックスタート: pysenでのlinterの管理方法
まずは、あなたのpythonパッケージ内で、以下の設定をpysenの設定ファイルpyproject.toml
に記入してみてください。
[tool.pysen]
version = "0.9"
[tool.pysen.lint]
enable_black = true
enable_flake8 = true
enable_isort = true
enable_mypy = true
mypy_preset = "strict"
line_length = 88
py_version = "py37"
[[tool.pysen.lint.mypy_targets]]
paths = ["."]
次に、次のコマンドを実行します。
$ pysen run lint
$ pysen run format # ここでformatter(black, isort)を使ったコードの自動修正を試みます
これでお終りです!
pysenは特定のlinter(black, isort, mypy, flake8)の設定ファイルを生成し、適切に実行します。pyproject.toml
に関して、より詳細を知りたい場合はpysen/pyproject_model.py
を参照してください。
セットアップ用のコマンドはあなたのpythonのパッケージに追加することも可能です。次のコードを、あなたのパッケージ内のsetup.py
に追記して、実行してみてください。
import pysen
setup = pysen.setup_from_pyproject(__file__)
$ python setup.py lint
また、設定をカスタマイズしたり、pysenを拡張するためのPythonインターフェースも提供しています。詳しい内容は以下を参照してください。
- Pythonを使った設定例:
examples/advanced_example/config.py
[訳注] 3/29現在このファイルは存在しません。おそらくlint.py
のこと - pysenのプラグイン例:
examples/plugin_example/plugin.py
どう動いているか?: 設定ファイルのディレクトリ
水面下では、pysenが動くときはlinterに使われるファイルを一時的に生成しています。もし、このファイルをディスクに取っておきたい場合(例えば、エディタで使いたいときなど)、以下のコマンドを実行して保存先を指定してください。
$ pysen generate [保存先ディレクトリ]
pysen run
実行時に、pysenの使用する設定ディレクトリを指定することも可能です。次のセクションをpyproject.toml
に追加してください。
[tool.pysen-cli]
settings_dir = "path/to/generate/settings"
指定したディレクトリが既に設定ファイルを含んでいた場合、pysenはマージします。よって、settings_dir
を指定しなかった時と異なる挙動になるかもしれません。
このオプションはpysenのCLIを介して使用する場合のみ適用されることに注意してください。pre-commitやsetuptoolsを使用する場合は、引数にsettings_dir
を指定する必要があります。
Tips: IDE/テキストエディタ との統合
[訳注] 私がvimやemacsに明るくないので訳がおかしな箇所があるかもしれません。分かりづらい箇所あれば原文をお読みください(修正歓迎です)
vim
pysenの出力するエラーはクイックフィックスウィンドウに次のコードで加えることができます
:cex system("pysen run_files lint --error-format gnu ".expand('%:p'))
他にも、pysenをmakeprg
に設定する方法もあります
set makeprg=pysen\ run_files\ --error-format\ gnu\ lint\ %
そして、:make
を実行するとクイックフィックスウィンドウにエラーを表示できます。これは、:Dispatch
の代わりに:Make
を呼び出す限り、vim-dispatch
でも動作します。
Emacs
Comliation modeを参照してください。
以下はpythonのフックの例です。
(add-hook 'python-mode-hook
(lambda ()
(set (make-local-variable 'compile-command)
(concat "pysen run_files lint --error-format gnu " buffer-file-name))))
VSCode
設定例のjsonを参考にしてみてください。実行すると、PROBLEMSウィンドウに以下のようなエラーが表示されます。
※注意※
VSCodeの拡張機能からflake8のようなlinterを別途導入していた場合、重複してエラーが出力される可能性があります。pysenはすべてのファイルをチェックし時間がかかる可能性があります。よって、大規模なプロジェクトにおいて、ファイルの変更をトリガーにしてpysenを実行することは推奨しておりません。
pysenの設定
pysenを設定するための方法は2つあります。
- 1つ目の方法は、
project.toml
の[tool.pysen.lint]
セクションに書く方法です。この方法は最もシンプルな方法ですが、設定できる事項は限定的です。 - 2つ目の方法は、pysenを直接設定するpythonのスクリプトを書く方法です。もし、pysenのコマンドライン引数やpysenの挙動、pysenの生成する設定ファイルをカスタマイズしたい場合、この方法を使うことを推奨します。より詳しい例は
pysen/examples
を参照してください。
pyproject.toml で設定する場合
最新のものはpysen/pyproject_model.py
を参照してください。[訳注]3/29現在、参照先がありませんでした。pysen/project.toml
を参照すれば良いと思います。
以下は、基本的な設定例になります。
[tool.pysen]
version = "0.9"
[tool.pysen.lint]
enable_black = true
enable_flake8 = true
enable_isort = true
enable_mypy = true
mypy_preset = "strict"
line_length = 88
py_version = "py37"
isort_known_third_party = ["numpy"]
isort_known_first_party = ["pysen"]
mypy_ignore_packages = ["pysen.generated.*"]
mypy_path = ["stubs"]
[[tool.pysen.lint.mypy_targets]]
paths = [".", "tests/"]
[tool.pysen.lint.source]
includes = ["."]
include_globs = ["**/*.template"]
excludes = ["third_party/"]
exclude_globs = ["**/*_grpc.py"]
[tool.pysen.lint.mypy_modules."pysen.scripts"]
preset = "entry"
[tool.pysen.lint.mypy_modules."numpy"]
ignore_errors = true
プラグインを設計して、pysenをカスタマイズしよう
内製のツールや設定ファイルの管理、セットアップ用コマンドなどのためにプラグイン用インターフェースを用意しています。
より詳しい内容は、pysen/examples/plugin_example
を参照してください。
開発
私たちの開発環境を運用したい場合はpipenv
が必要になります.
- 環境構築
# setup your environment
$ pipenv sync
# activate the environment
$ pipenv shell
-
Pipfile.lock
の依存関係の更新
$ pipenv lock --pre
- 全テストの実行
$ pipenv run tox
Contributing
pysenの公開レポジトリはPreferred Networksのプライベートレポジトリのミラーです。現在、いかなるプルリクエストも受ける予定はありません。意欲のある開発者様はフォークしてからパッチを適用されることを推奨いたします。
また、私たちの人的リソースにも限りがあるため、Preferred Networks特有の要求を満たす開発を優先せざるを得ないときがあります。そのため、Issueを当面の間、閉鎖致します。心苦しいことではありますが、すべての質問、トラブルシューティング、feature request、バグレポートはすべてdev/null
にダイレクトします。