Pythonプログラムの静的解析

# はじめに
Pythonで利用できる以下の便利なツールの簡単な使い方をまとめました。

- pipenv
- black
- flake8
- isort
- mypy

# pipenvとは
Pythonで開発するときにパッケージの管理や仮想環境の構築を簡単にやってくれます。
Node.jsのnpmのような感じです。

## 準備
1. pipenvのインストール

    ```bash
    pip install pipenv
    ```

2. pipfileの作成

    ```bash
    pipenv --python 3.8 # 3.8の部分は使用したいPythonのバージョンに変更可能
    ```
    `Pipfile`が作成されます。

3. 開発用パッケージのインストール
    開発時にしか使用しない静的解析ツールをインストールします。

    ```bash
    pipenv install --dev black --pre
    pipenv install --dev flake8 --pre
    pipenv install --dev isort --pre
    pipenv install --dev mypy --pre
    ```
    `Pipfile`の[dev-packages]に各パッケージが追加され、`Pipfile.lock`が作成/更新されます。

4. 本番利用のパッケージのインストール
    本番に利用するパッケージをインストールします。

    ```bash
    pipenv install requests --pre
    ```
    `Pipfile`の[packages]に各パッケージが追加され、`Pipfile.lock`が作成/更新されます。

## 環境構築
1. 仮想環境の構築
    `Pipfile.lock`の情報をもとに構築します。
    1. 開発環境の場合

        ```bash
        pipenv sync --dev
        ```

    2. 本番環境の場合

        ```bash
        pipenv sync
        ```

2. `Pipfile.lock`の更新（必要になった時でOK）

     ```bash
     pipenv install
     ```

2. 仮想環境に入る

    ```bash
    pipenv shell
    ```

3. インストールパッケージの確認

    ```bash
    pip list
    ```

    <details><summary>開発環境の結果（ここをクリック）</summary><div>

    ```bash
    Package           Version
    ----------------- ---------
    appdirs           1.4.4
    black             20.8b1
    certifi           2020.6.20
    chardet           3.0.4
    click             7.1.2
    flake8            3.8.3
    idna              2.10
    isort             5.5.3
    mccabe            0.6.1
    mypy              0.782
    mypy-extensions   0.4.3
    pathspec          0.8.0
    pip               20.1.1
    pycodestyle       2.6.0
    pyflakes          2.2.0
    regex             2020.9.27
    requests          2.24.0
    setuptools        49.6.0
    toml              0.10.1
    typed-ast         1.4.1
    typing-extensions 3.7.4.3
    urllib3           1.25.10
    wheel             0.35.1
    ```

    </div></details>

    <details><summary>本番環境の結果（ここをクリック）</summary><div>

    ```bash
    Package    Version
    ---------- ---------
    certifi    2020.6.20
    chardet    3.0.4
    idna       2.10
    pip        20.1.1
    requests   2.24.0
    setuptools 49.6.0
    urllib3    1.25.10
    wheel      0.35.1
    ```

    </div></details>

    ※本番環境は開発用のパッケージ及びその依存パッケージがインストールされていないことがわかります。

4. 仮想環境から出る

    ```bash
    exit
    ```

5. 仮想環境の削除

    ```bash
    pipenv --rm
    ```

