【pysen README和訳】: あの「Preferred Networks」が作ったpython linter/formatter 管理アプリ「pysen」のREADMEを和訳してみた

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](https://github.com/pfnet/pysen)のREADME.mdには英語のドキュメントしかなかったので、和訳したのが以下です。（執筆時 2021/03/29）

[参考](https://tech.preferred.jp/ja/blog/pysen-is-the-new-sempai/)

![イメージ](https://github.com/pfnet/pysen/raw/main/assets/imgs/pysen.gif?raw=true)

# 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](https://github.com/pfnet/pysen/blob/102a6bd67644faa5ef3f766ea74cc8415988cac3/setup.py#L44)を確認してください。`pip install pysen[lint]`によるlinterのバージョン管理は**非推奨**です。
- pysenはlintだけに限って作られたものではありません。是非、「[プラグイン](https://github.com/pfnet/pysen/blob/main/README.md#create-a-plugin-to-customize-pysen)」を見て詳細を確認してみてください。

# インストール方法
[訳注]以下のいずれかを使用してください。ただし、pipは非推奨です。

```bash
# 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`に記入してみてください。

```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 = ["."]
```
次に、次のコマンドを実行します。

```bash
$ pysen run lint
$ pysen run format  # ここでformatter(black, isort)を使ったコードの自動修正を試みます
```

これでお終りです！

pysenは特定のlinter（black, isort, mypy, flake8）の設定ファイルを生成し、適切に実行します。`pyproject.toml`に関して、より詳細を知りたい場合は`pysen/pyproject_model.py`を参照してください。

セットアップ用のコマンドはあなたのpythonのパッケージに追加することも可能です。次のコードを、あなたのパッケージ内の`setup.py`に追記して、実行してみてください。

```python
import pysen
setup = pysen.setup_from_pyproject(__file__)
```

```bash
$ python setup.py lint
```
また、設定をカスタマイズしたり、pysenを拡張するためのPythonインターフェースも提供しています。詳しい内容は以下を参照してください。
- Pythonを使った設定例：`examples/advanced_example/config.py` [訳注] 3/29現在このファイルは存在しません。おそらく`lint.py`のこと
- pysenのプラグイン例: `examples/plugin_example/plugin.py`

# どう動いているか？: 設定ファイルのディレクトリ
水面下では、pysenが動くときはlinterに使われるファイルを一時的に生成しています。もし、このファイルをディスクに取っておきたい場合（例えば、エディタで使いたいときなど）、以下のコマンドを実行して保存先を指定してください。

```bash
$ pysen generate [保存先ディレクトリ]
```
`pysen run`実行時に、pysenの使用する設定ディレクトリを指定することも可能です。次のセクションを`pyproject.toml`に追加してください。

```toml
[tool.pysen-cli]
settings_dir = "path/to/generate/settings"
```

指定したディレクトリが既に設定ファイルを含んでいた場合、pysenはマージします。よって、`settings_dir`を指定しなかった時と異なる挙動になるかもしれません。

このオプションはpysenのCLIを介して使用する場合のみ適用されることに注意してください。pre-commitやsetuptoolsを使用する場合は、引数に`settings_dir`を指定する必要があります。

# Tips: IDE/テキストエディタ との統合
[訳注] 私がvimやemacsに明るくないので訳がおかしな箇所があるかもしれません。分かりづらい箇所あれば[原文](https://github.com/pfnet/pysen#tips-ide--text-editor-integration)をお読みください（修正歓迎です)
## 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`でも動作します。

実行結果は以下のようになります。
![vim pysen](https://github.com/pfnet/pysen/raw/main/assets/imgs/pysen_vim.gif?raw=true)

## Emacs
[Comliation mode](https://www.gnu.org/software/emacs/manual/html_node/emacs/Compilation-Mode.html)を参照してください。
以下はpythonのフックの例です。

```emacs-lisp
(add-hook 'python-mode-hook
    (lambda ()
        (set (make-local-variable 'compile-command)
            (concat "pysen run_files lint --error-format gnu  " buffer-file-name))))
```

## VSCode
[設定例](https://github.com/pfnet/pysen/blob/main/assets/vscode/tasks.json)のjsonを参考にしてみてください。実行すると、PROBLEMSウィンドウに以下のようなエラーが表示されます。
![vscode エラー](https://github.com/pfnet/pysen/blob/main/assets/imgs/pysen_vscode.jpg?raw=true)

**※注意※**
VSCodeの拡張機能からflake8のようなlinterを別途導入していた場合、重複してエラーが出力される可能性があります。pysenはすべてのファイルをチェックし時間がかかる可能性があります。よって、大規模なプロジェクトにおいて、ファイルの変更をトリガーにしてpysenを実行することは推奨しておりません。


# pysenの設定

pysenを設定するための方法は2つあります。

- 1つ目の方法は、`project.toml`の`[tool.pysen.lint]`セクションに書く方法です。この方法は最もシンプルな方法ですが、設定できる事項は限定的です。
- 2つ目の方法は、pysenを直接設定するpythonのスクリプトを書く方法です。もし、pysenのコマンドライン引数やpysenの挙動、pysenの生成する設定ファイルをカスタマイズしたい場合、この方法を使うことを推奨します。より詳しい例は[`pysen/examples`](https://github.com/pfnet/pysen/tree/main/examples)を参照してください。

## pyproject.toml で設定する場合
最新のものは`pysen/pyproject_model.py`を参照してください。[訳注]3/29現在、参照先がありませんでした。[`pysen/project.toml`](https://github.com/pfnet/pysen/blob/main/pyproject.toml)を参照すれば良いと思います。

以下は、基本的な設定例になります。

```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`](https://github.com/pfnet/pysen/tree/main/examples/plugin_example)を参照してください。

# 開発
私たちの開発環境を運用したい場合は`pipenv`が必要になります.

- 環境構築

```bash
# setup your environment
$ pipenv sync
# activate the environment
$ pipenv shell
```

- `Pipfile.lock`の依存関係の更新

```bash
$ pipenv lock --pre
```

- 全テストの実行

```bash
$ pipenv run tox
```

# Contributing
pysenの公開レポジトリはPreferred Networksのプライベートレポジトリのミラーです。現在、いかなるプルリクエストも受ける予定はありません。意欲のある開発者様はフォークしてからパッチを適用されることを推奨いたします。

また、私たちの人的リソースにも限りがあるため、Preferred Networks特有の要求を満たす開発を優先せざるを得ないときがあります。そのため、Issueを当面の間、閉鎖致します。心苦しいことではありますが、すべての質問、トラブルシューティング、feature request、バグレポートはすべて`dev/null`にダイレクトします。