# blackとは
blackはPythonのコードフォーマッターで自動でプログラムの書き方を修正してくれます。
Python標準のコーディング規約である[PEP8](https://pep8-ja.readthedocs.io/ja/latest/)にも準拠しています。

## 設定
1. blackの設定
    `pyproject.toml`で設定を定義できます。
    以下は一行の長さを120行までにして、フォーマットしないフォルダを指定しています。
    もっといろいろ設定したい場合は調べると出てくると思います。

    ```toml:pyproject.toml
    [tool.black]
    line-length=120
    exclude = '''
    /(
        .eggs
    | .git
    | .hg
    | .pytest_cache
    | .mypy_cache
    | .tox
    | .venv
    | build
    | dist
    )/
    '''
    ```

2. pipenvのスクリプトの設定
    `Pipfile`にscriptsを追加します。

    ```:Pipfile
    [scripts]
    black = "black ."  # --checkをつけるとフォーマットせずにチェックのみになります
    ```

## 実行

```bash
pipenv run black
```
pythonコードが自動でフォーマットされます

# flake8とは
[flake8](https://flake8.pycqa.org/en/latest/user/error-codes.html)は下記コードチェックツールのラッパーとなります。

- PyFlakes（pyflakes : コードのエラーチェック）
- pycodestyle（pycodestyle : PEP8に準拠しているかチェック）
- Ned Batchelder’s McCabe script（mccabe : 循環的複雑度のチェック）

※flake8はチェックのみでフォーマットはできません。

## 設定
1. flake8の設定
    `setup.cfg`で設定を定義できます。
    以下は一行の長さを120行までにして、チェックしないフォルダを指定しています。
    また、blackとの兼ね合いでE203,W503,W504は無視します。
    もっといろいろ設定したい場合は調べると出てくると思います。

    ```cfg:setup.cfg
    [flake8]
    exclude = .git, .tox, .venv, .eggs, build, dist, docs, tests
    max-line-length = 120
    ignore = E203,W503,W504
    ```

2. pipenvのスクリプトの設定
    `Pipfile`にscriptsを追加する。

    ```:Pipfile
    [scripts]
    flake8 = "flake8 ."
    ```

## 実行 

```bash
pipenv run flake8
```
pythonコードのチェックが行われます。

# isortとは
isortはインポートをアルファベット順にソートし、自動的にセクションに分割してくれます。

## 設定
1. isortの設定
    `setup.cfg`で設定を定義できます。
    以下は一行の長さを120行までにして、チェックしないフォルダを指定しています。
    もっといろいろ設定したい場合は調べると出てくると思います。

    ```cfg:setup.cfg
    [isort]
    line_length = 120
    skip = .git, .tox, .venv, .eggs, build, dist, docs
    include_trailing_comma = true
    multi_line_output = 3
    '''
    ```

2. pipenvのスクリプトの設定
    `Pipfile`にscriptsを追加する。

    ```:Pipfile
    [scripts]
    isort = "isort . --atomic" # --atomicを外すとフォーマットせずにチェックのみになります
    ```

## 実行

```bash
pipenv run isort
```
pythonコードが自動でフォーマットされます

# mypyとは
mypyは[PEP484](https://www.python.org/dev/peps/pep-0484/)に準拠したType Hintsが書けているかをチェックしてくれます。

## 設定
1. mypyの設定
    `setup.cfg`で設定を定義できます。
    以下はモジュールの型定義ファイル(stub)が無いことを無視し、型アノテーションを強制しています。
    もっといろいろ設定したい場合は調べると出てくると思います。

    ```cfg:setup.cfg
    [mypy]
    ignore_missing_imports = True
    disallow_untyped_defs = True
    ```

2. pipenvのスクリプトの設定
    `Pipfile`にscriptsを追加する。

    ```:Pipfile
    [scripts]
    mypy = "mypy ."
    ```

## 実行

```bash
pipenv run mypy
```
pythonコードのチェックが行われます。

# まとめ
これらのツールを使えば、Pythonを使用した開発の生産性が向上すると思います。
GitHubでコードを管理している場合は、以下をGitHub Actionsに設定しておけばPush時に自動で静的解析を行ってくれます。
エラーが出た場合は修正してPushし直しましょう。

<details><summary>.github/workflows/ci.yml（ここをクリック）</summary><div>

```yml:.github/workflows/ci.yml
name: Source Code Check
on: [push]
jobs:
  ci:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@master
      - name: Setup Python
        uses: actions/setup-python@v1
        with:
          python-version: '3.8'
      - name: Install Python Dependencies
        run: |
            python -m pip install --upgrade pip
            pip install pipenv
            pipenv sync --dev
      - name: Check with black
        run: pipenv run black
      - name: Check with flake8
        run: pipenv run flake8
      - name: Check with isort
        run: pipenv run isort
      - name: Check with mypy
        run: pipenv run mypy
```

</div></details>